t_ptrace_wait.c revision 1.125
11.125Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.125 2019/06/11 23:30:05 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 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.125Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.125 2019/06/11 23:30:05 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.77Skamil#include <pthread.h>
471.1Skamil#include <sched.h>
481.1Skamil#include <signal.h>
491.124Skamil#include <spawn.h>
501.1Skamil#include <stdint.h>
511.1Skamil#include <stdio.h>
521.1Skamil#include <stdlib.h>
531.1Skamil#include <strings.h>
541.26Skamil#include <time.h>
551.1Skamil#include <unistd.h>
561.1Skamil
571.114Skamil#include <fenv.h>
581.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__
591.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
601.114Skamil#endif
611.114Skamil
621.121Smgorny#if defined(__i386__) || defined(__x86_64__)
631.121Smgorny#include <cpuid.h>
641.121Smgorny#include <x86/cpu_extended_state.h>
651.121Smgorny#endif
661.121Smgorny
671.1Skamil#include <atf-c.h>
681.1Skamil
691.1Skamil#include "h_macros.h"
701.1Skamil
711.1Skamil#include "t_ptrace_wait.h"
721.1Skamil#include "msg.h"
731.1Skamil
741.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
751.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
761.61Skre	sizeof(msg)) == 0)
771.1Skamil
781.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
791.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
801.61Skre	sizeof(msg)) == 0)
811.1Skamil
821.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
831.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
841.61Skre	sizeof(msg)) == 0)
851.1Skamil
861.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
871.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
881.61Skre	sizeof(msg)) == 0)
891.13Schristos
901.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
911.13Schristos    strerror(errno))
921.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
931.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
941.13Schristos
951.13Schristosstatic int debug = 0;
961.13Schristos
971.13Schristos#define DPRINTF(a, ...)	do  \
981.123Skamil	if (debug) \
991.123Skamil	printf("%s() %s:%d " a, __func__, __FILE__, __LINE__,  ##__VA_ARGS__); \
1001.13Schristos    while (/*CONSTCOND*/0)
1011.1Skamil
1021.110Skamil#ifndef TEST_VFORK_ENABLED
1031.109Skamil#define TEST_VFORK_ENABLED 0
1041.110Skamil#endif
1051.109Skamil
1061.34Skamil/// ----------------------------------------------------------------------------
1071.34Skamil
1081.33Skamilstatic void
1091.33Skamiltraceme_raise(int sigval)
1101.1Skamil{
1111.1Skamil	const int exitval = 5;
1121.1Skamil	pid_t child, wpid;
1131.1Skamil#if defined(TWAIT_HAVE_STATUS)
1141.1Skamil	int status;
1151.1Skamil#endif
1161.1Skamil
1171.45Skamil	struct ptrace_siginfo info;
1181.45Skamil	memset(&info, 0, sizeof(info));
1191.45Skamil
1201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1221.1Skamil	if (child == 0) {
1231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1251.1Skamil
1261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1281.1Skamil
1291.36Skamil		switch (sigval) {
1301.36Skamil		case SIGKILL:
1311.36Skamil			/* NOTREACHED */
1321.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1331.70Smrg			__unreachable();
1341.36Skamil		default:
1351.36Skamil			DPRINTF("Before exiting of the child process\n");
1361.36Skamil			_exit(exitval);
1371.36Skamil		}
1381.1Skamil	}
1391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1401.1Skamil
1411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1431.1Skamil
1441.36Skamil	switch (sigval) {
1451.36Skamil	case SIGKILL:
1461.36Skamil		validate_status_signaled(status, sigval, 0);
1471.36Skamil		break;
1481.36Skamil	default:
1491.36Skamil		validate_status_stopped(status, sigval);
1501.1Skamil
1511.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1521.61Skre			"child\n");
1531.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1541.61Skre			sizeof(info)) != -1);
1551.45Skamil
1561.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1571.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1581.61Skre			"si_errno=%#x\n",
1591.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1601.61Skre			info.psi_siginfo.si_errno);
1611.45Skamil
1621.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1631.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1641.45Skamil
1651.36Skamil		DPRINTF("Before resuming the child process where it left off "
1661.36Skamil		    "and without signal to be sent\n");
1671.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1681.1Skamil
1691.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1701.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1711.61Skre		    child);
1721.36Skamil		break;
1731.36Skamil	}
1741.1Skamil
1751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1771.1Skamil}
1781.1Skamil
1791.61Skre#define TRACEME_RAISE(test, sig)					\
1801.61SkreATF_TC(test);								\
1811.61SkreATF_TC_HEAD(test, tc)							\
1821.61Skre{									\
1831.61Skre	atf_tc_set_md_var(tc, "descr",					\
1841.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1851.61Skre}									\
1861.61Skre									\
1871.61SkreATF_TC_BODY(test, tc)							\
1881.61Skre{									\
1891.61Skre									\
1901.61Skre	traceme_raise(sig);						\
1911.33Skamil}
1921.33Skamil
1931.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1941.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1951.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1961.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1971.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1981.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1991.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
2001.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
2011.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
2021.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
2031.33Skamil
2041.34Skamil/// ----------------------------------------------------------------------------
2051.1Skamil
2061.1Skamilstatic void
2071.87Skamiltraceme_raisesignal_ignored(int sigignored)
2081.87Skamil{
2091.87Skamil	const int exitval = 5;
2101.87Skamil	const int sigval = SIGSTOP;
2111.87Skamil	pid_t child, wpid;
2121.87Skamil	struct sigaction sa;
2131.87Skamil#if defined(TWAIT_HAVE_STATUS)
2141.87Skamil	int status;
2151.87Skamil#endif
2161.87Skamil	struct ptrace_siginfo info;
2171.87Skamil
2181.87Skamil	memset(&info, 0, sizeof(info));
2191.87Skamil
2201.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2211.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2221.87Skamil	if (child == 0) {
2231.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2241.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2251.87Skamil
2261.87Skamil		memset(&sa, 0, sizeof(sa));
2271.87Skamil		sa.sa_handler = SIG_IGN;
2281.87Skamil		sigemptyset(&sa.sa_mask);
2291.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2301.87Skamil
2311.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2321.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2331.87Skamil
2341.87Skamil		DPRINTF("Before raising %s from child\n",
2351.87Skamil		    strsignal(sigignored));
2361.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2371.87Skamil
2381.87Skamil		DPRINTF("Before exiting of the child process\n");
2391.87Skamil		_exit(exitval);
2401.87Skamil	}
2411.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2421.87Skamil
2431.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2441.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2451.87Skamil
2461.87Skamil	validate_status_stopped(status, sigval);
2471.87Skamil
2481.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2491.87Skamil	SYSCALL_REQUIRE(
2501.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2511.87Skamil
2521.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2531.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2541.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2551.87Skamil	    info.psi_siginfo.si_errno);
2561.87Skamil
2571.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2581.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2591.87Skamil
2601.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2611.87Skamil	    "without signal to be sent\n");
2621.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2631.87Skamil
2641.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2651.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2661.87Skamil
2671.87Skamil	validate_status_stopped(status, sigignored);
2681.87Skamil
2691.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2701.87Skamil	SYSCALL_REQUIRE(
2711.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2721.87Skamil
2731.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2741.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2751.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2761.87Skamil	    info.psi_siginfo.si_errno);
2771.87Skamil
2781.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2791.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2801.87Skamil
2811.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2821.87Skamil	    "without signal to be sent\n");
2831.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2841.87Skamil
2851.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2861.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2871.87Skamil
2881.87Skamil	validate_status_exited(status, exitval);
2891.87Skamil
2901.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2911.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2921.87Skamil}
2931.87Skamil
2941.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2951.87SkamilATF_TC(test);								\
2961.87SkamilATF_TC_HEAD(test, tc)							\
2971.87Skamil{									\
2981.87Skamil	atf_tc_set_md_var(tc, "descr",					\
2991.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
3001.87Skamil	    "does not stop tracer from catching this raised signal");	\
3011.87Skamil}									\
3021.87Skamil									\
3031.87SkamilATF_TC_BODY(test, tc)							\
3041.87Skamil{									\
3051.87Skamil									\
3061.87Skamil	traceme_raisesignal_ignored(sig);				\
3071.87Skamil}
3081.87Skamil
3091.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
3101.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
3111.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
3121.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
3131.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
3141.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
3151.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3161.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3171.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3181.87Skamil
3191.87Skamil/// ----------------------------------------------------------------------------
3201.87Skamil
3211.87Skamilstatic void
3221.86Skamiltraceme_raisesignal_masked(int sigmasked)
3231.86Skamil{
3241.86Skamil	const int exitval = 5;
3251.86Skamil	const int sigval = SIGSTOP;
3261.86Skamil	pid_t child, wpid;
3271.86Skamil#if defined(TWAIT_HAVE_STATUS)
3281.86Skamil	int status;
3291.86Skamil#endif
3301.86Skamil	sigset_t intmask;
3311.86Skamil	struct ptrace_siginfo info;
3321.86Skamil
3331.86Skamil	memset(&info, 0, sizeof(info));
3341.86Skamil
3351.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3361.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3371.86Skamil	if (child == 0) {
3381.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3391.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3401.86Skamil
3411.86Skamil		sigemptyset(&intmask);
3421.86Skamil		sigaddset(&intmask, sigmasked);
3431.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3441.86Skamil
3451.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3461.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3471.86Skamil
3481.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3491.86Skamil		    strsignal(sigmasked));
3501.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3511.86Skamil
3521.86Skamil		DPRINTF("Before exiting of the child process\n");
3531.86Skamil		_exit(exitval);
3541.86Skamil	}
3551.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3561.86Skamil
3571.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3581.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3591.86Skamil
3601.86Skamil	validate_status_stopped(status, sigval);
3611.86Skamil
3621.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3631.86Skamil	SYSCALL_REQUIRE(
3641.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3651.86Skamil
3661.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3671.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3681.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3691.86Skamil	    info.psi_siginfo.si_errno);
3701.86Skamil
3711.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3721.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3731.86Skamil
3741.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3751.86Skamil	    "without signal to be sent\n");
3761.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3771.86Skamil
3781.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3791.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3801.86Skamil
3811.86Skamil	validate_status_exited(status, exitval);
3821.86Skamil
3831.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3841.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3851.86Skamil}
3861.86Skamil
3871.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3881.86SkamilATF_TC(test);								\
3891.86SkamilATF_TC_HEAD(test, tc)							\
3901.86Skamil{									\
3911.86Skamil	atf_tc_set_md_var(tc, "descr",					\
3921.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3931.86Skamil	    "stops tracer from catching this raised signal");		\
3941.86Skamil}									\
3951.86Skamil									\
3961.86SkamilATF_TC_BODY(test, tc)							\
3971.86Skamil{									\
3981.86Skamil									\
3991.86Skamil	traceme_raisesignal_masked(sig);				\
4001.86Skamil}
4011.86Skamil
4021.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4031.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
4041.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
4051.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
4061.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
4071.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
4081.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
4091.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
4101.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
4111.86Skamil
4121.86Skamil/// ----------------------------------------------------------------------------
4131.86Skamil
4141.86Skamilstatic void
4151.59Skamiltraceme_crash(int sig)
4161.59Skamil{
4171.59Skamil	pid_t child, wpid;
4181.59Skamil#if defined(TWAIT_HAVE_STATUS)
4191.59Skamil	int status;
4201.59Skamil#endif
4211.59Skamil	struct ptrace_siginfo info;
4221.61Skre
4231.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4241.71Skamil	if (sig == SIGILL)
4251.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4261.71Skamil#endif
4271.71Skamil
4281.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
4291.114Skamil		atf_tc_skip("FP exceptions are not supported");
4301.114Skamil
4311.59Skamil	memset(&info, 0, sizeof(info));
4321.59Skamil
4331.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4341.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4351.59Skamil	if (child == 0) {
4361.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4371.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4381.59Skamil
4391.59Skamil		DPRINTF("Before executing a trap\n");
4401.59Skamil		switch (sig) {
4411.59Skamil		case SIGTRAP:
4421.59Skamil			trigger_trap();
4431.59Skamil			break;
4441.59Skamil		case SIGSEGV:
4451.59Skamil			trigger_segv();
4461.59Skamil			break;
4471.59Skamil		case SIGILL:
4481.59Skamil			trigger_ill();
4491.59Skamil			break;
4501.59Skamil		case SIGFPE:
4511.59Skamil			trigger_fpe();
4521.59Skamil			break;
4531.59Skamil		case SIGBUS:
4541.59Skamil			trigger_bus();
4551.59Skamil			break;
4561.59Skamil		default:
4571.59Skamil			/* NOTREACHED */
4581.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4591.59Skamil		}
4601.59Skamil
4611.59Skamil		/* NOTREACHED */
4621.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4631.59Skamil	}
4641.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4651.59Skamil
4661.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4671.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4681.59Skamil
4691.59Skamil	validate_status_stopped(status, sig);
4701.59Skamil
4711.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4721.61Skre	SYSCALL_REQUIRE(
4731.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4741.59Skamil
4751.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4761.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4771.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4781.61Skre	    info.psi_siginfo.si_errno);
4791.59Skamil
4801.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4811.59Skamil	switch (sig) {
4821.59Skamil	case SIGTRAP:
4831.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4841.59Skamil		break;
4851.59Skamil	case SIGSEGV:
4861.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4871.59Skamil		break;
4881.71Skamil	case SIGILL:
4891.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
4901.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
4911.71Skamil		break;
4921.59Skamil	case SIGFPE:
4931.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4941.59Skamil		break;
4951.59Skamil	case SIGBUS:
4961.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
4971.59Skamil		break;
4981.59Skamil	}
4991.59Skamil
5001.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
5011.59Skamil
5021.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5031.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5041.59Skamil
5051.59Skamil	validate_status_signaled(status, SIGKILL, 0);
5061.59Skamil
5071.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5081.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5091.59Skamil}
5101.59Skamil
5111.61Skre#define TRACEME_CRASH(test, sig)					\
5121.61SkreATF_TC(test);								\
5131.61SkreATF_TC_HEAD(test, tc)							\
5141.61Skre{									\
5151.61Skre	atf_tc_set_md_var(tc, "descr",					\
5161.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
5171.61Skre}									\
5181.61Skre									\
5191.61SkreATF_TC_BODY(test, tc)							\
5201.61Skre{									\
5211.61Skre									\
5221.61Skre	traceme_crash(sig);						\
5231.59Skamil}
5241.59Skamil
5251.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5261.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5271.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5281.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5291.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5301.59Skamil
5311.59Skamil/// ----------------------------------------------------------------------------
5321.59Skamil
5331.59Skamilstatic void
5341.88Skamiltraceme_signalmasked_crash(int sig)
5351.88Skamil{
5361.89Skamil	const int sigval = SIGSTOP;
5371.88Skamil	pid_t child, wpid;
5381.88Skamil#if defined(TWAIT_HAVE_STATUS)
5391.88Skamil	int status;
5401.88Skamil#endif
5411.88Skamil	struct ptrace_siginfo info;
5421.88Skamil	sigset_t intmask;
5431.89Skamil	struct kinfo_proc2 kp;
5441.89Skamil	size_t len = sizeof(kp);
5451.89Skamil
5461.89Skamil	int name[6];
5471.89Skamil	const size_t namelen = __arraycount(name);
5481.89Skamil	ki_sigset_t kp_sigmask;
5491.88Skamil
5501.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5511.88Skamil	if (sig == SIGILL)
5521.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5531.88Skamil#endif
5541.88Skamil
5551.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
5561.114Skamil		atf_tc_skip("FP exceptions are not supported");
5571.114Skamil
5581.88Skamil	memset(&info, 0, sizeof(info));
5591.88Skamil
5601.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5611.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5621.88Skamil	if (child == 0) {
5631.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5641.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5651.88Skamil
5661.88Skamil		sigemptyset(&intmask);
5671.88Skamil		sigaddset(&intmask, sig);
5681.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5691.88Skamil
5701.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5711.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5721.89Skamil
5731.88Skamil		DPRINTF("Before executing a trap\n");
5741.88Skamil		switch (sig) {
5751.88Skamil		case SIGTRAP:
5761.88Skamil			trigger_trap();
5771.88Skamil			break;
5781.88Skamil		case SIGSEGV:
5791.88Skamil			trigger_segv();
5801.88Skamil			break;
5811.88Skamil		case SIGILL:
5821.88Skamil			trigger_ill();
5831.88Skamil			break;
5841.88Skamil		case SIGFPE:
5851.88Skamil			trigger_fpe();
5861.88Skamil			break;
5871.88Skamil		case SIGBUS:
5881.88Skamil			trigger_bus();
5891.88Skamil			break;
5901.88Skamil		default:
5911.88Skamil			/* NOTREACHED */
5921.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5931.88Skamil		}
5941.88Skamil
5951.88Skamil		/* NOTREACHED */
5961.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5971.88Skamil	}
5981.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5991.88Skamil
6001.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6011.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6021.88Skamil
6031.89Skamil	validate_status_stopped(status, sigval);
6041.89Skamil
6051.89Skamil	name[0] = CTL_KERN,
6061.89Skamil	name[1] = KERN_PROC2,
6071.89Skamil	name[2] = KERN_PROC_PID;
6081.89Skamil	name[3] = child;
6091.89Skamil	name[4] = sizeof(kp);
6101.89Skamil	name[5] = 1;
6111.89Skamil
6121.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6131.89Skamil
6141.89Skamil	kp_sigmask = kp.p_sigmask;
6151.89Skamil
6161.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6171.89Skamil	SYSCALL_REQUIRE(
6181.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6191.89Skamil
6201.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6211.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6221.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6231.89Skamil	    info.psi_siginfo.si_errno);
6241.89Skamil
6251.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6261.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6271.89Skamil
6281.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6291.89Skamil	    "without signal to be sent\n");
6301.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6311.89Skamil
6321.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6331.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6341.89Skamil
6351.88Skamil	validate_status_stopped(status, sig);
6361.88Skamil
6371.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6381.88Skamil	SYSCALL_REQUIRE(
6391.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6401.88Skamil
6411.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6421.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6431.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6441.88Skamil	    info.psi_siginfo.si_errno);
6451.88Skamil
6461.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6471.89Skamil
6481.89Skamil	DPRINTF("kp_sigmask="
6491.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6501.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6511.89Skamil	    kp_sigmask.__bits[3]);
6521.89Skamil
6531.89Skamil	DPRINTF("kp.p_sigmask="
6541.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6551.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6561.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6571.89Skamil
6581.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6591.89Skamil
6601.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6611.88Skamil	switch (sig) {
6621.88Skamil	case SIGTRAP:
6631.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6641.88Skamil		break;
6651.88Skamil	case SIGSEGV:
6661.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6671.88Skamil		break;
6681.88Skamil	case SIGILL:
6691.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
6701.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
6711.88Skamil		break;
6721.88Skamil	case SIGFPE:
6731.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6741.88Skamil		break;
6751.88Skamil	case SIGBUS:
6761.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6771.88Skamil		break;
6781.88Skamil	}
6791.88Skamil
6801.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6811.88Skamil
6821.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6831.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6841.88Skamil
6851.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6861.88Skamil
6871.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6881.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6891.88Skamil}
6901.88Skamil
6911.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6921.88SkamilATF_TC(test);								\
6931.88SkamilATF_TC_HEAD(test, tc)							\
6941.88Skamil{									\
6951.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6961.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6971.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6981.88Skamil}									\
6991.88Skamil									\
7001.88SkamilATF_TC_BODY(test, tc)							\
7011.88Skamil{									\
7021.88Skamil									\
7031.88Skamil	traceme_signalmasked_crash(sig);				\
7041.88Skamil}
7051.88Skamil
7061.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
7071.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
7081.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
7091.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
7101.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
7111.88Skamil
7121.88Skamil/// ----------------------------------------------------------------------------
7131.88Skamil
7141.88Skamilstatic void
7151.88Skamiltraceme_signalignored_crash(int sig)
7161.88Skamil{
7171.90Skamil	const int sigval = SIGSTOP;
7181.88Skamil	pid_t child, wpid;
7191.88Skamil#if defined(TWAIT_HAVE_STATUS)
7201.88Skamil	int status;
7211.88Skamil#endif
7221.88Skamil	struct sigaction sa;
7231.88Skamil	struct ptrace_siginfo info;
7241.90Skamil	struct kinfo_proc2 kp;
7251.90Skamil	size_t len = sizeof(kp);
7261.90Skamil
7271.90Skamil	int name[6];
7281.90Skamil	const size_t namelen = __arraycount(name);
7291.90Skamil	ki_sigset_t kp_sigignore;
7301.88Skamil
7311.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7321.88Skamil	if (sig == SIGILL)
7331.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7341.88Skamil#endif
7351.88Skamil
7361.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
7371.114Skamil		atf_tc_skip("FP exceptions are not supported");
7381.114Skamil
7391.88Skamil	memset(&info, 0, sizeof(info));
7401.88Skamil
7411.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7421.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7431.88Skamil	if (child == 0) {
7441.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7451.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7461.88Skamil
7471.88Skamil		memset(&sa, 0, sizeof(sa));
7481.88Skamil		sa.sa_handler = SIG_IGN;
7491.88Skamil		sigemptyset(&sa.sa_mask);
7501.88Skamil
7511.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7521.88Skamil
7531.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7541.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7551.90Skamil
7561.88Skamil		DPRINTF("Before executing a trap\n");
7571.88Skamil		switch (sig) {
7581.88Skamil		case SIGTRAP:
7591.88Skamil			trigger_trap();
7601.88Skamil			break;
7611.88Skamil		case SIGSEGV:
7621.88Skamil			trigger_segv();
7631.88Skamil			break;
7641.88Skamil		case SIGILL:
7651.88Skamil			trigger_ill();
7661.88Skamil			break;
7671.88Skamil		case SIGFPE:
7681.88Skamil			trigger_fpe();
7691.88Skamil			break;
7701.88Skamil		case SIGBUS:
7711.88Skamil			trigger_bus();
7721.88Skamil			break;
7731.88Skamil		default:
7741.88Skamil			/* NOTREACHED */
7751.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7761.88Skamil		}
7771.88Skamil
7781.88Skamil		/* NOTREACHED */
7791.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7801.88Skamil	}
7811.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7821.88Skamil
7831.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7841.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7851.88Skamil
7861.90Skamil	validate_status_stopped(status, sigval);
7871.90Skamil
7881.90Skamil	name[0] = CTL_KERN,
7891.90Skamil	name[1] = KERN_PROC2,
7901.90Skamil	name[2] = KERN_PROC_PID;
7911.90Skamil	name[3] = child;
7921.90Skamil	name[4] = sizeof(kp);
7931.90Skamil	name[5] = 1;
7941.90Skamil
7951.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
7961.90Skamil
7971.90Skamil	kp_sigignore = kp.p_sigignore;
7981.90Skamil
7991.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
8001.90Skamil	SYSCALL_REQUIRE(
8011.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8021.90Skamil
8031.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8041.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8051.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8061.90Skamil	    info.psi_siginfo.si_errno);
8071.90Skamil
8081.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8091.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
8101.90Skamil
8111.90Skamil	DPRINTF("Before resuming the child process where it left off and "
8121.90Skamil	    "without signal to be sent\n");
8131.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8141.90Skamil
8151.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8161.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8171.90Skamil
8181.88Skamil	validate_status_stopped(status, sig);
8191.88Skamil
8201.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
8211.88Skamil	SYSCALL_REQUIRE(
8221.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8231.88Skamil
8241.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8251.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8261.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8271.88Skamil	    info.psi_siginfo.si_errno);
8281.88Skamil
8291.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8301.90Skamil
8311.90Skamil	DPRINTF("kp_sigignore="
8321.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8331.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8341.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8351.90Skamil
8361.90Skamil	DPRINTF("kp.p_sigignore="
8371.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8381.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8391.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8401.90Skamil
8411.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8421.90Skamil
8431.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8441.88Skamil	switch (sig) {
8451.88Skamil	case SIGTRAP:
8461.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8471.88Skamil		break;
8481.88Skamil	case SIGSEGV:
8491.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8501.88Skamil		break;
8511.88Skamil	case SIGILL:
8521.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
8531.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
8541.88Skamil		break;
8551.88Skamil	case SIGFPE:
8561.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8571.88Skamil		break;
8581.88Skamil	case SIGBUS:
8591.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8601.88Skamil		break;
8611.88Skamil	}
8621.88Skamil
8631.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8641.88Skamil
8651.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8661.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8671.88Skamil
8681.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8691.88Skamil
8701.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8711.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8721.88Skamil}
8731.88Skamil
8741.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8751.88SkamilATF_TC(test);								\
8761.88SkamilATF_TC_HEAD(test, tc)							\
8771.88Skamil{									\
8781.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8791.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8801.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8811.88Skamil}									\
8821.88Skamil									\
8831.88SkamilATF_TC_BODY(test, tc)							\
8841.88Skamil{									\
8851.88Skamil									\
8861.88Skamil	traceme_signalignored_crash(sig);				\
8871.88Skamil}
8881.88Skamil
8891.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8901.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8911.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8921.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8931.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8941.88Skamil
8951.88Skamil/// ----------------------------------------------------------------------------
8961.88Skamil
8971.88Skamilstatic void
8981.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
8991.1Skamil{
9001.1Skamil	const int exitval = 5;
9011.34Skamil	const int sigval = SIGSTOP;
9021.1Skamil	pid_t child, wpid;
9031.1Skamil	struct sigaction sa;
9041.1Skamil#if defined(TWAIT_HAVE_STATUS)
9051.1Skamil	int status;
9061.1Skamil#endif
9071.61Skre	struct ptrace_siginfo info;
9081.1Skamil
9091.45Skamil	memset(&info, 0, sizeof(info));
9101.45Skamil
9111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
9121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
9131.1Skamil	if (child == 0) {
9141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9161.1Skamil
9171.34Skamil		sa.sa_handler = sah;
9181.1Skamil		sa.sa_flags = SA_SIGINFO;
9191.1Skamil		sigemptyset(&sa.sa_mask);
9201.1Skamil
9211.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
9221.1Skamil
9231.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9241.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9251.1Skamil
9261.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9271.1Skamil
9281.13Schristos		DPRINTF("Before exiting of the child process\n");
9291.1Skamil		_exit(exitval);
9301.1Skamil	}
9311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9321.1Skamil
9331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9351.1Skamil
9361.1Skamil	validate_status_stopped(status, sigval);
9371.1Skamil
9381.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9391.61Skre	SYSCALL_REQUIRE(
9401.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9411.45Skamil
9421.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9431.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9441.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9451.45Skamil	    info.psi_siginfo.si_errno);
9461.45Skamil
9471.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9481.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9491.45Skamil
9501.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9511.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9531.1Skamil
9541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9561.1Skamil
9571.1Skamil	validate_status_exited(status, exitval);
9581.1Skamil
9591.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9611.1Skamil}
9621.1Skamil
9631.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9641.61SkreATF_TC(test);								\
9651.61SkreATF_TC_HEAD(test, tc)							\
9661.61Skre{									\
9671.61Skre	atf_tc_set_md_var(tc, "descr",					\
9681.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9691.61Skre	    "handled correctly and caught by a signal handler");	\
9701.61Skre}									\
9711.61Skre									\
9721.61Skrestatic int test##_caught = 0;						\
9731.61Skre									\
9741.61Skrestatic void								\
9751.61Skretest##_sighandler(int arg)						\
9761.61Skre{									\
9771.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9781.61Skre									\
9791.61Skre	++ test##_caught;						\
9801.61Skre}									\
9811.61Skre									\
9821.61SkreATF_TC_BODY(test, tc)							\
9831.61Skre{									\
9841.61Skre									\
9851.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9861.34Skamil}
9871.34Skamil
9881.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9891.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9901.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9911.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9921.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9931.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9941.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9951.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
9961.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
9971.34Skamil
9981.34Skamil/// ----------------------------------------------------------------------------
9991.34Skamil
10001.35Skamilstatic void
10011.50Skamiltraceme_sendsignal_masked(int sigsent)
10021.50Skamil{
10031.50Skamil	const int exitval = 5;
10041.50Skamil	const int sigval = SIGSTOP;
10051.50Skamil	pid_t child, wpid;
10061.50Skamil	sigset_t set;
10071.50Skamil#if defined(TWAIT_HAVE_STATUS)
10081.50Skamil	int status;
10091.50Skamil#endif
10101.61Skre	struct ptrace_siginfo info;
10111.50Skamil
10121.50Skamil	memset(&info, 0, sizeof(info));
10131.50Skamil
10141.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10151.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10161.50Skamil	if (child == 0) {
10171.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10181.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10191.50Skamil
10201.50Skamil		sigemptyset(&set);
10211.50Skamil		sigaddset(&set, sigsent);
10221.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
10231.50Skamil
10241.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10251.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10261.50Skamil
10271.50Skamil		_exit(exitval);
10281.50Skamil	}
10291.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10301.50Skamil
10311.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10321.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10331.50Skamil
10341.50Skamil	validate_status_stopped(status, sigval);
10351.50Skamil
10361.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10371.61Skre	SYSCALL_REQUIRE(
10381.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10391.50Skamil
10401.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10411.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10421.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10431.50Skamil	    info.psi_siginfo.si_errno);
10441.50Skamil
10451.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10461.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10471.50Skamil
10481.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10491.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10501.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10511.50Skamil
10521.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10531.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10541.50Skamil
10551.50Skamil	validate_status_exited(status, exitval);
10561.50Skamil
10571.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10581.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10591.50Skamil}
10601.50Skamil
10611.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10621.61SkreATF_TC(test);								\
10631.61SkreATF_TC_HEAD(test, tc)							\
10641.61Skre{									\
10651.61Skre	atf_tc_set_md_var(tc, "descr",					\
10661.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10671.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10681.61Skre}									\
10691.61Skre									\
10701.61SkreATF_TC_BODY(test, tc)							\
10711.61Skre{									\
10721.61Skre									\
10731.61Skre	traceme_sendsignal_masked(sig);					\
10741.50Skamil}
10751.50Skamil
10761.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10771.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10781.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10791.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10801.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10811.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10821.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10831.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10841.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10851.50Skamil
10861.50Skamil/// ----------------------------------------------------------------------------
10871.50Skamil
10881.50Skamilstatic void
10891.50Skamiltraceme_sendsignal_ignored(int sigsent)
10901.50Skamil{
10911.50Skamil	const int exitval = 5;
10921.50Skamil	const int sigval = SIGSTOP;
10931.50Skamil	pid_t child, wpid;
10941.50Skamil	struct sigaction sa;
10951.50Skamil#if defined(TWAIT_HAVE_STATUS)
10961.50Skamil	int status;
10971.50Skamil#endif
10981.61Skre	struct ptrace_siginfo info;
10991.50Skamil
11001.50Skamil	memset(&info, 0, sizeof(info));
11011.50Skamil
11021.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
11031.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
11041.50Skamil	if (child == 0) {
11051.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11061.61Skre
11071.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11081.50Skamil
11091.50Skamil		memset(&sa, 0, sizeof(sa));
11101.50Skamil		sa.sa_handler = SIG_IGN;
11111.50Skamil		sigemptyset(&sa.sa_mask);
11121.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
11131.50Skamil
11141.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11151.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11161.50Skamil
11171.50Skamil		_exit(exitval);
11181.50Skamil	}
11191.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11201.50Skamil
11211.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11221.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11231.50Skamil
11241.50Skamil	validate_status_stopped(status, sigval);
11251.50Skamil
11261.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11271.61Skre	SYSCALL_REQUIRE(
11281.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11291.50Skamil
11301.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11311.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11321.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11331.50Skamil	    info.psi_siginfo.si_errno);
11341.50Skamil
11351.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11361.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11371.50Skamil
11381.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11391.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11401.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11411.50Skamil
11421.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11431.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11441.50Skamil
11451.50Skamil	validate_status_exited(status, exitval);
11461.50Skamil
11471.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11481.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11491.50Skamil}
11501.50Skamil
11511.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11521.61SkreATF_TC(test);								\
11531.61SkreATF_TC_HEAD(test, tc)							\
11541.61Skre{									\
11551.61Skre	atf_tc_set_md_var(tc, "descr",					\
11561.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11571.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11581.61Skre}									\
11591.61Skre									\
11601.61SkreATF_TC_BODY(test, tc)							\
11611.61Skre{									\
11621.61Skre									\
11631.61Skre	traceme_sendsignal_ignored(sig);				\
11641.50Skamil}
11651.50Skamil
11661.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11671.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11681.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11691.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11701.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11711.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11721.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11731.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11741.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11751.50Skamil
11761.50Skamil/// ----------------------------------------------------------------------------
11771.50Skamil
11781.50Skamilstatic void
11791.50Skamiltraceme_sendsignal_simple(int sigsent)
11801.1Skamil{
11811.35Skamil	const int sigval = SIGSTOP;
11821.35Skamil	int exitval = 0;
11831.1Skamil	pid_t child, wpid;
11841.1Skamil#if defined(TWAIT_HAVE_STATUS)
11851.1Skamil	int status;
11861.85Skamil	int expect_core;
11871.85Skamil
11881.85Skamil	switch (sigsent) {
11891.85Skamil	case SIGABRT:
11901.85Skamil	case SIGTRAP:
11911.85Skamil	case SIGBUS:
11921.85Skamil	case SIGILL:
11931.85Skamil	case SIGFPE:
11941.85Skamil	case SIGSEGV:
11951.85Skamil		expect_core = 1;
11961.85Skamil		break;
11971.85Skamil	default:
11981.85Skamil		expect_core = 0;
11991.85Skamil		break;
12001.85Skamil	}
12011.1Skamil#endif
12021.61Skre	struct ptrace_siginfo info;
12031.1Skamil
12041.45Skamil	memset(&info, 0, sizeof(info));
12051.45Skamil
12061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12081.1Skamil	if (child == 0) {
12091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12111.1Skamil
12121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12141.1Skamil
12151.35Skamil		switch (sigsent) {
12161.35Skamil		case SIGCONT:
12171.48Skamil		case SIGSTOP:
12181.35Skamil			_exit(exitval);
12191.35Skamil		default:
12201.35Skamil			/* NOTREACHED */
12211.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
12221.35Skamil		}
12231.1Skamil	}
12241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12251.1Skamil
12261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12281.1Skamil
12291.1Skamil	validate_status_stopped(status, sigval);
12301.1Skamil
12311.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12321.61Skre	SYSCALL_REQUIRE(
12331.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12341.45Skamil
12351.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12361.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12371.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12381.45Skamil	    info.psi_siginfo.si_errno);
12391.45Skamil
12401.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12411.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12421.45Skamil
12431.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12441.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12461.1Skamil
12471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12491.1Skamil
12501.35Skamil	switch (sigsent) {
12511.48Skamil	case SIGSTOP:
12521.48Skamil		validate_status_stopped(status, sigsent);
12531.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12541.61Skre		    "child\n");
12551.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12561.61Skre		    sizeof(info)) != -1);
12571.48Skamil
12581.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12591.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12601.61Skre		    "si_errno=%#x\n",
12611.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12621.61Skre		    info.psi_siginfo.si_errno);
12631.48Skamil
12641.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12651.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12661.48Skamil
12671.48Skamil		DPRINTF("Before resuming the child process where it left off "
12681.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12691.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12701.48Skamil
12711.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12721.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12731.61Skre		    child);
12741.48Skamil		/* FALLTHROUGH */
12751.35Skamil	case SIGCONT:
12761.35Skamil		validate_status_exited(status, exitval);
12771.35Skamil		break;
12781.35Skamil	default:
12791.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12801.35Skamil		break;
12811.35Skamil	}
12821.1Skamil
12831.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12851.1Skamil}
12861.1Skamil
12871.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12881.61SkreATF_TC(test);								\
12891.61SkreATF_TC_HEAD(test, tc)							\
12901.61Skre{									\
12911.61Skre	atf_tc_set_md_var(tc, "descr",					\
12921.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12931.61Skre	    "handled correctly in a child without a signal handler");	\
12941.61Skre}									\
12951.61Skre									\
12961.61SkreATF_TC_BODY(test, tc)							\
12971.61Skre{									\
12981.61Skre									\
12991.61Skre	traceme_sendsignal_simple(sig);					\
13001.35Skamil}
13011.35Skamil
13021.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
13031.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
13041.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
13051.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
13061.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
13071.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
13081.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
13091.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
13101.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
13111.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
13121.35Skamil
13131.35Skamil/// ----------------------------------------------------------------------------
13141.35Skamil
13151.37SkamilATF_TC(traceme_pid1_parent);
13161.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
13171.37Skamil{
13181.37Skamil	atf_tc_set_md_var(tc, "descr",
13191.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
13201.37Skamil}
13211.37Skamil
13221.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
13231.37Skamil{
13241.37Skamil	struct msg_fds parent_child;
13251.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13261.37Skamil	pid_t child1, child2, wpid;
13271.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13281.37Skamil#if defined(TWAIT_HAVE_STATUS)
13291.37Skamil	int status;
13301.37Skamil#endif
13311.37Skamil
13321.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13331.37Skamil
13341.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13351.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13361.37Skamil	if (child1 == 0) {
13371.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13381.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13391.37Skamil		if (child2 != 0) {
13401.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13411.61Skre			    getpid(), child2);
13421.37Skamil			_exit(exitval_child1);
13431.37Skamil		}
13441.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13451.37Skamil
13461.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13471.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13481.37Skamil
13491.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13501.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13511.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13521.37Skamil
13531.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13541.37Skamil
13551.37Skamil		_exit(exitval_child2);
13561.37Skamil	}
13571.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13581.37Skamil
13591.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13601.61Skre	TWAIT_REQUIRE_SUCCESS(
13611.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13621.37Skamil
13631.37Skamil	validate_status_exited(status, exitval_child1);
13641.37Skamil
13651.37Skamil	DPRINTF("Notify that child1 is dead\n");
13661.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13671.37Skamil
13681.37Skamil	DPRINTF("Wait for exiting of child2\n");
13691.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13701.37Skamil}
13711.37Skamil
13721.37Skamil/// ----------------------------------------------------------------------------
13731.37Skamil
13741.40Skamilstatic void
13751.40Skamiltraceme_vfork_raise(int sigval)
13761.40Skamil{
13771.46Skamil	const int exitval = 5, exitval_watcher = 10;
13781.46Skamil	pid_t child, parent, watcher, wpid;
13791.46Skamil	int rv;
13801.40Skamil#if defined(TWAIT_HAVE_STATUS)
13811.40Skamil	int status;
13821.85Skamil
13831.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13841.85Skamil	volatile int expect_core;
13851.85Skamil
13861.85Skamil	switch (sigval) {
13871.85Skamil	case SIGABRT:
13881.85Skamil	case SIGTRAP:
13891.85Skamil	case SIGBUS:
13901.85Skamil	case SIGILL:
13911.85Skamil	case SIGFPE:
13921.85Skamil	case SIGSEGV:
13931.85Skamil		expect_core = 1;
13941.85Skamil		break;
13951.85Skamil	default:
13961.85Skamil		expect_core = 0;
13971.85Skamil		break;
13981.85Skamil	}
13991.40Skamil#endif
14001.40Skamil
14011.46Skamil	/*
14021.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
14031.46Skamil	 * the SIGKILL signal to it.
14041.46Skamil	 *
14051.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
14061.46Skamil	 * simpler to reparent this process to initproc and forget about it.
14071.46Skamil	 */
14081.46Skamil	if (sigval == SIGSTOP) {
14091.46Skamil		parent = getpid();
14101.46Skamil
14111.46Skamil		watcher = fork();
14121.46Skamil		ATF_REQUIRE(watcher != 1);
14131.46Skamil		if (watcher == 0) {
14141.46Skamil			/* Double fork(2) trick to reparent to initproc */
14151.46Skamil			watcher = fork();
14161.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
14171.46Skamil			if (watcher != 0)
14181.46Skamil				_exit(exitval_watcher);
14191.46Skamil
14201.46Skamil			child = await_stopped_child(parent);
14211.46Skamil
14221.46Skamil			errno = 0;
14231.46Skamil			rv = kill(child, SIGKILL);
14241.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
14251.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14261.46Skamil
14271.46Skamil			/* This exit value will be collected by initproc */
14281.46Skamil			_exit(0);
14291.46Skamil		}
14301.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14311.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14321.61Skre		    watcher);
14331.46Skamil
14341.46Skamil		validate_status_exited(status, exitval_watcher);
14351.46Skamil
14361.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14371.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14381.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14391.46Skamil	}
14401.46Skamil
14411.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14421.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14431.40Skamil	if (child == 0) {
14441.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14451.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14461.40Skamil
14471.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14481.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14491.40Skamil
14501.40Skamil		switch (sigval) {
14511.46Skamil		case SIGSTOP:
14521.40Skamil		case SIGKILL:
14531.40Skamil		case SIGABRT:
14541.40Skamil		case SIGHUP:
14551.85Skamil		case SIGTRAP:
14561.85Skamil		case SIGBUS:
14571.85Skamil		case SIGILL:
14581.85Skamil		case SIGFPE:
14591.85Skamil		case SIGSEGV:
14601.40Skamil			/* NOTREACHED */
14611.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14621.70Smrg			__unreachable();
14631.40Skamil		default:
14641.40Skamil			DPRINTF("Before exiting of the child process\n");
14651.40Skamil			_exit(exitval);
14661.40Skamil		}
14671.40Skamil	}
14681.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14691.40Skamil
14701.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14711.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14721.40Skamil
14731.40Skamil	switch (sigval) {
14741.40Skamil	case SIGKILL:
14751.40Skamil	case SIGABRT:
14761.40Skamil	case SIGHUP:
14771.85Skamil	case SIGTRAP:
14781.85Skamil	case SIGBUS:
14791.85Skamil	case SIGILL:
14801.85Skamil	case SIGFPE:
14811.85Skamil	case SIGSEGV:
14821.40Skamil		validate_status_signaled(status, sigval, expect_core);
14831.40Skamil		break;
14841.40Skamil	case SIGSTOP:
14851.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14861.46Skamil		break;
14871.40Skamil	case SIGCONT:
14881.47Skamil	case SIGTSTP:
14891.47Skamil	case SIGTTIN:
14901.47Skamil	case SIGTTOU:
14911.40Skamil		validate_status_exited(status, exitval);
14921.40Skamil		break;
14931.40Skamil	default:
14941.40Skamil		/* NOTREACHED */
14951.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
14961.40Skamil		break;
14971.40Skamil	}
14981.40Skamil
14991.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15001.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15011.40Skamil}
15021.40Skamil
15031.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
15041.61SkreATF_TC(test);								\
15051.61SkreATF_TC_HEAD(test, tc)							\
15061.61Skre{									\
15071.61Skre	atf_tc_set_md_var(tc, "descr",					\
15081.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
15091.61Skre	    "vfork(2)ed child");					\
15101.61Skre}									\
15111.61Skre									\
15121.61SkreATF_TC_BODY(test, tc)							\
15131.61Skre{									\
15141.61Skre									\
15151.61Skre	traceme_vfork_raise(sig);					\
15161.40Skamil}
15171.40Skamil
15181.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
15191.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
15201.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
15211.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
15221.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
15231.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
15241.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
15251.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15261.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15271.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15281.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15291.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15301.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15311.40Skamil
15321.40Skamil/// ----------------------------------------------------------------------------
15331.40Skamil
15341.52Skamilstatic void
15351.52Skamiltraceme_vfork_crash(int sig)
15361.41Skamil{
15371.41Skamil	pid_t child, wpid;
15381.41Skamil#if defined(TWAIT_HAVE_STATUS)
15391.41Skamil	int status;
15401.41Skamil#endif
15411.41Skamil
15421.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15431.71Skamil	if (sig == SIGILL)
15441.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15451.71Skamil#endif
15461.71Skamil
15471.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
15481.114Skamil		atf_tc_skip("FP exceptions are not supported");
15491.114Skamil
15501.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15511.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15521.41Skamil	if (child == 0) {
15531.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15541.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15551.41Skamil
15561.52Skamil		DPRINTF("Before executing a trap\n");
15571.52Skamil		switch (sig) {
15581.52Skamil		case SIGTRAP:
15591.52Skamil			trigger_trap();
15601.52Skamil			break;
15611.52Skamil		case SIGSEGV:
15621.52Skamil			trigger_segv();
15631.52Skamil			break;
15641.52Skamil		case SIGILL:
15651.52Skamil			trigger_ill();
15661.52Skamil			break;
15671.52Skamil		case SIGFPE:
15681.52Skamil			trigger_fpe();
15691.52Skamil			break;
15701.52Skamil		case SIGBUS:
15711.52Skamil			trigger_bus();
15721.52Skamil			break;
15731.52Skamil		default:
15741.52Skamil			/* NOTREACHED */
15751.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15761.52Skamil		}
15771.41Skamil
15781.41Skamil		/* NOTREACHED */
15791.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15801.41Skamil	}
15811.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15821.41Skamil
15831.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15841.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15851.41Skamil
15861.52Skamil	validate_status_signaled(status, sig, 1);
15871.41Skamil
15881.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15891.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15901.41Skamil}
15911.41Skamil
15921.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15931.61SkreATF_TC(test);								\
15941.61SkreATF_TC_HEAD(test, tc)							\
15951.61Skre{									\
15961.61Skre	atf_tc_set_md_var(tc, "descr",					\
15971.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
15981.61Skre	    "vfork(2)ed child");					\
15991.61Skre}									\
16001.61Skre									\
16011.61SkreATF_TC_BODY(test, tc)							\
16021.61Skre{									\
16031.61Skre									\
16041.61Skre	traceme_vfork_crash(sig);					\
16051.52Skamil}
16061.52Skamil
16071.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
16081.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
16091.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
16101.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
16111.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
16121.52Skamil
16131.41Skamil/// ----------------------------------------------------------------------------
16141.41Skamil
16151.92Skamilstatic void
16161.92Skamiltraceme_vfork_signalmasked_crash(int sig)
16171.92Skamil{
16181.92Skamil	pid_t child, wpid;
16191.92Skamil#if defined(TWAIT_HAVE_STATUS)
16201.92Skamil	int status;
16211.92Skamil#endif
16221.92Skamil	sigset_t intmask;
16231.92Skamil
16241.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16251.92Skamil	if (sig == SIGILL)
16261.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16271.92Skamil#endif
16281.92Skamil
16291.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
16301.114Skamil		atf_tc_skip("FP exceptions are not supported");
16311.114Skamil
16321.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16331.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16341.92Skamil	if (child == 0) {
16351.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16361.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16371.92Skamil
16381.92Skamil		sigemptyset(&intmask);
16391.92Skamil		sigaddset(&intmask, sig);
16401.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16411.92Skamil
16421.92Skamil		DPRINTF("Before executing a trap\n");
16431.92Skamil		switch (sig) {
16441.92Skamil		case SIGTRAP:
16451.92Skamil			trigger_trap();
16461.92Skamil			break;
16471.92Skamil		case SIGSEGV:
16481.92Skamil			trigger_segv();
16491.92Skamil			break;
16501.92Skamil		case SIGILL:
16511.92Skamil			trigger_ill();
16521.92Skamil			break;
16531.92Skamil		case SIGFPE:
16541.92Skamil			trigger_fpe();
16551.92Skamil			break;
16561.92Skamil		case SIGBUS:
16571.92Skamil			trigger_bus();
16581.92Skamil			break;
16591.92Skamil		default:
16601.92Skamil			/* NOTREACHED */
16611.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16621.92Skamil		}
16631.92Skamil
16641.92Skamil		/* NOTREACHED */
16651.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16661.92Skamil	}
16671.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16681.92Skamil
16691.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16701.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16711.92Skamil
16721.92Skamil	validate_status_signaled(status, sig, 1);
16731.92Skamil
16741.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16751.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16761.92Skamil}
16771.92Skamil
16781.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16791.92SkamilATF_TC(test);								\
16801.92SkamilATF_TC_HEAD(test, tc)							\
16811.92Skamil{									\
16821.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16831.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16841.92Skamil	    "vfork(2)ed child with a masked signal");			\
16851.92Skamil}									\
16861.92Skamil									\
16871.92SkamilATF_TC_BODY(test, tc)							\
16881.92Skamil{									\
16891.92Skamil									\
16901.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16911.92Skamil}
16921.92Skamil
16931.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16941.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16951.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
16961.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
16971.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
16981.92Skamil
16991.92Skamil/// ----------------------------------------------------------------------------
17001.92Skamil
17011.92Skamilstatic void
17021.92Skamiltraceme_vfork_signalignored_crash(int sig)
17031.92Skamil{
17041.92Skamil	pid_t child, wpid;
17051.92Skamil#if defined(TWAIT_HAVE_STATUS)
17061.92Skamil	int status;
17071.92Skamil#endif
17081.92Skamil	struct sigaction sa;
17091.92Skamil
17101.92Skamil#ifndef PTRACE_ILLEGAL_ASM
17111.92Skamil	if (sig == SIGILL)
17121.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
17131.92Skamil#endif
17141.92Skamil
17151.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
17161.114Skamil		atf_tc_skip("FP exceptions are not supported");
17171.114Skamil
17181.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17191.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17201.92Skamil	if (child == 0) {
17211.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17221.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17231.92Skamil
17241.92Skamil		memset(&sa, 0, sizeof(sa));
17251.92Skamil		sa.sa_handler = SIG_IGN;
17261.92Skamil		sigemptyset(&sa.sa_mask);
17271.92Skamil
17281.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
17291.92Skamil
17301.92Skamil		DPRINTF("Before executing a trap\n");
17311.92Skamil		switch (sig) {
17321.92Skamil		case SIGTRAP:
17331.92Skamil			trigger_trap();
17341.92Skamil			break;
17351.92Skamil		case SIGSEGV:
17361.92Skamil			trigger_segv();
17371.92Skamil			break;
17381.92Skamil		case SIGILL:
17391.92Skamil			trigger_ill();
17401.92Skamil			break;
17411.92Skamil		case SIGFPE:
17421.92Skamil			trigger_fpe();
17431.92Skamil			break;
17441.92Skamil		case SIGBUS:
17451.92Skamil			trigger_bus();
17461.92Skamil			break;
17471.92Skamil		default:
17481.92Skamil			/* NOTREACHED */
17491.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17501.92Skamil		}
17511.92Skamil
17521.92Skamil		/* NOTREACHED */
17531.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17541.92Skamil	}
17551.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17561.92Skamil
17571.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17581.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17591.92Skamil
17601.92Skamil	validate_status_signaled(status, sig, 1);
17611.92Skamil
17621.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17631.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17641.92Skamil}
17651.92Skamil
17661.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17671.92SkamilATF_TC(test);								\
17681.92SkamilATF_TC_HEAD(test, tc)							\
17691.92Skamil{									\
17701.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17711.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17721.92Skamil	    "vfork(2)ed child with ignored signal");			\
17731.92Skamil}									\
17741.92Skamil									\
17751.92SkamilATF_TC_BODY(test, tc)							\
17761.92Skamil{									\
17771.92Skamil									\
17781.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17791.92Skamil}
17801.92Skamil
17811.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17821.92Skamil    SIGTRAP)
17831.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17841.92Skamil    SIGSEGV)
17851.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17861.92Skamil    SIGILL)
17871.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17881.92Skamil    SIGFPE)
17891.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17901.92Skamil    SIGBUS)
17911.92Skamil
17921.92Skamil/// ----------------------------------------------------------------------------
17931.92Skamil
17941.96Skamilstatic void
17951.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
17961.43Skamil{
17971.43Skamil	const int sigval = SIGTRAP;
17981.43Skamil	pid_t child, wpid;
17991.43Skamil#if defined(TWAIT_HAVE_STATUS)
18001.43Skamil	int status;
18011.43Skamil#endif
18021.96Skamil	struct sigaction sa;
18031.61Skre	struct ptrace_siginfo info;
18041.96Skamil	sigset_t intmask;
18051.96Skamil	struct kinfo_proc2 kp;
18061.96Skamil	size_t len = sizeof(kp);
18071.96Skamil
18081.96Skamil	int name[6];
18091.96Skamil	const size_t namelen = __arraycount(name);
18101.96Skamil	ki_sigset_t kp_sigmask;
18111.96Skamil	ki_sigset_t kp_sigignore;
18121.43Skamil
18131.43Skamil	memset(&info, 0, sizeof(info));
18141.43Skamil
18151.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
18161.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
18171.43Skamil	if (child == 0) {
18181.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18191.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18201.43Skamil
18211.96Skamil		if (masked) {
18221.96Skamil			sigemptyset(&intmask);
18231.96Skamil			sigaddset(&intmask, sigval);
18241.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
18251.96Skamil		}
18261.96Skamil
18271.96Skamil		if (ignored) {
18281.96Skamil			memset(&sa, 0, sizeof(sa));
18291.96Skamil			sa.sa_handler = SIG_IGN;
18301.96Skamil			sigemptyset(&sa.sa_mask);
18311.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
18321.96Skamil		}
18331.96Skamil
18341.43Skamil		DPRINTF("Before calling execve(2) from child\n");
18351.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
18361.43Skamil
18371.43Skamil		/* NOTREACHED */
18381.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18391.43Skamil	}
18401.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18411.43Skamil
18421.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18431.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18441.43Skamil
18451.43Skamil	validate_status_stopped(status, sigval);
18461.43Skamil
18471.96Skamil	name[0] = CTL_KERN,
18481.96Skamil	name[1] = KERN_PROC2,
18491.96Skamil	name[2] = KERN_PROC_PID;
18501.96Skamil	name[3] = getpid();
18511.96Skamil	name[4] = sizeof(kp);
18521.96Skamil	name[5] = 1;
18531.96Skamil
18541.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18551.96Skamil
18561.96Skamil	if (masked)
18571.96Skamil		kp_sigmask = kp.p_sigmask;
18581.96Skamil
18591.96Skamil	if (ignored)
18601.96Skamil		kp_sigignore = kp.p_sigignore;
18611.96Skamil
18621.96Skamil	name[3] = getpid();
18631.96Skamil
18641.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18651.96Skamil
18661.96Skamil	if (masked) {
18671.96Skamil		DPRINTF("kp_sigmask="
18681.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18691.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18701.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18711.96Skamil
18721.96Skamil	        DPRINTF("kp.p_sigmask="
18731.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18741.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18751.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18761.96Skamil
18771.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18781.96Skamil		    sizeof(kp_sigmask)));
18791.96Skamil	}
18801.96Skamil
18811.96Skamil	if (ignored) {
18821.96Skamil		DPRINTF("kp_sigignore="
18831.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18841.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18851.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18861.96Skamil
18871.96Skamil	        DPRINTF("kp.p_sigignore="
18881.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18891.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
18901.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
18911.96Skamil
18921.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
18931.96Skamil		    sizeof(kp_sigignore)));
18941.96Skamil	}
18951.96Skamil
18961.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
18971.61Skre	SYSCALL_REQUIRE(
18981.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
18991.43Skamil
19001.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
19011.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
19021.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
19031.43Skamil	    info.psi_siginfo.si_errno);
19041.43Skamil
19051.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
19061.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
19071.43Skamil
19081.43Skamil	DPRINTF("Before resuming the child process where it left off and "
19091.43Skamil	    "without signal to be sent\n");
19101.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19111.43Skamil
19121.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19131.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19141.43Skamil
19151.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19161.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19171.43Skamil}
19181.43Skamil
19191.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
19201.96SkamilATF_TC(test);								\
19211.96SkamilATF_TC_HEAD(test, tc)							\
19221.96Skamil{									\
19231.96Skamil	atf_tc_set_md_var(tc, "descr",					\
19241.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
19251.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
19261.96Skamil	    masked ? " with ignored signal" : "");			\
19271.96Skamil}									\
19281.96Skamil									\
19291.96SkamilATF_TC_BODY(test, tc)							\
19301.96Skamil{									\
19311.96Skamil									\
19321.96Skamil	traceme_vfork_exec(masked, ignored);				\
19331.96Skamil}
19341.96Skamil
19351.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
19361.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19371.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19381.96Skamil
19391.43Skamil/// ----------------------------------------------------------------------------
19401.43Skamil
19411.1Skamil#if defined(TWAIT_HAVE_PID)
19421.51Skamilstatic void
19431.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19441.59Skamil{
19451.94Skamil	const int sigval = SIGSTOP;
19461.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19471.59Skamil	const int exitval = 10;
19481.59Skamil	pid_t tracee, tracer, wpid;
19491.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19501.59Skamil#if defined(TWAIT_HAVE_STATUS)
19511.59Skamil	int status;
19521.59Skamil#endif
19531.94Skamil	struct sigaction sa;
19541.59Skamil	struct ptrace_siginfo info;
19551.94Skamil	sigset_t intmask;
19561.94Skamil	struct kinfo_proc2 kp;
19571.94Skamil	size_t len = sizeof(kp);
19581.94Skamil
19591.94Skamil	int name[6];
19601.94Skamil	const size_t namelen = __arraycount(name);
19611.94Skamil	ki_sigset_t kp_sigmask;
19621.94Skamil	ki_sigset_t kp_sigignore;
19631.61Skre
19641.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19651.71Skamil	if (sig == SIGILL)
19661.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19671.71Skamil#endif
19681.71Skamil
19691.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
19701.114Skamil		atf_tc_skip("FP exceptions are not supported");
19711.114Skamil
19721.59Skamil	memset(&info, 0, sizeof(info));
19731.59Skamil
19741.59Skamil	DPRINTF("Spawn tracee\n");
19751.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19761.59Skamil	tracee = atf_utils_fork();
19771.59Skamil	if (tracee == 0) {
19781.59Skamil		// Wait for parent to let us crash
19791.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19801.61Skre
19811.94Skamil		if (masked) {
19821.94Skamil			sigemptyset(&intmask);
19831.94Skamil			sigaddset(&intmask, sig);
19841.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19851.94Skamil		}
19861.94Skamil
19871.94Skamil		if (ignored) {
19881.94Skamil			memset(&sa, 0, sizeof(sa));
19891.94Skamil			sa.sa_handler = SIG_IGN;
19901.94Skamil			sigemptyset(&sa.sa_mask);
19911.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
19921.94Skamil		}
19931.94Skamil
19941.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19951.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19961.94Skamil
19971.59Skamil		DPRINTF("Before executing a trap\n");
19981.59Skamil		switch (sig) {
19991.59Skamil		case SIGTRAP:
20001.59Skamil			trigger_trap();
20011.59Skamil			break;
20021.59Skamil		case SIGSEGV:
20031.59Skamil			trigger_segv();
20041.59Skamil			break;
20051.59Skamil		case SIGILL:
20061.59Skamil			trigger_ill();
20071.59Skamil			break;
20081.59Skamil		case SIGFPE:
20091.59Skamil			trigger_fpe();
20101.59Skamil			break;
20111.59Skamil		case SIGBUS:
20121.59Skamil			trigger_bus();
20131.59Skamil			break;
20141.59Skamil		default:
20151.59Skamil			/* NOTREACHED */
20161.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
20171.59Skamil		}
20181.59Skamil
20191.59Skamil		/* NOTREACHED */
20201.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
20211.59Skamil	}
20221.59Skamil
20231.59Skamil	DPRINTF("Spawn debugger\n");
20241.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
20251.59Skamil	tracer = atf_utils_fork();
20261.59Skamil	if (tracer == 0) {
20271.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
20281.59Skamil		tracer = atf_utils_fork();
20291.59Skamil		if (tracer != 0)
20301.61Skre			_exit(exitval);
20311.59Skamil
20321.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
20331.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
20341.59Skamil
20351.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
20361.59Skamil		FORKEE_REQUIRE_SUCCESS(
20371.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20381.59Skamil
20391.59Skamil		forkee_status_stopped(status, SIGSTOP);
20401.59Skamil
20411.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20421.94Skamil		    "traced process\n");
20431.94Skamil		SYSCALL_REQUIRE(
20441.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20451.94Skamil
20461.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20471.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20481.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20491.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20501.94Skamil
20511.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20521.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20531.94Skamil
20541.59Skamil		/* Resume tracee with PT_CONTINUE */
20551.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20561.59Skamil
20571.59Skamil		/* Inform parent that tracer has attached to tracee */
20581.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20591.59Skamil
20601.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20611.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20621.59Skamil
20631.59Skamil		/* Wait for tracee and assert that it exited */
20641.59Skamil		FORKEE_REQUIRE_SUCCESS(
20651.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20661.59Skamil
20671.94Skamil		forkee_status_stopped(status, sigval);
20681.94Skamil
20691.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20701.94Skamil		    "traced process\n");
20711.94Skamil		SYSCALL_REQUIRE(
20721.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20731.94Skamil
20741.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20751.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20761.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20771.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20781.94Skamil
20791.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20801.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20811.94Skamil
20821.94Skamil		name[0] = CTL_KERN,
20831.94Skamil		name[1] = KERN_PROC2,
20841.94Skamil		name[2] = KERN_PROC_PID;
20851.94Skamil		name[3] = tracee;
20861.94Skamil		name[4] = sizeof(kp);
20871.94Skamil		name[5] = 1;
20881.94Skamil
20891.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20901.94Skamil
20911.94Skamil		if (masked)
20921.94Skamil			kp_sigmask = kp.p_sigmask;
20931.94Skamil
20941.94Skamil		if (ignored)
20951.94Skamil			kp_sigignore = kp.p_sigignore;
20961.94Skamil
20971.94Skamil		/* Resume tracee with PT_CONTINUE */
20981.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20991.94Skamil
21001.94Skamil		/* Wait for tracee and assert that it exited */
21011.94Skamil		FORKEE_REQUIRE_SUCCESS(
21021.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21031.94Skamil
21041.93Skamil		forkee_status_stopped(status, sig);
21051.59Skamil
21061.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
21071.61Skre		    "traced process\n");
21081.61Skre		SYSCALL_REQUIRE(
21091.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
21101.59Skamil
21111.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
21121.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
21131.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
21141.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
21151.59Skamil
21161.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
21171.94Skamil
21181.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
21191.94Skamil
21201.94Skamil		if (masked) {
21211.94Skamil			DPRINTF("kp_sigmask="
21221.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21231.94Skamil			    PRIx32 "\n",
21241.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
21251.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
21261.94Skamil
21271.94Skamil			DPRINTF("kp.p_sigmask="
21281.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21291.94Skamil			    PRIx32 "\n",
21301.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
21311.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
21321.94Skamil
21331.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
21341.94Skamil			    sizeof(kp_sigmask)));
21351.94Skamil		}
21361.94Skamil
21371.94Skamil		if (ignored) {
21381.94Skamil			DPRINTF("kp_sigignore="
21391.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21401.94Skamil			    PRIx32 "\n",
21411.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21421.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21431.94Skamil
21441.94Skamil			DPRINTF("kp.p_sigignore="
21451.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21461.94Skamil			    PRIx32 "\n",
21471.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21481.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21491.94Skamil
21501.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21511.94Skamil			    sizeof(kp_sigignore)));
21521.94Skamil		}
21531.94Skamil
21541.59Skamil		switch (sig) {
21551.59Skamil		case SIGTRAP:
21561.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21571.59Skamil			break;
21581.59Skamil		case SIGSEGV:
21591.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21601.59Skamil			break;
21611.71Skamil		case SIGILL:
21621.113Skamil			FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC &&
21631.112Skamil			            info.psi_siginfo.si_code <= ILL_BADSTK);
21641.71Skamil			break;
21651.59Skamil		case SIGFPE:
21661.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21671.59Skamil			break;
21681.59Skamil		case SIGBUS:
21691.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21701.59Skamil			break;
21711.59Skamil		}
21721.59Skamil
21731.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21741.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21751.93Skamil		FORKEE_REQUIRE_SUCCESS(
21761.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21771.59Skamil
21781.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21791.59Skamil
21801.71Skamil		/* Inform parent that tracer is exiting normally */
21811.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21821.71Skamil
21831.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21841.59Skamil		_exit(0 /* collect by initproc */);
21851.59Skamil	}
21861.59Skamil
21871.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21881.59Skamil	    "calling %s()\n", TWAIT_FNAME);
21891.59Skamil	TWAIT_REQUIRE_SUCCESS(
21901.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21911.59Skamil
21921.59Skamil	validate_status_exited(status, exitval);
21931.59Skamil
21941.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
21951.59Skamil	    TWAIT_FNAME);
21961.59Skamil	TWAIT_REQUIRE_SUCCESS(
21971.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
21981.59Skamil
21991.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
22001.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
22011.59Skamil
22021.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
22031.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
22041.59Skamil
22051.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
22061.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
22071.59Skamil
22081.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
22091.59Skamil	    TWAIT_FNAME);
22101.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22111.59Skamil
22121.59Skamil	validate_status_signaled(status, SIGKILL, 0);
22131.59Skamil
22141.71Skamil	DPRINTF("Await normal exit of tracer\n");
22151.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
22161.71Skamil
22171.59Skamil	msg_close(&parent_tracer);
22181.59Skamil	msg_close(&parent_tracee);
22191.59Skamil}
22201.59Skamil
22211.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
22221.61SkreATF_TC(test);								\
22231.61SkreATF_TC_HEAD(test, tc)							\
22241.61Skre{									\
22251.61Skre	atf_tc_set_md_var(tc, "descr",					\
22261.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22271.94Skamil	    "the debuggee");						\
22281.61Skre}									\
22291.61Skre									\
22301.61SkreATF_TC_BODY(test, tc)							\
22311.61Skre{									\
22321.61Skre									\
22331.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
22341.59Skamil}
22351.59Skamil
22361.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
22371.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
22381.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
22391.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
22401.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22411.94Skamil
22421.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22431.94SkamilATF_TC(test);								\
22441.94SkamilATF_TC_HEAD(test, tc)							\
22451.94Skamil{									\
22461.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22471.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22481.94Skamil	    "the debuggee with masked signal");				\
22491.94Skamil}									\
22501.94Skamil									\
22511.94SkamilATF_TC_BODY(test, tc)							\
22521.94Skamil{									\
22531.94Skamil									\
22541.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22551.94Skamil}
22561.94Skamil
22571.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22581.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22591.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22601.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22611.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22621.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22631.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22641.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22651.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22661.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22671.94Skamil
22681.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22691.94SkamilATF_TC(test);								\
22701.94SkamilATF_TC_HEAD(test, tc)							\
22711.94Skamil{									\
22721.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22731.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22741.94Skamil	    "the debuggee with signal ignored");			\
22751.94Skamil}									\
22761.94Skamil									\
22771.94SkamilATF_TC_BODY(test, tc)							\
22781.94Skamil{									\
22791.94Skamil									\
22801.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22811.94Skamil}
22821.94Skamil
22831.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22841.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22851.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22861.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22871.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22881.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
22891.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22901.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
22911.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22921.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
22931.59Skamil#endif
22941.59Skamil
22951.59Skamil/// ----------------------------------------------------------------------------
22961.59Skamil
22971.59Skamil#if defined(TWAIT_HAVE_PID)
22981.59Skamilstatic void
22991.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
23001.67Skamil                                             bool stopped)
23011.1Skamil{
23021.51Skamil	/*
23031.51Skamil	 * notimeout - disable timeout in await zombie function
23041.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
23051.67Skamil	 * stopped - attach to a stopped process
23061.51Skamil	 */
23071.1Skamil
23081.1Skamil	struct msg_fds parent_tracee, parent_tracer;
23091.1Skamil	const int exitval_tracee = 5;
23101.1Skamil	const int exitval_tracer = 10;
23111.1Skamil	pid_t tracee, tracer, wpid;
23121.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
23131.1Skamil#if defined(TWAIT_HAVE_STATUS)
23141.1Skamil	int status;
23151.1Skamil#endif
23161.1Skamil
23171.67Skamil	/*
23181.67Skamil	 * Only a subset of options are supported.
23191.67Skamil	 */
23201.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
23211.67Skamil	            (!notimeout && unrelated && !stopped) ||
23221.67Skamil	            (notimeout && !unrelated && !stopped) ||
23231.67Skamil	            (!notimeout && unrelated && stopped));
23241.67Skamil
23251.13Schristos	DPRINTF("Spawn tracee\n");
23261.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
23271.1Skamil	tracee = atf_utils_fork();
23281.1Skamil	if (tracee == 0) {
23291.67Skamil		if (stopped) {
23301.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
23311.67Skamil			raise(SIGSTOP);
23321.67Skamil		}
23331.67Skamil
23341.1Skamil		// Wait for parent to let us exit
23351.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
23361.1Skamil		_exit(exitval_tracee);
23371.1Skamil	}
23381.1Skamil
23391.13Schristos	DPRINTF("Spawn debugger\n");
23401.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23411.1Skamil	tracer = atf_utils_fork();
23421.1Skamil	if (tracer == 0) {
23431.51Skamil		if(unrelated) {
23441.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23451.51Skamil			tracer = atf_utils_fork();
23461.51Skamil			if (tracer != 0)
23471.51Skamil				_exit(exitval_tracer);
23481.51Skamil		}
23491.51Skamil
23501.67Skamil		if (stopped) {
23511.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23521.67Skamil			await_stopped(tracee);
23531.67Skamil		}
23541.67Skamil
23551.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23561.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23571.1Skamil
23581.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23591.1Skamil		FORKEE_REQUIRE_SUCCESS(
23601.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23611.1Skamil
23621.1Skamil		forkee_status_stopped(status, SIGSTOP);
23631.1Skamil
23641.1Skamil		/* Resume tracee with PT_CONTINUE */
23651.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23661.1Skamil
23671.1Skamil		/* Inform parent that tracer has attached to tracee */
23681.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23691.1Skamil
23701.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23711.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23721.1Skamil
23731.1Skamil		/* Wait for tracee and assert that it exited */
23741.1Skamil		FORKEE_REQUIRE_SUCCESS(
23751.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23761.1Skamil
23771.1Skamil		forkee_status_exited(status, exitval_tracee);
23781.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23791.1Skamil
23801.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23811.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23821.51Skamil	}
23831.51Skamil
23841.51Skamil	if (unrelated) {
23851.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23861.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23871.51Skamil		TWAIT_REQUIRE_SUCCESS(
23881.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23891.51Skamil
23901.51Skamil		validate_status_exited(status, exitval_tracer);
23911.51Skamil
23921.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
23931.51Skamil		    TWAIT_FNAME);
23941.51Skamil		TWAIT_REQUIRE_SUCCESS(
23951.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
23961.1Skamil	}
23971.1Skamil
23981.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
23991.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
24001.1Skamil
24011.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
24021.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
24031.1Skamil
24041.13Schristos	DPRINTF("Detect that tracee is zombie\n");
24051.51Skamil	if (notimeout)
24061.26Skamil		await_zombie_raw(tracee, 0);
24071.26Skamil	else
24081.26Skamil		await_zombie(tracee);
24091.1Skamil
24101.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
24111.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
24121.1Skamil	    TWAIT_FNAME);
24131.1Skamil	TWAIT_REQUIRE_SUCCESS(
24141.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
24151.1Skamil
24161.51Skamil	if (unrelated) {
24171.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
24181.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
24191.51Skamil	} else {
24201.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
24211.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
24221.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
24231.59Skamil			"%s()\n", TWAIT_FNAME);
24241.51Skamil
24251.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
24261.59Skamil			"tracee\n");
24271.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
24281.51Skamil		    tracer);
24291.1Skamil
24301.51Skamil		validate_status_exited(status, exitval_tracer);
24311.51Skamil	}
24321.1Skamil
24331.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
24341.1Skamil	    TWAIT_FNAME);
24351.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
24361.1Skamil
24371.1Skamil	validate_status_exited(status, exitval_tracee);
24381.1Skamil
24391.1Skamil	msg_close(&parent_tracer);
24401.1Skamil	msg_close(&parent_tracee);
24411.1Skamil}
24421.26Skamil
24431.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24441.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24451.51Skamil{
24461.51Skamil	atf_tc_set_md_var(tc, "descr",
24471.51Skamil	    "Assert that tracer sees process termination before the parent");
24481.51Skamil}
24491.51Skamil
24501.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24511.26Skamil{
24521.26Skamil
24531.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24541.26Skamil}
24551.26Skamil
24561.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24571.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24581.1Skamil{
24591.1Skamil	atf_tc_set_md_var(tc, "descr",
24601.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24611.51Skamil	    "process and no other error is reported");
24621.1Skamil}
24631.1Skamil
24641.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24651.1Skamil{
24661.51Skamil	time_t start, end;
24671.51Skamil	double diff;
24681.51Skamil	unsigned long N = 0;
24691.1Skamil
24701.51Skamil	/*
24711.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24721.51Skamil	 * This test body isn't specific to this race, however it's just good
24731.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24741.51Skamil	 */
24751.1Skamil
24761.51Skamil	start = time(NULL);
24771.51Skamil	while (true) {
24781.51Skamil		DPRINTF("Step: %lu\n", N);
24791.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24801.67Skamil		                                             false);
24811.51Skamil		end = time(NULL);
24821.51Skamil		diff = difftime(end, start);
24831.51Skamil		if (diff >= 5.0)
24841.51Skamil			break;
24851.51Skamil		++N;
24861.1Skamil	}
24871.51Skamil	DPRINTF("Iterations: %lu\n", N);
24881.51Skamil}
24891.1Skamil
24901.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
24911.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24921.51Skamil{
24931.51Skamil	atf_tc_set_md_var(tc, "descr",
24941.51Skamil	    "Assert that tracer sees process termination before the parent");
24951.51Skamil}
24961.1Skamil
24971.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24981.51Skamil{
24991.1Skamil
25001.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
25011.67Skamil}
25021.67Skamil
25031.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
25041.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
25051.67Skamil{
25061.67Skamil	atf_tc_set_md_var(tc, "descr",
25071.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
25081.67Skamil}
25091.67Skamil
25101.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
25111.67Skamil{
25121.67Skamil
25131.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
25141.1Skamil}
25151.1Skamil#endif
25161.1Skamil
25171.51Skamil/// ----------------------------------------------------------------------------
25181.51Skamil
25191.66Skamilstatic void
25201.66Skamilparent_attach_to_its_child(bool stopped)
25211.1Skamil{
25221.1Skamil	struct msg_fds parent_tracee;
25231.1Skamil	const int exitval_tracee = 5;
25241.1Skamil	pid_t tracee, wpid;
25251.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25261.1Skamil#if defined(TWAIT_HAVE_STATUS)
25271.1Skamil	int status;
25281.1Skamil#endif
25291.1Skamil
25301.13Schristos	DPRINTF("Spawn tracee\n");
25311.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25321.1Skamil	tracee = atf_utils_fork();
25331.1Skamil	if (tracee == 0) {
25341.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25351.13Schristos		DPRINTF("Parent should now attach to tracee\n");
25361.1Skamil
25371.66Skamil		if (stopped) {
25381.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
25391.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
25401.66Skamil		}
25411.66Skamil
25421.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25431.1Skamil		/* Wait for message from the parent */
25441.1Skamil		_exit(exitval_tracee);
25451.1Skamil	}
25461.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25471.57Skamil
25481.66Skamil	if (stopped) {
25491.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25501.66Skamil		await_stopped(tracee);
25511.66Skamil	}
25521.66Skamil
25531.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25551.1Skamil
25561.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25571.1Skamil	    TWAIT_FNAME);
25581.1Skamil	TWAIT_REQUIRE_SUCCESS(
25591.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25601.1Skamil
25611.1Skamil	validate_status_stopped(status, SIGSTOP);
25621.1Skamil
25631.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25651.1Skamil
25661.13Schristos	DPRINTF("Let the tracee exit now\n");
25671.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25681.1Skamil
25691.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25701.1Skamil	TWAIT_REQUIRE_SUCCESS(
25711.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25721.1Skamil
25731.1Skamil	validate_status_exited(status, exitval_tracee);
25741.1Skamil
25751.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25771.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25781.1Skamil
25791.1Skamil	msg_close(&parent_tracee);
25801.1Skamil}
25811.1Skamil
25821.66SkamilATF_TC(parent_attach_to_its_child);
25831.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25841.66Skamil{
25851.66Skamil	atf_tc_set_md_var(tc, "descr",
25861.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25871.66Skamil}
25881.66Skamil
25891.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
25901.66Skamil{
25911.66Skamil
25921.66Skamil	parent_attach_to_its_child(false);
25931.66Skamil}
25941.66Skamil
25951.66SkamilATF_TC(parent_attach_to_its_stopped_child);
25961.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
25971.66Skamil{
25981.66Skamil	atf_tc_set_md_var(tc, "descr",
25991.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
26001.66Skamil}
26011.66Skamil
26021.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
26031.66Skamil{
26041.66Skamil
26051.66Skamil	parent_attach_to_its_child(true);
26061.66Skamil}
26071.66Skamil
26081.51Skamil/// ----------------------------------------------------------------------------
26091.51Skamil
26101.65Skamilstatic void
26111.65Skamilchild_attach_to_its_parent(bool stopped)
26121.1Skamil{
26131.1Skamil	struct msg_fds parent_tracee;
26141.1Skamil	const int exitval_tracer = 5;
26151.1Skamil	pid_t tracer, wpid;
26161.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
26171.1Skamil#if defined(TWAIT_HAVE_STATUS)
26181.1Skamil	int status;
26191.1Skamil#endif
26201.1Skamil
26211.13Schristos	DPRINTF("Spawn tracer\n");
26221.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
26231.1Skamil	tracer = atf_utils_fork();
26241.1Skamil	if (tracer == 0) {
26251.1Skamil		/* Wait for message from the parent */
26261.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
26271.1Skamil
26281.65Skamil		if (stopped) {
26291.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
26301.65Skamil			        getppid());
26311.65Skamil			await_stopped(getppid());
26321.65Skamil		}
26331.65Skamil
26341.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
26351.1Skamil		    getppid());
26361.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
26371.1Skamil
26381.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
26391.1Skamil		    TWAIT_FNAME);
26401.1Skamil		FORKEE_REQUIRE_SUCCESS(
26411.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26421.1Skamil
26431.1Skamil		forkee_status_stopped(status, SIGSTOP);
26441.1Skamil
26451.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26461.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26471.1Skamil		    != -1);
26481.1Skamil
26491.1Skamil		/* Tell parent we are ready */
26501.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26511.1Skamil
26521.1Skamil		_exit(exitval_tracer);
26531.1Skamil	}
26541.1Skamil
26551.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26561.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26571.65Skamil
26581.65Skamil	if (stopped) {
26591.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26601.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26611.65Skamil	}
26621.65Skamil
26631.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26641.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26651.1Skamil
26661.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26671.1Skamil	TWAIT_REQUIRE_SUCCESS(
26681.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26691.1Skamil
26701.1Skamil	validate_status_exited(status, exitval_tracer);
26711.1Skamil
26721.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26731.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26741.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26751.1Skamil
26761.1Skamil	msg_close(&parent_tracee);
26771.1Skamil}
26781.1Skamil
26791.65SkamilATF_TC(child_attach_to_its_parent);
26801.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26811.65Skamil{
26821.65Skamil	atf_tc_set_md_var(tc, "descr",
26831.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26841.65Skamil}
26851.65Skamil
26861.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26871.65Skamil{
26881.65Skamil
26891.65Skamil	child_attach_to_its_parent(false);
26901.65Skamil}
26911.65Skamil
26921.65SkamilATF_TC(child_attach_to_its_stopped_parent);
26931.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
26941.65Skamil{
26951.65Skamil	atf_tc_set_md_var(tc, "descr",
26961.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
26971.65Skamil}
26981.65Skamil
26991.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
27001.65Skamil{
27011.65Skamil	/*
27021.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
27031.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
27041.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
27051.65Skamil	 *
27061.65Skamil	 * As a workaround spawn this test as a subprocess.
27071.65Skamil	 */
27081.65Skamil
27091.65Skamil	const int exitval = 15;
27101.65Skamil	pid_t child, wpid;
27111.65Skamil#if defined(TWAIT_HAVE_STATUS)
27121.65Skamil	int status;
27131.65Skamil#endif
27141.65Skamil
27151.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
27161.65Skamil	if (child == 0) {
27171.65Skamil		child_attach_to_its_parent(true);
27181.65Skamil		_exit(exitval);
27191.65Skamil	} else {
27201.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27211.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27221.65Skamil
27231.65Skamil		validate_status_exited(status, exitval);
27241.65Skamil
27251.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
27261.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27271.65Skamil	}
27281.65Skamil}
27291.65Skamil
27301.51Skamil/// ----------------------------------------------------------------------------
27311.51Skamil
27321.1Skamil#if defined(TWAIT_HAVE_PID)
27331.1Skamil
27341.51Skamilenum tracee_sees_its_original_parent_type {
27351.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
27361.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
27371.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
27381.51Skamil};
27391.51Skamil
27401.51Skamilstatic void
27411.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27421.1Skamil{
27431.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27441.1Skamil	const int exitval_tracee = 5;
27451.1Skamil	const int exitval_tracer = 10;
27461.1Skamil	pid_t parent, tracee, tracer, wpid;
27471.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27481.1Skamil#if defined(TWAIT_HAVE_STATUS)
27491.1Skamil	int status;
27501.1Skamil#endif
27511.51Skamil	/* sysctl(3) - kinfo_proc2 */
27521.51Skamil	int name[CTL_MAXNAME];
27531.51Skamil	struct kinfo_proc2 kp;
27541.51Skamil	size_t len = sizeof(kp);
27551.51Skamil	unsigned int namelen;
27561.51Skamil
27571.51Skamil	/* procfs - status  */
27581.51Skamil	FILE *fp;
27591.51Skamil	struct stat st;
27601.51Skamil	const char *fname = "/proc/curproc/status";
27611.51Skamil	char s_executable[MAXPATHLEN];
27621.51Skamil	int s_pid, s_ppid;
27631.51Skamil	int rv;
27641.51Skamil
27651.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27661.61Skre		SYSCALL_REQUIRE(
27671.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27681.61Skre		if (rv != 0)
27691.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27701.51Skamil	}
27711.1Skamil
27721.13Schristos	DPRINTF("Spawn tracee\n");
27731.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27741.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27751.1Skamil	tracee = atf_utils_fork();
27761.1Skamil	if (tracee == 0) {
27771.1Skamil		parent = getppid();
27781.1Skamil
27791.1Skamil		/* Emit message to the parent */
27801.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27811.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27821.1Skamil
27831.51Skamil		switch (type) {
27841.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27851.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27861.51Skamil			break;
27871.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27881.51Skamil			namelen = 0;
27891.51Skamil			name[namelen++] = CTL_KERN;
27901.51Skamil			name[namelen++] = KERN_PROC2;
27911.51Skamil			name[namelen++] = KERN_PROC_PID;
27921.51Skamil			name[namelen++] = getpid();
27931.51Skamil			name[namelen++] = len;
27941.51Skamil			name[namelen++] = 1;
27951.51Skamil
27961.61Skre			FORKEE_ASSERT_EQ(
27971.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
27981.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
27991.51Skamil			break;
28001.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
28011.51Skamil			/*
28021.51Skamil			 * Format:
28031.51Skamil			 *  EXECUTABLE PID PPID ...
28041.51Skamil			 */
28051.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
28061.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
28071.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
28081.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
28091.51Skamil			break;
28101.51Skamil		}
28111.1Skamil
28121.1Skamil		_exit(exitval_tracee);
28131.1Skamil	}
28141.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
28151.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
28161.1Skamil
28171.13Schristos	DPRINTF("Spawn debugger\n");
28181.1Skamil	tracer = atf_utils_fork();
28191.1Skamil	if (tracer == 0) {
28201.1Skamil		/* No IPC to communicate with the child */
28211.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
28221.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
28231.1Skamil
28241.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
28251.1Skamil		FORKEE_REQUIRE_SUCCESS(
28261.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28271.1Skamil
28281.1Skamil		forkee_status_stopped(status, SIGSTOP);
28291.1Skamil
28301.1Skamil		/* Resume tracee with PT_CONTINUE */
28311.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
28321.1Skamil
28331.1Skamil		/* Inform parent that tracer has attached to tracee */
28341.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
28351.1Skamil
28361.1Skamil		/* Wait for parent to tell use that tracee should have exited */
28371.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
28381.1Skamil
28391.1Skamil		/* Wait for tracee and assert that it exited */
28401.1Skamil		FORKEE_REQUIRE_SUCCESS(
28411.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28421.1Skamil
28431.1Skamil		forkee_status_exited(status, exitval_tracee);
28441.1Skamil
28451.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28461.1Skamil		_exit(exitval_tracer);
28471.1Skamil	}
28481.1Skamil
28491.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28501.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28511.1Skamil
28521.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28531.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28541.1Skamil
28551.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28561.1Skamil	await_zombie(tracee);
28571.1Skamil
28581.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28591.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28601.1Skamil	TWAIT_REQUIRE_SUCCESS(
28611.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28621.1Skamil
28631.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28641.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28651.1Skamil
28661.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28681.1Skamil	    tracer);
28691.1Skamil
28701.1Skamil	validate_status_exited(status, exitval_tracer);
28711.1Skamil
28721.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28731.1Skamil	    TWAIT_FNAME);
28741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28751.1Skamil	    tracee);
28761.1Skamil
28771.1Skamil	validate_status_exited(status, exitval_tracee);
28781.1Skamil
28791.1Skamil	msg_close(&parent_tracer);
28801.1Skamil	msg_close(&parent_tracee);
28811.1Skamil}
28821.1Skamil
28831.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28841.61SkreATF_TC(test);								\
28851.61SkreATF_TC_HEAD(test, tc)							\
28861.61Skre{									\
28871.61Skre	atf_tc_set_md_var(tc, "descr",					\
28881.61Skre	    "Assert that tracee sees its original parent when being traced " \
28891.61Skre	    "(check " descr ")");					\
28901.61Skre}									\
28911.61Skre									\
28921.61SkreATF_TC_BODY(test, tc)							\
28931.61Skre{									\
28941.61Skre									\
28951.61Skre	tracee_sees_its_original_parent(type);				\
28961.1Skamil}
28971.1Skamil
28981.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28991.51Skamil	tracee_sees_its_original_parent_getppid,
29001.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
29011.51Skamil	"getppid(2)");
29021.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29031.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
29041.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
29051.51Skamil	"sysctl(3) and kinfo_proc2");
29061.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29071.51Skamil	tracee_sees_its_original_parent_procfs_status,
29081.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
29091.51Skamil	"the status file in procfs");
29101.1Skamil#endif
29111.1Skamil
29121.51Skamil/// ----------------------------------------------------------------------------
29131.1Skamil
29141.53Skamilstatic void
29151.53Skamileventmask_preserved(int event)
29161.1Skamil{
29171.1Skamil	const int exitval = 5;
29181.1Skamil	const int sigval = SIGSTOP;
29191.1Skamil	pid_t child, wpid;
29201.1Skamil#if defined(TWAIT_HAVE_STATUS)
29211.1Skamil	int status;
29221.1Skamil#endif
29231.1Skamil	ptrace_event_t set_event, get_event;
29241.1Skamil	const int len = sizeof(ptrace_event_t);
29251.1Skamil
29261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29281.1Skamil	if (child == 0) {
29291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29311.1Skamil
29321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29341.1Skamil
29351.13Schristos		DPRINTF("Before exiting of the child process\n");
29361.1Skamil		_exit(exitval);
29371.1Skamil	}
29381.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29391.1Skamil
29401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29421.1Skamil
29431.1Skamil	validate_status_stopped(status, sigval);
29441.1Skamil
29451.53Skamil	set_event.pe_set_event = event;
29461.61Skre	SYSCALL_REQUIRE(
29471.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29481.61Skre	SYSCALL_REQUIRE(
29491.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29501.125Skamil	DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event,
29511.125Skamil	    get_event.pe_set_event);
29521.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29531.1Skamil
29541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29551.1Skamil	    "without signal to be sent\n");
29561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29571.1Skamil
29581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29601.1Skamil
29611.1Skamil	validate_status_exited(status, exitval);
29621.1Skamil
29631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29651.1Skamil}
29661.1Skamil
29671.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29681.61SkreATF_TC(test);								\
29691.61SkreATF_TC_HEAD(test, tc)							\
29701.61Skre{									\
29711.61Skre	atf_tc_set_md_var(tc, "descr",					\
29721.61Skre	    "Verify that eventmask " #event " is preserved");		\
29731.61Skre}									\
29741.61Skre									\
29751.61SkreATF_TC_BODY(test, tc)							\
29761.61Skre{									\
29771.61Skre									\
29781.61Skre	eventmask_preserved(event);					\
29791.1Skamil}
29801.1Skamil
29811.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29821.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29831.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29841.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29851.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29861.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29871.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN)
29881.1Skamil
29891.53Skamil/// ----------------------------------------------------------------------------
29901.1Skamil
29911.28Skamilstatic void
29921.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork,
29931.105Skamil    bool trackvforkdone)
29941.1Skamil{
29951.1Skamil	const int exitval = 5;
29961.125Skamil	const int exitval2 = 0; /* This matched exit status from /bin/echo */
29971.1Skamil	const int sigval = SIGSTOP;
29981.31Skamil	pid_t child, child2 = 0, wpid;
29991.1Skamil#if defined(TWAIT_HAVE_STATUS)
30001.1Skamil	int status;
30011.1Skamil#endif
30021.1Skamil	ptrace_state_t state;
30031.1Skamil	const int slen = sizeof(state);
30041.1Skamil	ptrace_event_t event;
30051.1Skamil	const int elen = sizeof(event);
30061.1Skamil
30071.124Skamil	char * const arg[] = { __UNCONST("/bin/echo"), NULL };
30081.124Skamil
30091.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30101.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30111.1Skamil	if (child == 0) {
30121.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30131.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30141.1Skamil
30151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30171.1Skamil
30181.125Skamil		if (strcmp(fn, "spawn") == 0) {
30191.124Skamil			FORKEE_ASSERT_EQ(posix_spawn(&child2,
30201.124Skamil			    arg[0], NULL, NULL, arg, NULL), 0);
30211.125Skamil		} else {
30221.125Skamil			if (strcmp(fn, "fork") == 0) {
30231.125Skamil				FORKEE_ASSERT((child2 = fork()) != -1);
30241.125Skamil			} else if (strcmp(fn, "vfork") == 0) {
30251.125Skamil				FORKEE_ASSERT((child2 = vfork()) != -1);
30261.125Skamil			}
30271.1Skamil
30281.124Skamil			if (child2 == 0)
30291.124Skamil				_exit(exitval2);
30301.124Skamil		}
30311.1Skamil		FORKEE_REQUIRE_SUCCESS
30321.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30331.1Skamil
30341.1Skamil		forkee_status_exited(status, exitval2);
30351.1Skamil
30361.13Schristos		DPRINTF("Before exiting of the child process\n");
30371.1Skamil		_exit(exitval);
30381.1Skamil	}
30391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30401.1Skamil
30411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30431.1Skamil
30441.1Skamil	validate_status_stopped(status, sigval);
30451.1Skamil
30461.125Skamil	DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n",
30471.125Skamil	    trackspawn ? "|PTRACE_POSIX_SPAWN" : "",
30481.61Skre	    trackfork ? "|PTRACE_FORK" : "",
30491.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
30501.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
30511.30Skamil	event.pe_set_event = 0;
30521.125Skamil	if (trackspawn)
30531.125Skamil		event.pe_set_event |= PTRACE_POSIX_SPAWN;
30541.30Skamil	if (trackfork)
30551.30Skamil		event.pe_set_event |= PTRACE_FORK;
30561.30Skamil	if (trackvfork)
30571.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30581.30Skamil	if (trackvforkdone)
30591.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30611.1Skamil
30621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30631.1Skamil	    "without signal to be sent\n");
30641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30651.1Skamil
30661.29Skamil#if defined(TWAIT_HAVE_PID)
30671.125Skamil	if ((trackspawn && strcmp(fn, "spawn") == 0) ||
30681.125Skamil	    (trackfork && strcmp(fn, "fork") == 0) ||
30691.125Skamil	    (trackvfork && strcmp(fn, "vfork") == 0)) {
30701.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30711.61Skre		    child);
30721.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30731.61Skre		    child);
30741.1Skamil
30751.29Skamil		validate_status_stopped(status, SIGTRAP);
30761.1Skamil
30771.61Skre		SYSCALL_REQUIRE(
30781.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30791.125Skamil		if (trackspawn && strcmp(fn, "spawn") == 0) {
30801.125Skamil			ATF_REQUIRE_EQ(
30811.125Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
30821.125Skamil			       PTRACE_POSIX_SPAWN);
30831.125Skamil		}
30841.125Skamil		if (trackfork && strcmp(fn, "fork") == 0) {
30851.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30861.30Skamil			       PTRACE_FORK);
30871.30Skamil		}
30881.125Skamil		if (trackvfork && strcmp(fn, "vfork") == 0) {
30891.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30901.30Skamil			       PTRACE_VFORK);
30911.30Skamil		}
30921.29Skamil
30931.29Skamil		child2 = state.pe_other_pid;
30941.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
30951.29Skamil
30961.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
30971.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
30981.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
30991.29Skamil		    child2);
31001.1Skamil
31011.29Skamil		validate_status_stopped(status, SIGTRAP);
31021.1Skamil
31031.61Skre		SYSCALL_REQUIRE(
31041.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
31051.125Skamil		if (trackspawn && strcmp(fn, "spawn") == 0) {
31061.125Skamil			ATF_REQUIRE_EQ(
31071.125Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
31081.125Skamil			       PTRACE_POSIX_SPAWN);
31091.125Skamil		}
31101.125Skamil		if (trackfork && strcmp(fn, "fork") == 0) {
31111.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
31121.30Skamil			       PTRACE_FORK);
31131.30Skamil		}
31141.125Skamil		if (trackvfork && strcmp(fn, "vfork") == 0) {
31151.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
31161.30Skamil			       PTRACE_VFORK);
31171.30Skamil		}
31181.30Skamil
31191.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
31201.29Skamil
31211.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
31221.29Skamil		    "and without signal to be sent\n");
31231.61Skre		SYSCALL_REQUIRE(
31241.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
31251.29Skamil
31261.29Skamil		DPRINTF("Before resuming the child process where it left off "
31271.61Skre		    "and without signal to be sent\n");
31281.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31291.30Skamil	}
31301.30Skamil#endif
31311.30Skamil
31321.125Skamil	if (trackvforkdone && strcmp(fn, "vfork") == 0) {
31331.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
31341.61Skre		    child);
31351.61Skre		TWAIT_REQUIRE_SUCCESS(
31361.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
31371.30Skamil
31381.30Skamil		validate_status_stopped(status, SIGTRAP);
31391.30Skamil
31401.61Skre		SYSCALL_REQUIRE(
31411.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
31421.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
31431.30Skamil
31441.30Skamil		child2 = state.pe_other_pid;
31451.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
31461.61Skre		    child2);
31471.30Skamil
31481.30Skamil		DPRINTF("Before resuming the child process where it left off "
31491.61Skre		    "and without signal to be sent\n");
31501.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31511.30Skamil	}
31521.29Skamil
31531.30Skamil#if defined(TWAIT_HAVE_PID)
31541.125Skamil	if ((trackspawn && strcmp(fn, "spawn") == 0) ||
31551.125Skamil	    (trackfork && strcmp(fn, "fork") == 0) ||
31561.125Skamil	    (trackvfork && strcmp(fn, "vfork") == 0)) {
31571.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
31581.61Skre		    "\n", TWAIT_FNAME);
31591.61Skre		TWAIT_REQUIRE_SUCCESS(
31601.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
31611.29Skamil
31621.29Skamil		validate_status_exited(status, exitval2);
31631.29Skamil
31641.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
31651.61Skre		    "process\n", TWAIT_FNAME);
31661.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
31671.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
31681.29Skamil	}
31691.29Skamil#endif
31701.1Skamil
31711.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31721.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31741.1Skamil
31751.1Skamil	validate_status_stopped(status, SIGCHLD);
31761.1Skamil
31771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31781.1Skamil	    "without signal to be sent\n");
31791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31801.1Skamil
31811.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31821.1Skamil	    TWAIT_FNAME);
31831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31841.1Skamil
31851.1Skamil	validate_status_exited(status, exitval);
31861.1Skamil
31871.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31881.1Skamil	    TWAIT_FNAME);
31891.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31901.1Skamil}
31911.28Skamil
31921.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone)		\
31931.61SkreATF_TC(name);								\
31941.61SkreATF_TC_HEAD(name, tc)							\
31951.61Skre{									\
31961.125Skamil	atf_tc_set_md_var(tc, "descr", "Verify " fun "() "		\
31971.125Skamil	    "called with 0%s%s%s%s in EVENT_MASK",			\
31981.125Skamil	    tspawn ? "|PTRACE_FORK" : "",				\
31991.105Skamil	    tfork ? "|PTRACE_FORK" : "",				\
32001.105Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
32011.105Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
32021.61Skre}									\
32031.61Skre									\
32041.61SkreATF_TC_BODY(name, tc)							\
32051.61Skre{									\
32061.61Skre									\
32071.125Skamil	fork_body(fun, tspawn, tfork, tvfork, tvforkdone);		\
32081.32Skamil}
32091.32Skamil
32101.125SkamilFORK_TEST(fork1, "fork", false, false, false, false)
32111.31Skamil#if defined(TWAIT_HAVE_PID)
32121.125SkamilFORK_TEST(fork2, "fork", false, true, false, false)
32131.125SkamilFORK_TEST(fork3, "fork", false, false, true, false)
32141.125SkamilFORK_TEST(fork4, "fork", false, true, true, false)
32151.31Skamil#endif
32161.125SkamilFORK_TEST(fork5, "fork", false, false, false, true)
32171.31Skamil#if defined(TWAIT_HAVE_PID)
32181.125SkamilFORK_TEST(fork6, "fork", false, true, false, true)
32191.125SkamilFORK_TEST(fork7, "fork", false, false, true, true)
32201.125SkamilFORK_TEST(fork8, "fork", false, true, true, true)
32211.125Skamil#endif
32221.125SkamilFORK_TEST(fork9, "fork", true, false, false, false)
32231.125Skamil#if defined(TWAIT_HAVE_PID)
32241.125SkamilFORK_TEST(fork10, "fork", true, true, false, false)
32251.125SkamilFORK_TEST(fork11, "fork", true, false, true, false)
32261.125SkamilFORK_TEST(fork12, "fork", true, true, true, false)
32271.125Skamil#endif
32281.125SkamilFORK_TEST(fork13, "fork", true, false, false, true)
32291.125Skamil#if defined(TWAIT_HAVE_PID)
32301.125SkamilFORK_TEST(fork14, "fork", true, true, false, true)
32311.125SkamilFORK_TEST(fork15, "fork", true, false, true, true)
32321.125SkamilFORK_TEST(fork16, "fork", true, true, true, true)
32331.31Skamil#endif
32341.1Skamil
32351.110Skamil#if TEST_VFORK_ENABLED
32361.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false)
32371.31Skamil#if defined(TWAIT_HAVE_PID)
32381.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false)
32391.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false)
32401.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false)
32411.31Skamil#endif
32421.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true)
32431.31Skamil#if defined(TWAIT_HAVE_PID)
32441.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true)
32451.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true)
32461.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true)
32471.31Skamil#endif
32481.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false)
32491.125Skamil#if defined(TWAIT_HAVE_PID)
32501.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false)
32511.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false)
32521.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false)
32531.110Skamil#endif
32541.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true)
32551.124Skamil#if defined(TWAIT_HAVE_PID)
32561.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true)
32571.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true)
32581.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true)
32591.124Skamil#endif
32601.125Skamil#endif
32611.125Skamil
32621.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false)
32631.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false)
32641.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false)
32651.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false)
32661.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true)
32671.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true)
32681.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true)
32691.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true)
32701.124Skamil#if defined(TWAIT_HAVE_PID)
32711.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false)
32721.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false)
32731.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false)
32741.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false)
32751.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true)
32761.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true)
32771.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true)
32781.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true)
32791.124Skamil#endif
32801.124Skamil
32811.54Skamil/// ----------------------------------------------------------------------------
32821.31Skamil
32831.116Skamil#if defined(TWAIT_HAVE_PID)
32841.116Skamilstatic void
32851.116Skamilfork_detach_forker_body(bool detachfork, bool detachvfork,
32861.116Skamil    bool detachvforkdone, bool kill_process)
32871.116Skamil{
32881.116Skamil	const int exitval = 5;
32891.116Skamil	const int exitval2 = 15;
32901.116Skamil	const int sigval = SIGSTOP;
32911.116Skamil	pid_t child, child2 = 0, wpid;
32921.116Skamil#if defined(TWAIT_HAVE_STATUS)
32931.116Skamil	int status;
32941.116Skamil#endif
32951.116Skamil	ptrace_state_t state;
32961.116Skamil	const int slen = sizeof(state);
32971.116Skamil	ptrace_event_t event;
32981.116Skamil	const int elen = sizeof(event);
32991.116Skamil
33001.116Skamil	pid_t (*fn)(void);
33011.116Skamil	int op;
33021.116Skamil
33031.116Skamil	ATF_REQUIRE((detachfork && !detachvfork && !detachvforkdone) ||
33041.116Skamil	            (!detachfork && detachvfork && !detachvforkdone) ||
33051.116Skamil	            (!detachfork && !detachvfork && detachvforkdone));
33061.116Skamil
33071.116Skamil	if (detachfork)
33081.116Skamil		fn = fork;
33091.116Skamil	else
33101.116Skamil		fn = vfork;
33111.116Skamil
33121.116Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
33131.116Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
33141.116Skamil	if (child == 0) {
33151.116Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33161.116Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33171.116Skamil
33181.116Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33191.116Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33201.116Skamil
33211.116Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
33221.116Skamil
33231.116Skamil		if (child2 == 0)
33241.116Skamil			_exit(exitval2);
33251.116Skamil
33261.116Skamil		FORKEE_REQUIRE_SUCCESS
33271.116Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
33281.116Skamil
33291.116Skamil		forkee_status_exited(status, exitval2);
33301.116Skamil
33311.116Skamil		DPRINTF("Before exiting of the child process\n");
33321.116Skamil		_exit(exitval);
33331.116Skamil	}
33341.116Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33351.116Skamil
33361.116Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33371.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33381.116Skamil
33391.116Skamil	validate_status_stopped(status, sigval);
33401.116Skamil
33411.116Skamil	DPRINTF("Set EVENT_MASK for the child %d\n", child);
33421.116Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
33431.116Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
33441.116Skamil
33451.116Skamil	DPRINTF("Before resuming the child process where it left off and "
33461.116Skamil	    "without signal to be sent\n");
33471.116Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33481.116Skamil
33491.116Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
33501.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33511.116Skamil
33521.116Skamil	validate_status_stopped(status, SIGTRAP);
33531.116Skamil
33541.116Skamil	SYSCALL_REQUIRE(
33551.116Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
33561.116Skamil	op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK;
33571.116Skamil	ATF_REQUIRE_EQ(state.pe_report_event & op, op);
33581.116Skamil
33591.116Skamil	child2 = state.pe_other_pid;
33601.116Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
33611.116Skamil
33621.116Skamil	if (detachfork || detachvfork)
33631.116Skamil		op = kill_process ? PT_KILL : PT_DETACH;
33641.116Skamil	else
33651.116Skamil		op = PT_CONTINUE;
33661.116Skamil	SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1);
33671.116Skamil
33681.116Skamil	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
33691.116Skamil	    TWAIT_FNAME, child2, child);
33701.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
33711.116Skamil
33721.116Skamil	validate_status_stopped(status, SIGTRAP);
33731.116Skamil
33741.116Skamil	SYSCALL_REQUIRE(
33751.116Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
33761.116Skamil	op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK;
33771.116Skamil	ATF_REQUIRE_EQ(state.pe_report_event & op, op);
33781.116Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
33791.116Skamil
33801.116Skamil	DPRINTF("Before resuming the forkee process where it left off "
33811.116Skamil	    "and without signal to be sent\n");
33821.116Skamil 	SYSCALL_REQUIRE(
33831.116Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
33841.116Skamil
33851.116Skamil	if (detachvforkdone && fn == vfork) {
33861.116Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
33871.116Skamil		    child);
33881.116Skamil		TWAIT_REQUIRE_SUCCESS(
33891.116Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
33901.116Skamil
33911.116Skamil		validate_status_stopped(status, SIGTRAP);
33921.116Skamil
33931.116Skamil		SYSCALL_REQUIRE(
33941.116Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
33951.116Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
33961.116Skamil
33971.116Skamil		child2 = state.pe_other_pid;
33981.116Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
33991.116Skamil		    child2);
34001.116Skamil
34011.116Skamil		op = kill_process ? PT_KILL : PT_DETACH;
34021.116Skamil		DPRINTF("Before resuming the child process where it left off "
34031.116Skamil		    "and without signal to be sent\n");
34041.116Skamil		SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1);
34051.116Skamil	}
34061.116Skamil
34071.116Skamil	DPRINTF("Before calling %s() for the forkee - expected exited\n",
34081.116Skamil	    TWAIT_FNAME);
34091.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
34101.116Skamil
34111.116Skamil	validate_status_exited(status, exitval2);
34121.116Skamil
34131.116Skamil	DPRINTF("Before calling %s() for the forkee - expected no process\n",
34141.116Skamil	    TWAIT_FNAME);
34151.116Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0));
34161.116Skamil
34171.116Skamil	DPRINTF("Before calling %s() for the forkee - expected exited\n",
34181.116Skamil	    TWAIT_FNAME);
34191.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34201.116Skamil
34211.116Skamil	if (kill_process) {
34221.116Skamil		validate_status_signaled(status, SIGKILL, 0);
34231.116Skamil	} else {
34241.116Skamil		validate_status_exited(status, exitval);
34251.116Skamil	}
34261.116Skamil
34271.116Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
34281.116Skamil	    TWAIT_FNAME);
34291.116Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34301.116Skamil}
34311.116Skamil
34321.116Skamil#define FORK_DETACH_FORKER(name,detfork,detvfork,detvforkdone,kprocess)	\
34331.116SkamilATF_TC(name);								\
34341.116SkamilATF_TC_HEAD(name, tc)							\
34351.116Skamil{									\
34361.116Skamil	atf_tc_set_md_var(tc, "descr", "Verify %s %s%s%s",		\
34371.116Skamil	    kprocess ? "killed" : "detached",				\
34381.116Skamil	    detfork ? "forker" : "",					\
34391.116Skamil	    detvfork ? "vforker" : "",					\
34401.116Skamil	    detvforkdone ? "vforker done" : "");			\
34411.116Skamil}									\
34421.116Skamil									\
34431.116SkamilATF_TC_BODY(name, tc)							\
34441.116Skamil{									\
34451.116Skamil									\
34461.116Skamil	fork_detach_forker_body(detfork, detvfork, detvforkdone,	\
34471.116Skamil	                        kprocess);				\
34481.116Skamil}
34491.116Skamil
34501.116SkamilFORK_DETACH_FORKER(fork_detach_forker, true, false, false, false)
34511.116Skamil#if TEST_VFORK_ENABLED
34521.116SkamilFORK_DETACH_FORKER(vfork_detach_vforker, false, true, false, false)
34531.116SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, false, false, true, false)
34541.116Skamil#endif
34551.116SkamilFORK_DETACH_FORKER(fork_kill_forker, true, false, false, true)
34561.116Skamil#if TEST_VFORK_ENABLED
34571.116SkamilFORK_DETACH_FORKER(vfork_kill_vforker, false, true, false, true)
34581.116SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, false, false, true, true)
34591.116Skamil#endif
34601.116Skamil#endif
34611.116Skamil
34621.116Skamil/// ----------------------------------------------------------------------------
34631.116Skamil
34641.110Skamil#if TEST_VFORK_ENABLED
34651.108Skamilstatic void
34661.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void))
34671.108Skamil{
34681.108Skamil	const int exitval = 5;
34691.108Skamil	const int exitval2 = 15;
34701.108Skamil	pid_t child, child2 = 0, wpid;
34711.108Skamil#if defined(TWAIT_HAVE_STATUS)
34721.108Skamil	int status;
34731.108Skamil#endif
34741.108Skamil
34751.108Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
34761.108Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
34771.108Skamil	if (child == 0) {
34781.108Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34791.108Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34801.108Skamil
34811.108Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
34821.108Skamil
34831.108Skamil		if (child2 == 0)
34841.108Skamil			_exit(exitval2);
34851.108Skamil
34861.108Skamil		FORKEE_REQUIRE_SUCCESS
34871.108Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
34881.108Skamil
34891.108Skamil		forkee_status_exited(status, exitval2);
34901.108Skamil
34911.108Skamil		DPRINTF("Before exiting of the child process\n");
34921.108Skamil		_exit(exitval);
34931.108Skamil	}
34941.108Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34951.108Skamil
34961.108Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
34971.108Skamil	    TWAIT_FNAME);
34981.108Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34991.108Skamil
35001.108Skamil	validate_status_exited(status, exitval);
35011.108Skamil
35021.108Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
35031.108Skamil	    TWAIT_FNAME);
35041.108Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35051.108Skamil}
35061.108Skamil
35071.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun)				\
35081.108SkamilATF_TC(name);								\
35091.108SkamilATF_TC_HEAD(name, tc)							\
35101.108Skamil{									\
35111.108Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
35121.108Skamil	    "called from vfork(2)ed child");				\
35131.108Skamil}									\
35141.108Skamil									\
35151.108SkamilATF_TC_BODY(name, tc)							\
35161.108Skamil{									\
35171.108Skamil									\
35181.108Skamil	traceme_vfork_fork_body(fun);					\
35191.108Skamil}
35201.108Skamil
35211.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork)
35221.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork)
35231.110Skamil#endif
35241.108Skamil
35251.108Skamil/// ----------------------------------------------------------------------------
35261.108Skamil
35271.54Skamilenum bytes_transfer_type {
35281.54Skamil	BYTES_TRANSFER_DATA,
35291.54Skamil	BYTES_TRANSFER_DATAIO,
35301.54Skamil	BYTES_TRANSFER_TEXT,
35311.54Skamil	BYTES_TRANSFER_TEXTIO,
35321.54Skamil	BYTES_TRANSFER_AUXV
35331.54Skamil};
35341.31Skamil
35351.54Skamilstatic int __used
35361.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
35371.54Skamil{
35381.54Skamil	int e, f, g, h;
35391.1Skamil
35401.54Skamil	a *= 4;
35411.54Skamil	b += 3;
35421.54Skamil	c -= 2;
35431.54Skamil	d /= 1;
35441.1Skamil
35451.54Skamil	e = strtol("10", NULL, 10);
35461.54Skamil	f = strtol("20", NULL, 10);
35471.54Skamil	g = strtol("30", NULL, 10);
35481.54Skamil	h = strtol("40", NULL, 10);
35491.1Skamil
35501.54Skamil	return (a + b * c - d) + (e * f - g / h);
35511.1Skamil}
35521.1Skamil
35531.54Skamilstatic void
35541.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
35551.1Skamil{
35561.1Skamil	const int exitval = 5;
35571.1Skamil	const int sigval = SIGSTOP;
35581.1Skamil	pid_t child, wpid;
35591.54Skamil	bool skip = false;
35601.1Skamil
35611.54Skamil	int lookup_me = 0;
35621.54Skamil	uint8_t lookup_me8 = 0;
35631.54Skamil	uint16_t lookup_me16 = 0;
35641.54Skamil	uint32_t lookup_me32 = 0;
35651.54Skamil	uint64_t lookup_me64 = 0;
35661.1Skamil
35671.54Skamil	int magic = 0x13579246;
35681.54Skamil	uint8_t magic8 = 0xab;
35691.54Skamil	uint16_t magic16 = 0x1234;
35701.54Skamil	uint32_t magic32 = 0x98765432;
35711.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
35721.1Skamil
35731.54Skamil	struct ptrace_io_desc io;
35741.1Skamil#if defined(TWAIT_HAVE_STATUS)
35751.1Skamil	int status;
35761.1Skamil#endif
35771.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
35781.60Skre	AuxInfo ai[513], *aip;
35791.55Schristos
35801.55Schristos	ATF_REQUIRE(size < sizeof(ai));
35811.1Skamil
35821.54Skamil	/* Prepare variables for .TEXT transfers */
35831.54Skamil	switch (type) {
35841.54Skamil	case BYTES_TRANSFER_TEXT:
35851.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
35861.54Skamil		break;
35871.54Skamil	case BYTES_TRANSFER_TEXTIO:
35881.54Skamil		switch (size) {
35891.54Skamil		case 8:
35901.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
35911.54Skamil			break;
35921.54Skamil		case 16:
35931.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
35941.54Skamil			break;
35951.54Skamil		case 32:
35961.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
35971.54Skamil			break;
35981.54Skamil		case 64:
35991.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
36001.54Skamil			break;
36011.54Skamil		}
36021.54Skamil		break;
36031.54Skamil	default:
36041.54Skamil		break;
36051.54Skamil	}
36061.1Skamil
36071.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
36081.54Skamil	switch (type) {
36091.54Skamil	case BYTES_TRANSFER_TEXTIO:
36101.54Skamil	case BYTES_TRANSFER_DATAIO:
36111.54Skamil		io.piod_op = operation;
36121.54Skamil		switch (size) {
36131.54Skamil		case 8:
36141.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36151.54Skamil			               (void *)bytes_transfer_dummy :
36161.54Skamil			               &lookup_me8;
36171.54Skamil			io.piod_addr = &lookup_me8;
36181.54Skamil			io.piod_len = sizeof(lookup_me8);
36191.54Skamil			break;
36201.54Skamil		case 16:
36211.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36221.54Skamil			               (void *)bytes_transfer_dummy :
36231.54Skamil			               &lookup_me16;
36241.54Skamil			io.piod_addr = &lookup_me16;
36251.54Skamil			io.piod_len = sizeof(lookup_me16);
36261.54Skamil			break;
36271.54Skamil		case 32:
36281.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36291.54Skamil			               (void *)bytes_transfer_dummy :
36301.54Skamil			               &lookup_me32;
36311.54Skamil			io.piod_addr = &lookup_me32;
36321.54Skamil			io.piod_len = sizeof(lookup_me32);
36331.54Skamil			break;
36341.54Skamil		case 64:
36351.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36361.54Skamil			               (void *)bytes_transfer_dummy :
36371.54Skamil			               &lookup_me64;
36381.54Skamil			io.piod_addr = &lookup_me64;
36391.54Skamil			io.piod_len = sizeof(lookup_me64);
36401.54Skamil			break;
36411.54Skamil		default:
36421.54Skamil			break;
36431.54Skamil		}
36441.54Skamil		break;
36451.54Skamil	case BYTES_TRANSFER_AUXV:
36461.54Skamil		io.piod_op = operation;
36471.54Skamil		io.piod_offs = 0;
36481.54Skamil		io.piod_addr = ai;
36491.54Skamil		io.piod_len = size;
36501.54Skamil		break;
36511.54Skamil	default:
36521.54Skamil		break;
36531.1Skamil	}
36541.1Skamil
36551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36571.1Skamil	if (child == 0) {
36581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36601.1Skamil
36611.54Skamil		switch (type) {
36621.54Skamil		case BYTES_TRANSFER_DATA:
36631.54Skamil			switch (operation) {
36641.54Skamil			case PT_READ_D:
36651.54Skamil			case PT_READ_I:
36661.54Skamil				lookup_me = magic;
36671.54Skamil				break;
36681.54Skamil			default:
36691.54Skamil				break;
36701.54Skamil			}
36711.54Skamil			break;
36721.54Skamil		case BYTES_TRANSFER_DATAIO:
36731.54Skamil			switch (operation) {
36741.54Skamil			case PIOD_READ_D:
36751.54Skamil			case PIOD_READ_I:
36761.54Skamil				switch (size) {
36771.54Skamil				case 8:
36781.54Skamil					lookup_me8 = magic8;
36791.54Skamil					break;
36801.54Skamil				case 16:
36811.54Skamil					lookup_me16 = magic16;
36821.54Skamil					break;
36831.54Skamil				case 32:
36841.54Skamil					lookup_me32 = magic32;
36851.54Skamil					break;
36861.54Skamil				case 64:
36871.54Skamil					lookup_me64 = magic64;
36881.54Skamil					break;
36891.54Skamil				default:
36901.54Skamil					break;
36911.54Skamil				}
36921.54Skamil				break;
36931.54Skamil			default:
36941.54Skamil				break;
36951.54Skamil			}
36961.54Skamil		default:
36971.54Skamil			break;
36981.54Skamil		}
36991.54Skamil
37001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37021.1Skamil
37031.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
37041.54Skamil		switch (type) {
37051.54Skamil		case BYTES_TRANSFER_DATA:
37061.54Skamil			switch (operation) {
37071.54Skamil			case PT_WRITE_D:
37081.54Skamil			case PT_WRITE_I:
37091.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
37101.54Skamil				break;
37111.54Skamil			default:
37121.54Skamil				break;
37131.54Skamil			}
37141.54Skamil			break;
37151.54Skamil		case BYTES_TRANSFER_DATAIO:
37161.54Skamil			switch (operation) {
37171.54Skamil			case PIOD_WRITE_D:
37181.54Skamil			case PIOD_WRITE_I:
37191.54Skamil				switch (size) {
37201.54Skamil				case 8:
37211.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
37221.54Skamil					break;
37231.54Skamil				case 16:
37241.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
37251.54Skamil					break;
37261.54Skamil				case 32:
37271.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
37281.54Skamil					break;
37291.54Skamil				case 64:
37301.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
37311.54Skamil					break;
37321.54Skamil				default:
37331.54Skamil					break;
37341.54Skamil				}
37351.54Skamil				break;
37361.54Skamil			default:
37371.54Skamil				break;
37381.54Skamil			}
37391.54Skamil			break;
37401.54Skamil		case BYTES_TRANSFER_TEXT:
37411.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
37421.54Skamil			                     sizeof(magic)) == 0);
37431.54Skamil			break;
37441.54Skamil		case BYTES_TRANSFER_TEXTIO:
37451.54Skamil			switch (size) {
37461.54Skamil			case 8:
37471.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
37481.54Skamil				                     bytes_transfer_dummy,
37491.54Skamil				                     sizeof(magic8)) == 0);
37501.54Skamil				break;
37511.54Skamil			case 16:
37521.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
37531.54Skamil				                     bytes_transfer_dummy,
37541.54Skamil				                     sizeof(magic16)) == 0);
37551.54Skamil				break;
37561.54Skamil			case 32:
37571.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
37581.54Skamil				                     bytes_transfer_dummy,
37591.54Skamil				                     sizeof(magic32)) == 0);
37601.54Skamil				break;
37611.54Skamil			case 64:
37621.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
37631.54Skamil				                     bytes_transfer_dummy,
37641.54Skamil				                     sizeof(magic64)) == 0);
37651.54Skamil				break;
37661.54Skamil			}
37671.54Skamil			break;
37681.54Skamil		default:
37691.54Skamil			break;
37701.54Skamil		}
37711.54Skamil
37721.13Schristos		DPRINTF("Before exiting of the child process\n");
37731.1Skamil		_exit(exitval);
37741.1Skamil	}
37751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37761.1Skamil
37771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37791.1Skamil
37801.1Skamil	validate_status_stopped(status, sigval);
37811.1Skamil
37821.54Skamil	/* Check PaX MPROTECT */
37831.54Skamil	if (!can_we_write_to_text(child)) {
37841.54Skamil		switch (type) {
37851.54Skamil		case BYTES_TRANSFER_TEXTIO:
37861.54Skamil			switch (operation) {
37871.54Skamil			case PIOD_WRITE_D:
37881.54Skamil			case PIOD_WRITE_I:
37891.54Skamil				skip = true;
37901.54Skamil				break;
37911.54Skamil			default:
37921.54Skamil				break;
37931.54Skamil			}
37941.54Skamil			break;
37951.54Skamil		case BYTES_TRANSFER_TEXT:
37961.54Skamil			switch (operation) {
37971.54Skamil			case PT_WRITE_D:
37981.54Skamil			case PT_WRITE_I:
37991.54Skamil				skip = true;
38001.54Skamil				break;
38011.54Skamil			default:
38021.54Skamil				break;
38031.54Skamil			}
38041.54Skamil			break;
38051.54Skamil		default:
38061.54Skamil			break;
38071.54Skamil		}
38081.54Skamil	}
38091.1Skamil
38101.54Skamil	/* Bailout cleanly killing the child process */
38111.54Skamil	if (skip) {
38121.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
38131.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38141.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
38151.54Skamil		                      child);
38161.1Skamil
38171.54Skamil		validate_status_signaled(status, SIGKILL, 0);
38181.1Skamil
38191.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
38201.54Skamil	}
38211.1Skamil
38221.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
38231.54Skamil	       "parent=%d\n", child, getpid());
38241.1Skamil
38251.54Skamil	switch (type) {
38261.54Skamil	case BYTES_TRANSFER_TEXTIO:
38271.54Skamil	case BYTES_TRANSFER_DATAIO:
38281.54Skamil	case BYTES_TRANSFER_AUXV:
38291.54Skamil		switch (operation) {
38301.54Skamil		case PIOD_WRITE_D:
38311.54Skamil		case PIOD_WRITE_I:
38321.54Skamil			switch (size) {
38331.54Skamil			case 8:
38341.54Skamil				lookup_me8 = magic8;
38351.54Skamil				break;
38361.54Skamil			case 16:
38371.54Skamil				lookup_me16 = magic16;
38381.54Skamil				break;
38391.54Skamil			case 32:
38401.54Skamil				lookup_me32 = magic32;
38411.54Skamil				break;
38421.54Skamil			case 64:
38431.54Skamil				lookup_me64 = magic64;
38441.54Skamil				break;
38451.54Skamil			default:
38461.54Skamil				break;
38471.54Skamil			}
38481.54Skamil			break;
38491.54Skamil		default:
38501.54Skamil			break;
38511.54Skamil		}
38521.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
38531.54Skamil		switch (operation) {
38541.54Skamil		case PIOD_READ_D:
38551.54Skamil		case PIOD_READ_I:
38561.54Skamil			switch (size) {
38571.54Skamil			case 8:
38581.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
38591.54Skamil				break;
38601.54Skamil			case 16:
38611.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
38621.54Skamil				break;
38631.54Skamil			case 32:
38641.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
38651.54Skamil				break;
38661.54Skamil			case 64:
38671.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
38681.54Skamil				break;
38691.54Skamil			default:
38701.54Skamil				break;
38711.54Skamil			}
38721.54Skamil			break;
38731.54Skamil		case PIOD_READ_AUXV:
38741.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
38751.54Skamil			        io.piod_len);
38761.54Skamil			ATF_REQUIRE(io.piod_len > 0);
38771.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
38781.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
38791.54Skamil				    (long long int)aip->a_type,
38801.54Skamil				    (long long int)aip->a_v);
38811.54Skamil			break;
38821.54Skamil		default:
38831.54Skamil			break;
38841.54Skamil		}
38851.54Skamil		break;
38861.54Skamil	case BYTES_TRANSFER_TEXT:
38871.54Skamil		switch (operation) {
38881.54Skamil		case PT_READ_D:
38891.54Skamil		case PT_READ_I:
38901.54Skamil			errno = 0;
38911.54Skamil			lookup_me = ptrace(operation, child,
38921.54Skamil			                   bytes_transfer_dummy, 0);
38931.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
38941.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
38951.54Skamil			break;
38961.54Skamil		case PT_WRITE_D:
38971.54Skamil		case PT_WRITE_I:
38981.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
38991.54Skamil			                       bytes_transfer_dummy, magic)
39001.54Skamil			                != -1);
39011.54Skamil			break;
39021.54Skamil		default:
39031.54Skamil			break;
39041.54Skamil		}
39051.54Skamil		break;
39061.54Skamil	case BYTES_TRANSFER_DATA:
39071.54Skamil		switch (operation) {
39081.54Skamil		case PT_READ_D:
39091.54Skamil		case PT_READ_I:
39101.54Skamil			errno = 0;
39111.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
39121.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
39131.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
39141.54Skamil			break;
39151.54Skamil		case PT_WRITE_D:
39161.54Skamil		case PT_WRITE_I:
39171.54Skamil			lookup_me = magic;
39181.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
39191.54Skamil			                       magic) != -1);
39201.54Skamil			break;
39211.54Skamil		default:
39221.54Skamil			break;
39231.54Skamil		}
39241.54Skamil		break;
39251.54Skamil	default:
39261.54Skamil		break;
39271.54Skamil	}
39281.1Skamil
39291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39301.1Skamil	    "without signal to be sent\n");
39311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39321.1Skamil
39331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39351.1Skamil
39361.1Skamil	validate_status_exited(status, exitval);
39371.1Skamil
39381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39401.1Skamil}
39411.1Skamil
39421.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
39431.61SkreATF_TC(test);								\
39441.61SkreATF_TC_HEAD(test, tc)							\
39451.61Skre{									\
39461.61Skre	atf_tc_set_md_var(tc, "descr",					\
39471.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
39481.61Skre	    " of type " #type);						\
39491.61Skre}									\
39501.61Skre									\
39511.61SkreATF_TC_BODY(test, tc)							\
39521.61Skre{									\
39531.61Skre									\
39541.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
39551.1Skamil}
39561.1Skamil
39571.54Skamil// DATA
39581.1Skamil
39591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
39601.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
39611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
39621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
39631.54Skamil
39641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
39651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
39661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
39671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
39681.54Skamil
39691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
39701.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
39711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
39721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
39731.54Skamil
39741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
39751.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
39761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
39771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
39781.54Skamil
39791.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
39801.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
39811.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
39821.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
39831.54Skamil
39841.54Skamil// TEXT
39851.54Skamil
39861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
39871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
39881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
39891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
39901.54Skamil
39911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
39921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
39931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
39941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
39951.54Skamil
39961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
39971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
39981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
39991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
40001.54Skamil
40011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
40021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
40031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
40041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
40051.54Skamil
40061.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
40071.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
40081.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
40091.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
40101.1Skamil
40111.54Skamil// AUXV
40121.1Skamil
40131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
40141.1Skamil
40151.54Skamil/// ----------------------------------------------------------------------------
40161.1Skamil
40171.101Skamilstatic void
40181.101Skamilbytes_transfer_alignment(const char *operation)
40191.101Skamil{
40201.101Skamil	const int exitval = 5;
40211.101Skamil	const int sigval = SIGSTOP;
40221.101Skamil	pid_t child, wpid;
40231.101Skamil#if defined(TWAIT_HAVE_STATUS)
40241.101Skamil	int status;
40251.101Skamil#endif
40261.101Skamil	char *buffer;
40271.101Skamil	int vector;
40281.101Skamil	size_t len;
40291.101Skamil	size_t i;
40301.101Skamil	int op;
40311.101Skamil
40321.101Skamil	struct ptrace_io_desc io;
40331.101Skamil	struct ptrace_siginfo info;
40341.101Skamil
40351.101Skamil	memset(&io, 0, sizeof(io));
40361.101Skamil	memset(&info, 0, sizeof(info));
40371.101Skamil
40381.101Skamil	/* Testing misaligned byte transfer crossing page boundaries */
40391.101Skamil	len = sysconf(_SC_PAGESIZE) * 2;
40401.101Skamil	buffer = malloc(len);
40411.101Skamil	ATF_REQUIRE(buffer != NULL);
40421.101Skamil
40431.101Skamil	/* Initialize the buffer with random data */
40441.101Skamil	for (i = 0; i < len; i++)
40451.101Skamil		buffer[i] = i & 0xff;
40461.101Skamil
40471.101Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
40481.101Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
40491.101Skamil	if (child == 0) {
40501.101Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40511.101Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40521.101Skamil
40531.101Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40541.101Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40551.101Skamil
40561.101Skamil		DPRINTF("Before exiting of the child process\n");
40571.101Skamil		_exit(exitval);
40581.101Skamil	}
40591.101Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40601.101Skamil
40611.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40621.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40631.101Skamil
40641.101Skamil	validate_status_stopped(status, sigval);
40651.101Skamil
40661.101Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40671.101Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
40681.101Skamil		!= -1);
40691.101Skamil
40701.101Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
40711.101Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
40721.101Skamil		"si_errno=%#x\n",
40731.101Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
40741.101Skamil		info.psi_siginfo.si_errno);
40751.101Skamil
40761.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
40771.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
40781.101Skamil
40791.101Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
40801.101Skamil	    strcmp(operation, "PT_READ_D") == 0) {
40811.101Skamil		if (strcmp(operation, "PT_READ_I"))
40821.101Skamil			op = PT_READ_I;
40831.101Skamil		else
40841.101Skamil			op = PT_READ_D;
40851.101Skamil
40861.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
40871.101Skamil			errno = 0;
40881.101Skamil			vector = ptrace(op, child, buffer + i, 0);
40891.101Skamil			ATF_REQUIRE_EQ(errno, 0);
40901.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
40911.101Skamil		}
40921.101Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
40931.101Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
40941.101Skamil		if (strcmp(operation, "PT_WRITE_I"))
40951.101Skamil			op = PT_WRITE_I;
40961.101Skamil		else
40971.101Skamil			op = PT_WRITE_D;
40981.101Skamil
40991.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41001.101Skamil			memcpy(&vector, buffer + i, sizeof(int));
41011.101Skamil			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
41021.101Skamil			    != -1);
41031.101Skamil		}
41041.101Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
41051.101Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
41061.101Skamil		if (strcmp(operation, "PIOD_READ_I"))
41071.101Skamil			op = PIOD_READ_I;
41081.101Skamil		else
41091.101Skamil			op = PIOD_READ_D;
41101.101Skamil
41111.101Skamil		io.piod_op = op;
41121.101Skamil		io.piod_addr = &vector;
41131.101Skamil		io.piod_len = sizeof(int);
41141.101Skamil
41151.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41161.101Skamil			io.piod_offs = buffer + i;
41171.101Skamil
41181.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
41191.101Skamil			                != -1);
41201.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
41211.101Skamil		}
41221.101Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
41231.101Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
41241.101Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
41251.101Skamil			op = PIOD_WRITE_I;
41261.101Skamil		else
41271.101Skamil			op = PIOD_WRITE_D;
41281.101Skamil
41291.101Skamil		io.piod_op = op;
41301.101Skamil		io.piod_addr = &vector;
41311.101Skamil		io.piod_len = sizeof(int);
41321.101Skamil
41331.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41341.101Skamil			io.piod_offs = buffer + i;
41351.101Skamil
41361.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
41371.101Skamil			                != -1);
41381.101Skamil		}
41391.101Skamil	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
41401.101Skamil		io.piod_op = PIOD_READ_AUXV;
41411.101Skamil		io.piod_addr = &vector;
41421.101Skamil		io.piod_len = sizeof(int);
41431.101Skamil
41441.101Skamil		errno = 0;
41451.101Skamil		i = 0;
41461.101Skamil		/* Read the whole AUXV vector, it has no clear length */
41471.120Skamil		while (io.piod_len > 0) {
41481.101Skamil			io.piod_offs = (void *)(intptr_t)i;
41491.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
41501.120Skamil			                != -1 || (io.piod_len == 0 && i > 0));
41511.101Skamil			++i;
41521.101Skamil		}
41531.101Skamil	}
41541.101Skamil
41551.101Skamil	DPRINTF("Before resuming the child process where it left off "
41561.101Skamil	    "and without signal to be sent\n");
41571.101Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41581.101Skamil
41591.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41601.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
41611.101Skamil	    child);
41621.101Skamil
41631.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41641.101Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41651.101Skamil}
41661.101Skamil
41671.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
41681.101SkamilATF_TC(test);								\
41691.101SkamilATF_TC_HEAD(test, tc)							\
41701.101Skamil{									\
41711.101Skamil	atf_tc_set_md_var(tc, "descr",					\
41721.101Skamil	    "Verify bytes transfer for potentially misaligned "		\
41731.101Skamil	    "operation " operation);					\
41741.101Skamil}									\
41751.101Skamil									\
41761.101SkamilATF_TC_BODY(test, tc)							\
41771.101Skamil{									\
41781.101Skamil									\
41791.101Skamil	bytes_transfer_alignment(operation);				\
41801.101Skamil}
41811.101Skamil
41821.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
41831.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
41841.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
41851.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
41861.101Skamil
41871.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
41881.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
41891.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
41901.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
41911.101Skamil
41921.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
41931.101Skamil
41941.101Skamil/// ----------------------------------------------------------------------------
41951.101Skamil
41961.115Skamilstatic void
41971.115Skamilbytes_transfer_eof(const char *operation)
41981.115Skamil{
41991.115Skamil	const int exitval = 5;
42001.115Skamil	const int sigval = SIGSTOP;
42011.115Skamil	pid_t child, wpid;
42021.115Skamil#if defined(TWAIT_HAVE_STATUS)
42031.115Skamil	int status;
42041.115Skamil#endif
42051.115Skamil	FILE *fp;
42061.115Skamil	char *p;
42071.115Skamil	int vector;
42081.115Skamil	int op;
42091.115Skamil
42101.115Skamil	struct ptrace_io_desc io;
42111.115Skamil	struct ptrace_siginfo info;
42121.115Skamil
42131.115Skamil	memset(&io, 0, sizeof(io));
42141.115Skamil	memset(&info, 0, sizeof(info));
42151.115Skamil
42161.115Skamil	vector = 0;
42171.115Skamil
42181.115Skamil	fp = tmpfile();
42191.115Skamil	ATF_REQUIRE(fp != NULL);
42201.115Skamil
42211.115Skamil	p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
42221.115Skamil	ATF_REQUIRE(p != MAP_FAILED);
42231.115Skamil
42241.115Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
42251.115Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
42261.115Skamil	if (child == 0) {
42271.115Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42281.115Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42291.115Skamil
42301.115Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42311.115Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42321.115Skamil
42331.115Skamil		DPRINTF("Before exiting of the child process\n");
42341.115Skamil		_exit(exitval);
42351.115Skamil	}
42361.115Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42371.115Skamil
42381.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42391.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42401.115Skamil
42411.115Skamil	validate_status_stopped(status, sigval);
42421.115Skamil
42431.115Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
42441.115Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
42451.115Skamil		!= -1);
42461.115Skamil
42471.115Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
42481.115Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
42491.115Skamil		"si_errno=%#x\n",
42501.115Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
42511.115Skamil		info.psi_siginfo.si_errno);
42521.115Skamil
42531.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
42541.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
42551.115Skamil
42561.115Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
42571.115Skamil	    strcmp(operation, "PT_READ_D") == 0) {
42581.115Skamil		if (strcmp(operation, "PT_READ_I"))
42591.115Skamil			op = PT_READ_I;
42601.115Skamil		else
42611.115Skamil			op = PT_READ_D;
42621.115Skamil
42631.115Skamil		errno = 0;
42641.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1);
42651.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42661.115Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
42671.115Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
42681.115Skamil		if (strcmp(operation, "PT_WRITE_I"))
42691.115Skamil			op = PT_WRITE_I;
42701.115Skamil		else
42711.115Skamil			op = PT_WRITE_D;
42721.115Skamil
42731.115Skamil		errno = 0;
42741.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1);
42751.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42761.115Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
42771.115Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
42781.115Skamil		if (strcmp(operation, "PIOD_READ_I"))
42791.115Skamil			op = PIOD_READ_I;
42801.115Skamil		else
42811.115Skamil			op = PIOD_READ_D;
42821.115Skamil
42831.115Skamil		io.piod_op = op;
42841.115Skamil		io.piod_addr = &vector;
42851.115Skamil		io.piod_len = sizeof(int);
42861.115Skamil		io.piod_offs = p;
42871.115Skamil
42881.115Skamil		errno = 0;
42891.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
42901.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42911.115Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
42921.115Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
42931.115Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
42941.115Skamil			op = PIOD_WRITE_I;
42951.115Skamil		else
42961.115Skamil			op = PIOD_WRITE_D;
42971.115Skamil
42981.115Skamil		io.piod_op = op;
42991.115Skamil		io.piod_addr = &vector;
43001.115Skamil		io.piod_len = sizeof(int);
43011.115Skamil		io.piod_offs = p;
43021.115Skamil
43031.115Skamil		errno = 0;
43041.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
43051.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
43061.115Skamil	}
43071.115Skamil
43081.115Skamil	DPRINTF("Before resuming the child process where it left off "
43091.115Skamil	    "and without signal to be sent\n");
43101.115Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43111.115Skamil
43121.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43131.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
43141.115Skamil	    child);
43151.115Skamil
43161.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43171.115Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43181.115Skamil}
43191.115Skamil
43201.115Skamil#define BYTES_TRANSFER_EOF(test, operation)				\
43211.115SkamilATF_TC(test);								\
43221.115SkamilATF_TC_HEAD(test, tc)							\
43231.115Skamil{									\
43241.115Skamil	atf_tc_set_md_var(tc, "descr",					\
43251.115Skamil	    "Verify bytes EOF byte transfer for the " operation		\
43261.115Skamil	    " operation");						\
43271.115Skamil}									\
43281.115Skamil									\
43291.115SkamilATF_TC_BODY(test, tc)							\
43301.115Skamil{									\
43311.115Skamil									\
43321.115Skamil	bytes_transfer_eof(operation);					\
43331.115Skamil}
43341.115Skamil
43351.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I")
43361.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D")
43371.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I")
43381.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D")
43391.115Skamil
43401.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I")
43411.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D")
43421.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I")
43431.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D")
43441.115Skamil
43451.115Skamil/// ----------------------------------------------------------------------------
43461.115Skamil
43471.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
43481.72Skamilstatic void
43491.72Skamilaccess_regs(const char *regset, const char *aux)
43501.1Skamil{
43511.1Skamil	const int exitval = 5;
43521.1Skamil	const int sigval = SIGSTOP;
43531.1Skamil	pid_t child, wpid;
43541.1Skamil#if defined(TWAIT_HAVE_STATUS)
43551.1Skamil	int status;
43561.1Skamil#endif
43571.72Skamil#if defined(HAVE_GPREGS)
43581.72Skamil	struct reg gpr;
43591.76Sscole	register_t rgstr;
43601.1Skamil#endif
43611.72Skamil#if defined(HAVE_FPREGS)
43621.72Skamil	struct fpreg fpr;
43631.1Skamil#endif
43641.76Sscole
43651.72Skamil#if !defined(HAVE_GPREGS)
43661.72Skamil	if (strcmp(regset, "regs") == 0)
43671.72Skamil		atf_tc_fail("Impossible test scenario!");
43681.1Skamil#endif
43691.1Skamil
43701.72Skamil#if !defined(HAVE_FPREGS)
43711.72Skamil	if (strcmp(regset, "fpregs") == 0)
43721.72Skamil		atf_tc_fail("Impossible test scenario!");
43731.1Skamil#endif
43741.1Skamil
43751.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43761.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43771.1Skamil	if (child == 0) {
43781.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43791.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43801.1Skamil
43811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43831.1Skamil
43841.13Schristos		DPRINTF("Before exiting of the child process\n");
43851.1Skamil		_exit(exitval);
43861.1Skamil	}
43871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43881.1Skamil
43891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43911.1Skamil
43921.1Skamil	validate_status_stopped(status, sigval);
43931.1Skamil
43941.1Skamil#if defined(HAVE_GPREGS)
43951.72Skamil	if (strcmp(regset, "regs") == 0) {
43961.72Skamil		DPRINTF("Call GETREGS for the child process\n");
43971.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
43981.72Skamil
43991.72Skamil		if (strcmp(aux, "none") == 0) {
44001.72Skamil			DPRINTF("Retrieved registers\n");
44011.72Skamil		} else if (strcmp(aux, "pc") == 0) {
44021.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
44031.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44041.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
44051.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
44061.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
44071.72Skamil		} else if (strcmp(aux, "sp") == 0) {
44081.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
44091.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44101.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
44111.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
44121.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44131.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
44141.72Skamil			DPRINTF("Call SETREGS for the child process\n");
44151.72Skamil			SYSCALL_REQUIRE(
44161.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
44171.72Skamil		}
44181.72Skamil	}
44191.1Skamil#endif
44201.1Skamil
44211.72Skamil#if defined(HAVE_FPREGS)
44221.72Skamil	if (strcmp(regset, "fpregs") == 0) {
44231.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
44241.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
44251.72Skamil
44261.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
44271.72Skamil			DPRINTF("Retrieved FP registers\n");
44281.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
44291.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
44301.72Skamil			SYSCALL_REQUIRE(
44311.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
44321.72Skamil		}
44331.1Skamil	}
44341.1Skamil#endif
44351.1Skamil
44361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44371.1Skamil	    "without signal to be sent\n");
44381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44391.1Skamil
44401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44421.1Skamil
44431.1Skamil	validate_status_exited(status, exitval);
44441.1Skamil
44451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44471.1Skamil}
44481.1Skamil
44491.72Skamil#define ACCESS_REGS(test, regset, aux)					\
44501.72SkamilATF_TC(test);								\
44511.72SkamilATF_TC_HEAD(test, tc)							\
44521.72Skamil{									\
44531.72Skamil        atf_tc_set_md_var(tc, "descr",					\
44541.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
44551.72Skamil}									\
44561.72Skamil									\
44571.72SkamilATF_TC_BODY(test, tc)							\
44581.72Skamil{									\
44591.72Skamil									\
44601.72Skamil        access_regs(regset, aux);					\
44611.1Skamil}
44621.1Skamil#endif
44631.1Skamil
44641.72Skamil#if defined(HAVE_GPREGS)
44651.72SkamilACCESS_REGS(access_regs1, "regs", "none")
44661.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
44671.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
44681.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
44691.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
44701.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
44711.1Skamil#endif
44721.1Skamil#if defined(HAVE_FPREGS)
44731.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
44741.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
44751.1Skamil#endif
44761.1Skamil
44771.72Skamil/// ----------------------------------------------------------------------------
44781.1Skamil
44791.1Skamil#if defined(PT_STEP)
44801.1Skamilstatic void
44811.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
44821.1Skamil{
44831.1Skamil	const int exitval = 5;
44841.1Skamil	const int sigval = SIGSTOP;
44851.1Skamil	pid_t child, wpid;
44861.1Skamil#if defined(TWAIT_HAVE_STATUS)
44871.1Skamil	int status;
44881.1Skamil#endif
44891.1Skamil	int happy;
44901.95Skamil	struct sigaction sa;
44911.81Skamil	struct ptrace_siginfo info;
44921.95Skamil	sigset_t intmask;
44931.95Skamil	struct kinfo_proc2 kp;
44941.95Skamil	size_t len = sizeof(kp);
44951.95Skamil
44961.95Skamil	int name[6];
44971.95Skamil	const size_t namelen = __arraycount(name);
44981.95Skamil	ki_sigset_t kp_sigmask;
44991.95Skamil	ki_sigset_t kp_sigignore;
45001.1Skamil
45011.1Skamil#if defined(__arm__)
45021.1Skamil	/* PT_STEP not supported on arm 32-bit */
45031.1Skamil	atf_tc_expect_fail("PR kern/52119");
45041.1Skamil#endif
45051.1Skamil
45061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45081.1Skamil	if (child == 0) {
45091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45111.1Skamil
45121.95Skamil		if (masked) {
45131.95Skamil			sigemptyset(&intmask);
45141.95Skamil			sigaddset(&intmask, SIGTRAP);
45151.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
45161.95Skamil		}
45171.95Skamil
45181.95Skamil		if (ignored) {
45191.95Skamil			memset(&sa, 0, sizeof(sa));
45201.95Skamil			sa.sa_handler = SIG_IGN;
45211.95Skamil			sigemptyset(&sa.sa_mask);
45221.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
45231.95Skamil		}
45241.95Skamil
45251.1Skamil		happy = check_happy(999);
45261.1Skamil
45271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45291.1Skamil
45301.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
45311.1Skamil
45321.13Schristos		DPRINTF("Before exiting of the child process\n");
45331.1Skamil		_exit(exitval);
45341.1Skamil	}
45351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45361.1Skamil
45371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45391.1Skamil
45401.1Skamil	validate_status_stopped(status, sigval);
45411.1Skamil
45421.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45431.81Skamil	SYSCALL_REQUIRE(
45441.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45451.81Skamil
45461.81Skamil	DPRINTF("Before checking siginfo_t\n");
45471.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
45481.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
45491.81Skamil
45501.95Skamil	name[0] = CTL_KERN,
45511.95Skamil	name[1] = KERN_PROC2,
45521.95Skamil	name[2] = KERN_PROC_PID;
45531.95Skamil	name[3] = child;
45541.95Skamil	name[4] = sizeof(kp);
45551.95Skamil	name[5] = 1;
45561.95Skamil
45571.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
45581.95Skamil
45591.95Skamil	if (masked)
45601.95Skamil		kp_sigmask = kp.p_sigmask;
45611.95Skamil
45621.95Skamil	if (ignored)
45631.95Skamil		kp_sigignore = kp.p_sigignore;
45641.95Skamil
45651.1Skamil	while (N --> 0) {
45661.2Skamil		if (setstep) {
45671.13Schristos			DPRINTF("Before resuming the child process where it "
45681.2Skamil			    "left off and without signal to be sent (use "
45691.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
45701.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
45711.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
45721.2Skamil			    != -1);
45731.2Skamil		} else {
45741.13Schristos			DPRINTF("Before resuming the child process where it "
45751.2Skamil			    "left off and without signal to be sent (use "
45761.2Skamil			    "PT_STEP)\n");
45771.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
45781.2Skamil			    != -1);
45791.2Skamil		}
45801.1Skamil
45811.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45821.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
45831.1Skamil		    child);
45841.1Skamil
45851.1Skamil		validate_status_stopped(status, SIGTRAP);
45861.2Skamil
45871.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45881.81Skamil		SYSCALL_REQUIRE(
45891.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45901.81Skamil
45911.81Skamil		DPRINTF("Before checking siginfo_t\n");
45921.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
45931.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
45941.81Skamil
45951.2Skamil		if (setstep) {
45961.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
45971.2Skamil		}
45981.95Skamil
45991.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
46001.95Skamil
46011.95Skamil		if (masked) {
46021.95Skamil			DPRINTF("kp_sigmask="
46031.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46041.95Skamil			    PRIx32 "\n",
46051.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
46061.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
46071.95Skamil
46081.95Skamil			DPRINTF("kp.p_sigmask="
46091.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46101.95Skamil			    PRIx32 "\n",
46111.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
46121.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
46131.95Skamil
46141.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
46151.95Skamil			    sizeof(kp_sigmask)));
46161.95Skamil		}
46171.95Skamil
46181.95Skamil		if (ignored) {
46191.95Skamil			DPRINTF("kp_sigignore="
46201.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46211.95Skamil			    PRIx32 "\n",
46221.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
46231.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
46241.95Skamil
46251.95Skamil			DPRINTF("kp.p_sigignore="
46261.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46271.95Skamil			    PRIx32 "\n",
46281.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
46291.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
46301.95Skamil
46311.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
46321.95Skamil			    sizeof(kp_sigignore)));
46331.95Skamil		}
46341.1Skamil	}
46351.1Skamil
46361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46371.1Skamil	    "without signal to be sent\n");
46381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46391.1Skamil
46401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46421.1Skamil
46431.1Skamil	validate_status_exited(status, exitval);
46441.1Skamil
46451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46471.1Skamil}
46481.1Skamil
46491.73Skamil#define PTRACE_STEP(test, N, setstep)					\
46501.73SkamilATF_TC(test);								\
46511.73SkamilATF_TC_HEAD(test, tc)							\
46521.73Skamil{									\
46531.73Skamil        atf_tc_set_md_var(tc, "descr",					\
46541.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
46551.73Skamil}									\
46561.73Skamil									\
46571.73SkamilATF_TC_BODY(test, tc)							\
46581.73Skamil{									\
46591.73Skamil									\
46601.95Skamil        ptrace_step(N, setstep, false, false);				\
46611.1Skamil}
46621.1Skamil
46631.73SkamilPTRACE_STEP(step1, 1, 0)
46641.73SkamilPTRACE_STEP(step2, 2, 0)
46651.73SkamilPTRACE_STEP(step3, 3, 0)
46661.73SkamilPTRACE_STEP(step4, 4, 0)
46671.73SkamilPTRACE_STEP(setstep1, 1, 1)
46681.73SkamilPTRACE_STEP(setstep2, 2, 1)
46691.73SkamilPTRACE_STEP(setstep3, 3, 1)
46701.73SkamilPTRACE_STEP(setstep4, 4, 1)
46711.95Skamil
46721.95SkamilATF_TC(step_signalmasked);
46731.95SkamilATF_TC_HEAD(step_signalmasked, tc)
46741.95Skamil{
46751.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
46761.95Skamil}
46771.95Skamil
46781.95SkamilATF_TC_BODY(step_signalmasked, tc)
46791.95Skamil{
46801.95Skamil
46811.95Skamil	ptrace_step(1, 0, true, false);
46821.95Skamil}
46831.95Skamil
46841.95SkamilATF_TC(step_signalignored);
46851.95SkamilATF_TC_HEAD(step_signalignored, tc)
46861.95Skamil{
46871.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
46881.95Skamil}
46891.95Skamil
46901.95SkamilATF_TC_BODY(step_signalignored, tc)
46911.95Skamil{
46921.95Skamil
46931.95Skamil	ptrace_step(1, 0, false, true);
46941.95Skamil}
46951.1Skamil#endif
46961.1Skamil
46971.73Skamil/// ----------------------------------------------------------------------------
46981.1Skamil
46991.75Skamilstatic void
47001.75Skamilptrace_kill(const char *type)
47011.1Skamil{
47021.75Skamil	const int sigval = SIGSTOP;
47031.1Skamil	pid_t child, wpid;
47041.1Skamil#if defined(TWAIT_HAVE_STATUS)
47051.1Skamil	int status;
47061.1Skamil#endif
47071.1Skamil
47081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47101.1Skamil	if (child == 0) {
47111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47131.1Skamil
47141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47161.1Skamil
47171.1Skamil		/* NOTREACHED */
47181.1Skamil		FORKEE_ASSERTX(0 &&
47191.1Skamil		    "Child should be terminated by a signal from its parent");
47201.1Skamil	}
47211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47221.1Skamil
47231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47251.1Skamil
47261.1Skamil	validate_status_stopped(status, sigval);
47271.1Skamil
47281.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
47291.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
47301.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
47311.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
47321.75Skamil		kill(child, SIGKILL);
47331.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
47341.75Skamil		setpgid(child, 0);
47351.75Skamil		killpg(getpgid(child), SIGKILL);
47361.75Skamil	}
47371.1Skamil
47381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47401.1Skamil
47411.75Skamil	validate_status_signaled(status, SIGKILL, 0);
47421.1Skamil
47431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47451.1Skamil}
47461.1Skamil
47471.75Skamil#define PTRACE_KILL(test, type)						\
47481.75SkamilATF_TC(test);								\
47491.75SkamilATF_TC_HEAD(test, tc)							\
47501.75Skamil{									\
47511.75Skamil        atf_tc_set_md_var(tc, "descr",					\
47521.75Skamil            "Verify killing the child with " type);			\
47531.75Skamil}									\
47541.75Skamil									\
47551.75SkamilATF_TC_BODY(test, tc)							\
47561.75Skamil{									\
47571.75Skamil									\
47581.75Skamil        ptrace_kill(type);						\
47591.1Skamil}
47601.1Skamil
47611.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
47621.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
47631.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
47641.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
47651.1Skamil
47661.75Skamil/// ----------------------------------------------------------------------------
47671.1Skamil
47681.77Skamilstatic void
47691.77Skamiltraceme_lwpinfo(const int threads)
47701.1Skamil{
47711.1Skamil	const int sigval = SIGSTOP;
47721.77Skamil	const int sigval2 = SIGINT;
47731.1Skamil	pid_t child, wpid;
47741.1Skamil#if defined(TWAIT_HAVE_STATUS)
47751.1Skamil	int status;
47761.1Skamil#endif
47771.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
47781.77Skamil	struct ptrace_siginfo info;
47791.77Skamil
47801.77Skamil	/* Maximum number of supported threads in this test */
47811.77Skamil	pthread_t t[3];
47821.77Skamil	int n, rv;
47831.77Skamil
47841.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
47851.1Skamil
47861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47881.1Skamil	if (child == 0) {
47891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47911.1Skamil
47921.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47931.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47941.1Skamil
47951.77Skamil		for (n = 0; n < threads; n++) {
47961.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
47971.77Skamil			FORKEE_ASSERT(rv == 0);
47981.77Skamil		}
47991.77Skamil
48001.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
48011.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
48021.77Skamil
48031.77Skamil		/* NOTREACHED */
48041.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
48051.1Skamil	}
48061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48071.1Skamil
48081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48101.1Skamil
48111.1Skamil	validate_status_stopped(status, sigval);
48121.1Skamil
48131.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
48141.77Skamil	SYSCALL_REQUIRE(
48151.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48161.77Skamil
48171.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48181.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48191.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48201.77Skamil	    info.psi_siginfo.si_errno);
48211.77Skamil
48221.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
48231.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
48241.77Skamil
48251.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48261.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48271.1Skamil
48281.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
48291.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
48301.1Skamil
48311.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
48321.77Skamil	    lwp.pl_lwpid);
48331.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
48341.1Skamil
48351.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48361.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48371.1Skamil
48381.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
48391.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
48401.1Skamil
48411.13Schristos	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\n", TWAIT_FNAME);
48461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48471.1Skamil
48481.77Skamil	validate_status_stopped(status, sigval2);
48491.77Skamil
48501.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
48511.77Skamil	SYSCALL_REQUIRE(
48521.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48531.77Skamil
48541.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48551.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48561.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48571.77Skamil	    info.psi_siginfo.si_errno);
48581.77Skamil
48591.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
48601.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
48611.77Skamil
48621.77Skamil	memset(&lwp, 0, sizeof(lwp));
48631.77Skamil
48641.77Skamil	for (n = 0; n <= threads; n++) {
48651.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48661.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48671.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
48681.77Skamil
48691.77Skamil		DPRINTF("Assert that the thread exists\n");
48701.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
48711.77Skamil
48721.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
48731.77Skamil		    lwp.pl_lwpid);
48741.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
48751.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
48761.77Skamil	}
48771.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48781.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48791.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
48801.77Skamil
48811.77Skamil	DPRINTF("Assert that there are no more threads\n");
48821.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
48831.77Skamil
48841.77Skamil	DPRINTF("Before resuming the child process where it left off and "
48851.77Skamil	    "without signal to be sent\n");
48861.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
48871.77Skamil
48881.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48891.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48901.77Skamil
48911.77Skamil	validate_status_signaled(status, SIGKILL, 0);
48921.1Skamil
48931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48951.1Skamil}
48961.1Skamil
48971.77Skamil#define TRACEME_LWPINFO(test, threads)					\
48981.77SkamilATF_TC(test);								\
48991.77SkamilATF_TC_HEAD(test, tc)							\
49001.77Skamil{									\
49011.77Skamil	atf_tc_set_md_var(tc, "descr",					\
49021.77Skamil	    "Verify LWPINFO with the child with " #threads		\
49031.77Skamil	    " spawned extra threads");					\
49041.77Skamil}									\
49051.77Skamil									\
49061.77SkamilATF_TC_BODY(test, tc)							\
49071.77Skamil{									\
49081.77Skamil									\
49091.77Skamil	traceme_lwpinfo(threads);					\
49101.1Skamil}
49111.1Skamil
49121.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
49131.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
49141.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
49151.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
49161.77Skamil
49171.77Skamil/// ----------------------------------------------------------------------------
49181.77Skamil
49191.77Skamil#if defined(TWAIT_HAVE_PID)
49201.77Skamilstatic void
49211.77Skamilattach_lwpinfo(const int threads)
49221.1Skamil{
49231.77Skamil	const int sigval = SIGINT;
49241.1Skamil	struct msg_fds parent_tracee, parent_tracer;
49251.1Skamil	const int exitval_tracer = 10;
49261.1Skamil	pid_t tracee, tracer, wpid;
49271.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
49281.1Skamil#if defined(TWAIT_HAVE_STATUS)
49291.1Skamil	int status;
49301.1Skamil#endif
49311.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
49321.77Skamil	struct ptrace_siginfo info;
49331.77Skamil
49341.77Skamil	/* Maximum number of supported threads in this test */
49351.77Skamil	pthread_t t[3];
49361.77Skamil	int n, rv;
49371.1Skamil
49381.13Schristos	DPRINTF("Spawn tracee\n");
49391.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
49401.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
49411.1Skamil	tracee = atf_utils_fork();
49421.1Skamil	if (tracee == 0) {
49431.1Skamil		/* Wait for message from the parent */
49441.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
49451.1Skamil
49461.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
49471.77Skamil
49481.77Skamil		for (n = 0; n < threads; n++) {
49491.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
49501.77Skamil			FORKEE_ASSERT(rv == 0);
49511.77Skamil		}
49521.77Skamil
49531.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
49541.77Skamil
49551.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49561.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49571.77Skamil
49581.77Skamil		/* NOTREACHED */
49591.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
49601.1Skamil	}
49611.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
49621.1Skamil
49631.13Schristos	DPRINTF("Spawn debugger\n");
49641.1Skamil	tracer = atf_utils_fork();
49651.1Skamil	if (tracer == 0) {
49661.1Skamil		/* No IPC to communicate with the child */
49671.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
49681.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
49691.1Skamil
49701.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
49711.1Skamil		FORKEE_REQUIRE_SUCCESS(
49721.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
49731.1Skamil
49741.1Skamil		forkee_status_stopped(status, SIGSTOP);
49751.1Skamil
49761.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
49771.77Skamil		    "tracee");
49781.77Skamil		FORKEE_ASSERT(
49791.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
49801.77Skamil
49811.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49821.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
49831.77Skamil		    "si_errno=%#x\n",
49841.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49851.77Skamil		    info.psi_siginfo.si_errno);
49861.77Skamil
49871.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
49881.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
49891.77Skamil
49901.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
49911.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
49921.1Skamil		    != -1);
49931.1Skamil
49941.13Schristos		DPRINTF("Assert that there exists a thread\n");
49951.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
49961.1Skamil
49971.13Schristos		DPRINTF("Assert that lwp thread %d received event "
49981.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
49991.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
50001.1Skamil
50011.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50021.77Skamil		    "tracee\n");
50031.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
50041.1Skamil		    != -1);
50051.1Skamil
50061.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
50071.77Skamil		    "tracee\n");
50081.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
50091.1Skamil
50101.1Skamil		/* Resume tracee with PT_CONTINUE */
50111.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
50121.1Skamil
50131.1Skamil		/* Inform parent that tracer has attached to tracee */
50141.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
50151.77Skamil
50161.1Skamil		/* Wait for parent */
50171.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
50181.1Skamil
50191.77Skamil		/* Wait for tracee and assert that it raised a signal */
50201.77Skamil		FORKEE_REQUIRE_SUCCESS(
50211.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
50221.77Skamil
50231.77Skamil		forkee_status_stopped(status, SIGINT);
50241.77Skamil
50251.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
50261.77Skamil		    "child");
50271.77Skamil		FORKEE_ASSERT(
50281.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
50291.77Skamil
50301.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50311.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50321.77Skamil		    "si_errno=%#x\n",
50331.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50341.77Skamil		    info.psi_siginfo.si_errno);
50351.77Skamil
50361.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
50371.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
50381.77Skamil
50391.77Skamil		memset(&lwp, 0, sizeof(lwp));
50401.77Skamil
50411.77Skamil		for (n = 0; n <= threads; n++) {
50421.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50431.77Skamil			    "child\n");
50441.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
50451.77Skamil			    sizeof(lwp)) != -1);
50461.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
50471.77Skamil
50481.77Skamil			DPRINTF("Assert that the thread exists\n");
50491.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
50501.77Skamil
50511.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
50521.77Skamil			    "event\n", lwp.pl_lwpid);
50531.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
50541.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
50551.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
50561.77Skamil		}
50571.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50581.77Skamil		    "tracee\n");
50591.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
50601.77Skamil		    != -1);
50611.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
50621.77Skamil
50631.77Skamil		DPRINTF("Assert that there are no more threads\n");
50641.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
50651.77Skamil
50661.77Skamil		DPRINTF("Before resuming the child process where it left off "
50671.77Skamil		    "and without signal to be sent\n");
50681.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
50691.77Skamil		    != -1);
50701.77Skamil
50711.1Skamil		/* Wait for tracee and assert that it exited */
50721.1Skamil		FORKEE_REQUIRE_SUCCESS(
50731.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
50741.1Skamil
50751.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
50761.1Skamil
50771.13Schristos		DPRINTF("Before exiting of the tracer process\n");
50781.1Skamil		_exit(exitval_tracer);
50791.1Skamil	}
50801.1Skamil
50811.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
50821.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
50831.1Skamil
50841.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
50851.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
50861.77Skamil
50871.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
50881.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
50891.1Skamil
50901.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
50911.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
50921.1Skamil
50931.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
50941.1Skamil	    TWAIT_FNAME);
50951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
50961.1Skamil	    tracer);
50971.1Skamil
50981.1Skamil	validate_status_exited(status, exitval_tracer);
50991.1Skamil
51001.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
51011.1Skamil	    TWAIT_FNAME);
51021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
51031.1Skamil	    tracee);
51041.1Skamil
51051.77Skamil	validate_status_signaled(status, SIGKILL, 0);
51061.1Skamil
51071.1Skamil	msg_close(&parent_tracer);
51081.1Skamil	msg_close(&parent_tracee);
51091.1Skamil}
51101.77Skamil
51111.77Skamil#define ATTACH_LWPINFO(test, threads)					\
51121.77SkamilATF_TC(test);								\
51131.77SkamilATF_TC_HEAD(test, tc)							\
51141.77Skamil{									\
51151.77Skamil	atf_tc_set_md_var(tc, "descr",					\
51161.77Skamil	    "Verify LWPINFO with the child with " #threads		\
51171.77Skamil	    " spawned extra threads (tracer is not the original "	\
51181.77Skamil	    "parent)");							\
51191.77Skamil}									\
51201.77Skamil									\
51211.77SkamilATF_TC_BODY(test, tc)							\
51221.77Skamil{									\
51231.77Skamil									\
51241.77Skamil	attach_lwpinfo(threads);					\
51251.77Skamil}
51261.77Skamil
51271.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
51281.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
51291.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
51301.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
51311.1Skamil#endif
51321.1Skamil
51331.77Skamil/// ----------------------------------------------------------------------------
51341.77Skamil
51351.1Skamilstatic void
51361.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
51371.1Skamil{
51381.1Skamil	const int exitval = 5;
51391.1Skamil	const int sigval = SIGINT;
51401.1Skamil	const int sigfaked = SIGTRAP;
51411.1Skamil	const int sicodefaked = TRAP_BRKPT;
51421.1Skamil	pid_t child, wpid;
51431.1Skamil	struct sigaction sa;
51441.1Skamil#if defined(TWAIT_HAVE_STATUS)
51451.1Skamil	int status;
51461.1Skamil#endif
51471.1Skamil	struct ptrace_siginfo info;
51481.1Skamil	memset(&info, 0, sizeof(info));
51491.1Skamil
51501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51521.1Skamil	if (child == 0) {
51531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51551.1Skamil
51561.79Skamil		sa.sa_sigaction = sah;
51571.1Skamil		sa.sa_flags = SA_SIGINFO;
51581.1Skamil		sigemptyset(&sa.sa_mask);
51591.1Skamil
51601.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
51611.79Skamil		    != -1);
51621.1Skamil
51631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51651.1Skamil
51661.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
51671.1Skamil
51681.13Schristos		DPRINTF("Before exiting of the child process\n");
51691.1Skamil		_exit(exitval);
51701.1Skamil	}
51711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51721.1Skamil
51731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51751.1Skamil
51761.1Skamil	validate_status_stopped(status, sigval);
51771.1Skamil
51781.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51791.61Skre	SYSCALL_REQUIRE(
51801.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51811.1Skamil
51821.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
51831.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
51841.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
51851.1Skamil	    info.psi_siginfo.si_errno);
51861.1Skamil
51871.79Skamil	if (faked) {
51881.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
51891.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
51901.79Skamil		info.psi_siginfo.si_signo = sigfaked;
51911.79Skamil		info.psi_siginfo.si_code = sicodefaked;
51921.79Skamil	}
51931.1Skamil
51941.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
51951.61Skre	SYSCALL_REQUIRE(
51961.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
51971.1Skamil
51981.79Skamil	if (faked) {
51991.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
52001.79Skamil		    "child\n");
52011.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
52021.79Skamil		    sizeof(info)) != -1);
52031.1Skamil
52041.79Skamil		DPRINTF("Before checking siginfo_t\n");
52051.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
52061.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
52071.79Skamil	}
52081.1Skamil
52091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52101.1Skamil	    "without signal to be sent\n");
52111.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
52121.79Skamil	    faked ? sigfaked : sigval) != -1);
52131.1Skamil
52141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52161.1Skamil
52171.1Skamil	validate_status_exited(status, exitval);
52181.1Skamil
52191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52211.1Skamil}
52221.1Skamil
52231.79Skamil#define PTRACE_SIGINFO(test, faked)					\
52241.79SkamilATF_TC(test);								\
52251.79SkamilATF_TC_HEAD(test, tc)							\
52261.79Skamil{									\
52271.79Skamil	atf_tc_set_md_var(tc, "descr",					\
52281.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
52291.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
52301.79Skamil}									\
52311.79Skamil									\
52321.79Skamilstatic int test##_caught = 0;						\
52331.79Skamil									\
52341.79Skamilstatic void								\
52351.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
52361.79Skamil{									\
52371.79Skamil	if (faked) {							\
52381.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
52391.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
52401.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
52411.79Skamil	} else {							\
52421.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
52431.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
52441.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
52451.79Skamil	}								\
52461.79Skamil									\
52471.79Skamil	++ test##_caught;						\
52481.79Skamil}									\
52491.79Skamil									\
52501.79SkamilATF_TC_BODY(test, tc)							\
52511.79Skamil{									\
52521.79Skamil									\
52531.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
52541.79Skamil}
52551.79Skamil
52561.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
52571.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
52581.79Skamil
52591.79Skamil/// ----------------------------------------------------------------------------
52601.79Skamil
52611.97Skamilstatic void
52621.97Skamiltraceme_exec(bool masked, bool ignored)
52631.1Skamil{
52641.1Skamil	const int sigval = SIGTRAP;
52651.1Skamil	pid_t child, wpid;
52661.1Skamil#if defined(TWAIT_HAVE_STATUS)
52671.1Skamil	int status;
52681.1Skamil#endif
52691.97Skamil	struct sigaction sa;
52701.97Skamil	struct ptrace_siginfo info;
52711.97Skamil	sigset_t intmask;
52721.97Skamil	struct kinfo_proc2 kp;
52731.97Skamil	size_t len = sizeof(kp);
52741.97Skamil
52751.97Skamil	int name[6];
52761.97Skamil	const size_t namelen = __arraycount(name);
52771.97Skamil	ki_sigset_t kp_sigmask;
52781.97Skamil	ki_sigset_t kp_sigignore;
52791.1Skamil
52801.1Skamil	memset(&info, 0, sizeof(info));
52811.1Skamil
52821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52841.1Skamil	if (child == 0) {
52851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52871.1Skamil
52881.97Skamil		if (masked) {
52891.97Skamil			sigemptyset(&intmask);
52901.97Skamil			sigaddset(&intmask, sigval);
52911.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
52921.97Skamil		}
52931.97Skamil
52941.97Skamil		if (ignored) {
52951.97Skamil			memset(&sa, 0, sizeof(sa));
52961.97Skamil			sa.sa_handler = SIG_IGN;
52971.97Skamil			sigemptyset(&sa.sa_mask);
52981.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
52991.97Skamil		}
53001.97Skamil
53011.13Schristos		DPRINTF("Before calling execve(2) from child\n");
53021.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
53031.1Skamil
53041.1Skamil		FORKEE_ASSERT(0 && "Not reached");
53051.1Skamil	}
53061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53071.1Skamil
53081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53101.1Skamil
53111.1Skamil	validate_status_stopped(status, sigval);
53121.1Skamil
53131.97Skamil	name[0] = CTL_KERN,
53141.97Skamil	name[1] = KERN_PROC2,
53151.97Skamil	name[2] = KERN_PROC_PID;
53161.97Skamil	name[3] = getpid();
53171.97Skamil	name[4] = sizeof(kp);
53181.97Skamil	name[5] = 1;
53191.97Skamil
53201.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53211.97Skamil
53221.97Skamil	if (masked)
53231.97Skamil		kp_sigmask = kp.p_sigmask;
53241.97Skamil
53251.97Skamil	if (ignored)
53261.97Skamil		kp_sigignore = kp.p_sigignore;
53271.97Skamil
53281.97Skamil	name[3] = getpid();
53291.97Skamil
53301.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53311.97Skamil
53321.97Skamil	if (masked) {
53331.97Skamil		DPRINTF("kp_sigmask="
53341.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53351.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
53361.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
53371.97Skamil
53381.97Skamil		DPRINTF("kp.p_sigmask="
53391.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53401.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
53411.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
53421.97Skamil
53431.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
53441.97Skamil		    sizeof(kp_sigmask)));
53451.97Skamil	}
53461.97Skamil
53471.97Skamil	if (ignored) {
53481.97Skamil		DPRINTF("kp_sigignore="
53491.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53501.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
53511.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
53521.97Skamil
53531.97Skamil		DPRINTF("kp.p_sigignore="
53541.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53551.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
53561.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
53571.97Skamil
53581.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
53591.97Skamil		    sizeof(kp_sigignore)));
53601.97Skamil	}
53611.97Skamil
53621.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53631.61Skre	SYSCALL_REQUIRE(
53641.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53651.1Skamil
53661.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
53671.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
53681.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
53691.1Skamil	    info.psi_siginfo.si_errno);
53701.1Skamil
53711.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
53721.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
53731.1Skamil
53741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53751.1Skamil	    "without signal to be sent\n");
53761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53771.1Skamil
53781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53801.1Skamil
53811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53831.1Skamil}
53841.1Skamil
53851.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
53861.97SkamilATF_TC(test);								\
53871.97SkamilATF_TC_HEAD(test, tc)							\
53881.97Skamil{									\
53891.97Skamil       atf_tc_set_md_var(tc, "descr",					\
53901.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
53911.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
53921.97Skamil           masked ? " with ignored signal" : "");			\
53931.97Skamil}									\
53941.97Skamil									\
53951.97SkamilATF_TC_BODY(test, tc)							\
53961.97Skamil{									\
53971.97Skamil									\
53981.97Skamil       traceme_exec(masked, ignored);					\
53991.97Skamil}
54001.97Skamil
54011.97SkamilTRACEME_EXEC(traceme_exec, false, false)
54021.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
54031.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
54041.97Skamil
54051.82Skamil/// ----------------------------------------------------------------------------
54061.82Skamil
54071.83Skamilstatic volatile int done;
54081.1Skamil
54091.83Skamilstatic void *
54101.83Skamiltrace_threads_cb(void *arg __unused)
54111.1Skamil{
54121.1Skamil
54131.83Skamil	done++;
54141.83Skamil
54151.83Skamil	while (done < 3)
54161.83Skamil		continue;
54171.83Skamil
54181.83Skamil	return NULL;
54191.1Skamil}
54201.1Skamil
54211.83Skamilstatic void
54221.83Skamiltrace_threads(bool trace_create, bool trace_exit)
54231.1Skamil{
54241.1Skamil	const int sigval = SIGSTOP;
54251.1Skamil	pid_t child, wpid;
54261.1Skamil#if defined(TWAIT_HAVE_STATUS)
54271.1Skamil	int status;
54281.1Skamil#endif
54291.1Skamil	ptrace_state_t state;
54301.1Skamil	const int slen = sizeof(state);
54311.1Skamil	ptrace_event_t event;
54321.1Skamil	const int elen = sizeof(event);
54331.83Skamil	struct ptrace_siginfo info;
54341.83Skamil
54351.83Skamil	pthread_t t[3];
54361.83Skamil	int rv;
54371.83Skamil	size_t n;
54381.1Skamil	lwpid_t lid;
54391.83Skamil
54401.83Skamil	/* Track created and exited threads */
54411.83Skamil	bool traced_lwps[__arraycount(t)];
54421.83Skamil
54431.120Skamil	if (trace_create || trace_exit)
54441.119Skamil		atf_tc_skip("PR kern/51995");
54451.1Skamil
54461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54481.1Skamil	if (child == 0) {
54491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54511.1Skamil
54521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54541.1Skamil
54551.83Skamil		for (n = 0; n < __arraycount(t); n++) {
54561.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
54571.83Skamil			    NULL);
54581.83Skamil			FORKEE_ASSERT(rv == 0);
54591.83Skamil		}
54601.1Skamil
54611.83Skamil		for (n = 0; n < __arraycount(t); n++) {
54621.83Skamil			rv = pthread_join(t[n], NULL);
54631.83Skamil			FORKEE_ASSERT(rv == 0);
54641.83Skamil		}
54651.1Skamil
54661.83Skamil		/*
54671.83Skamil		 * There is race between _exit() and pthread_join() detaching
54681.83Skamil		 * a thread. For simplicity kill the process after detecting
54691.83Skamil		 * LWP events.
54701.83Skamil		 */
54711.83Skamil		while (true)
54721.83Skamil			continue;
54731.1Skamil
54741.83Skamil		FORKEE_ASSERT(0 && "Not reached");
54751.1Skamil	}
54761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54771.1Skamil
54781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54801.1Skamil
54811.1Skamil	validate_status_stopped(status, sigval);
54821.1Skamil
54831.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
54841.83Skamil	SYSCALL_REQUIRE(
54851.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
54861.1Skamil
54871.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
54881.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
54891.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
54901.83Skamil	    info.psi_siginfo.si_errno);
54911.1Skamil
54921.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
54931.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
54941.1Skamil
54951.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
54961.83Skamil	memset(&event, 0, sizeof(event));
54971.83Skamil	if (trace_create)
54981.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
54991.83Skamil	if (trace_exit)
55001.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
55011.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
55021.1Skamil
55031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55041.1Skamil	    "without signal to be sent\n");
55051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55061.1Skamil
55071.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
55081.1Skamil
55091.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
55101.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
55111.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
55121.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
55131.83Skamil		    child);
55141.1Skamil
55151.83Skamil		validate_status_stopped(status, SIGTRAP);
55161.1Skamil
55171.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
55181.83Skamil		    "child\n");
55191.83Skamil		SYSCALL_REQUIRE(
55201.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55211.1Skamil
55221.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
55231.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
55241.83Skamil		    "si_errno=%#x\n",
55251.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
55261.83Skamil		    info.psi_siginfo.si_errno);
55271.1Skamil
55281.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55291.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
55301.1Skamil
55311.83Skamil		SYSCALL_REQUIRE(
55321.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55331.1Skamil
55341.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
55351.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
55361.1Skamil
55371.83Skamil		lid = state.pe_lwp;
55381.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
55391.1Skamil
55401.83Skamil		traced_lwps[lid - 1] = true;
55411.1Skamil
55421.83Skamil		DPRINTF("Before resuming the child process where it left off "
55431.83Skamil		    "and without signal to be sent\n");
55441.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55451.83Skamil	}
55461.1Skamil
55471.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
55481.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
55491.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
55501.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
55511.83Skamil		    child);
55521.1Skamil
55531.83Skamil		validate_status_stopped(status, SIGTRAP);
55541.1Skamil
55551.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
55561.83Skamil		    "child\n");
55571.83Skamil		SYSCALL_REQUIRE(
55581.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55591.1Skamil
55601.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
55611.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
55621.83Skamil		    "si_errno=%#x\n",
55631.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
55641.83Skamil		    info.psi_siginfo.si_errno);
55651.1Skamil
55661.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55671.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
55681.1Skamil
55691.83Skamil		SYSCALL_REQUIRE(
55701.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55711.1Skamil
55721.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
55731.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
55741.1Skamil
55751.83Skamil		lid = state.pe_lwp;
55761.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
55771.1Skamil
55781.83Skamil		if (trace_create) {
55791.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
55801.83Skamil			traced_lwps[lid - 1] = false;
55811.83Skamil		}
55821.1Skamil
55831.83Skamil		DPRINTF("Before resuming the child process where it left off "
55841.83Skamil		    "and without signal to be sent\n");
55851.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55861.83Skamil	}
55871.1Skamil
55881.83Skamil	kill(child, SIGKILL);
55891.1Skamil
55901.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55911.1Skamil	    TWAIT_FNAME);
55921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55931.1Skamil
55941.83Skamil	validate_status_signaled(status, SIGKILL, 0);
55951.1Skamil
55961.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55971.1Skamil	    TWAIT_FNAME);
55981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55991.1Skamil}
56001.1Skamil
56011.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
56021.83SkamilATF_TC(test);								\
56031.83SkamilATF_TC_HEAD(test, tc)							\
56041.83Skamil{									\
56051.83Skamil        atf_tc_set_md_var(tc, "descr",					\
56061.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
56071.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
56081.83Skamil	    trace_exit ? "" : "out");					\
56091.83Skamil}									\
56101.83Skamil									\
56111.83SkamilATF_TC_BODY(test, tc)							\
56121.83Skamil{									\
56131.83Skamil									\
56141.83Skamil        trace_threads(trace_create, trace_exit);			\
56151.83Skamil}
56161.83Skamil
56171.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false)
56181.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true)
56191.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false)
56201.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true)
56211.83Skamil
56221.83Skamil/// ----------------------------------------------------------------------------
56231.83Skamil
56241.84SkamilATF_TC(signal_mask_unrelated);
56251.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
56261.1Skamil{
56271.1Skamil	atf_tc_set_md_var(tc, "descr",
56281.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
56291.1Skamil	    "from catching other signals");
56301.1Skamil}
56311.1Skamil
56321.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
56331.1Skamil{
56341.1Skamil	const int exitval = 5;
56351.1Skamil	const int sigval = SIGSTOP;
56361.1Skamil	const int sigmasked = SIGTRAP;
56371.1Skamil	const int signotmasked = SIGINT;
56381.1Skamil	pid_t child, wpid;
56391.1Skamil#if defined(TWAIT_HAVE_STATUS)
56401.1Skamil	int status;
56411.1Skamil#endif
56421.1Skamil	sigset_t intmask;
56431.1Skamil
56441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56461.1Skamil	if (child == 0) {
56471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56491.1Skamil
56501.1Skamil		sigemptyset(&intmask);
56511.1Skamil		sigaddset(&intmask, sigmasked);
56521.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56531.1Skamil
56541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56561.1Skamil
56571.13Schristos		DPRINTF("Before raising %s from child\n",
56581.1Skamil		    strsignal(signotmasked));
56591.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
56601.1Skamil
56611.13Schristos		DPRINTF("Before exiting of the child process\n");
56621.1Skamil		_exit(exitval);
56631.1Skamil	}
56641.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56651.1Skamil
56661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56681.1Skamil
56691.1Skamil	validate_status_stopped(status, sigval);
56701.1Skamil
56711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56721.1Skamil	    "without signal to be sent\n");
56731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56741.1Skamil
56751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56771.1Skamil
56781.1Skamil	validate_status_stopped(status, signotmasked);
56791.1Skamil
56801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56811.1Skamil	    "without signal to be sent\n");
56821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56831.1Skamil
56841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56861.1Skamil
56871.1Skamil	validate_status_exited(status, exitval);
56881.1Skamil
56891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56911.1Skamil}
56921.1Skamil
56931.84Skamil/// ----------------------------------------------------------------------------
56941.84Skamil
56951.1Skamil#if defined(TWAIT_HAVE_PID)
56961.99Skamilstatic void
56971.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked,
56981.99Skamil           bool ignored)
56991.1Skamil{
57001.1Skamil	const int exitval = 5;
57011.1Skamil	const int exitval2 = 15;
57021.1Skamil	const int sigval = SIGSTOP;
57031.99Skamil	pid_t child, child2 = 0, wpid;
57041.1Skamil#if defined(TWAIT_HAVE_STATUS)
57051.1Skamil	int status;
57061.1Skamil#endif
57071.1Skamil	ptrace_state_t state;
57081.1Skamil	const int slen = sizeof(state);
57091.1Skamil	ptrace_event_t event;
57101.1Skamil	const int elen = sizeof(event);
57111.99Skamil	pid_t (*fn)(void);
57121.99Skamil	struct sigaction sa;
57131.99Skamil	struct ptrace_siginfo info;
57141.99Skamil	sigset_t intmask;
57151.99Skamil	struct kinfo_proc2 kp;
57161.99Skamil	size_t len = sizeof(kp);
57171.99Skamil
57181.99Skamil	int name[6];
57191.99Skamil	const size_t namelen = __arraycount(name);
57201.99Skamil	ki_sigset_t kp_sigmask;
57211.99Skamil	ki_sigset_t kp_sigignore;
57221.1Skamil
57231.99Skamil	if (trackfork)
57241.99Skamil		fn = fork;
57251.99Skamil	if (trackvfork || trackvforkdone)
57261.99Skamil		fn = vfork;
57271.14Schristos
57281.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57291.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57301.1Skamil	if (child == 0) {
57311.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57321.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57331.1Skamil
57341.99Skamil		if (masked) {
57351.99Skamil			sigemptyset(&intmask);
57361.99Skamil			sigaddset(&intmask, SIGTRAP);
57371.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
57381.99Skamil		}
57391.99Skamil
57401.99Skamil		if (ignored) {
57411.99Skamil			memset(&sa, 0, sizeof(sa));
57421.99Skamil			sa.sa_handler = SIG_IGN;
57431.99Skamil			sigemptyset(&sa.sa_mask);
57441.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
57451.99Skamil		}
57461.1Skamil
57471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57491.1Skamil
57501.99Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
57511.1Skamil
57521.1Skamil		if (child2 == 0)
57531.1Skamil			_exit(exitval2);
57541.1Skamil
57551.1Skamil		FORKEE_REQUIRE_SUCCESS
57561.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
57571.1Skamil
57581.1Skamil		forkee_status_exited(status, exitval2);
57591.1Skamil
57601.13Schristos		DPRINTF("Before exiting of the child process\n");
57611.1Skamil		_exit(exitval);
57621.1Skamil	}
57631.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57641.1Skamil
57651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57671.1Skamil
57681.1Skamil	validate_status_stopped(status, sigval);
57691.1Skamil
57701.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
57711.99Skamil	SYSCALL_REQUIRE(
57721.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
57731.99Skamil
57741.99Skamil	DPRINTF("Before checking siginfo_t\n");
57751.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
57761.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
57771.1Skamil
57781.99Skamil	name[0] = CTL_KERN,
57791.99Skamil	name[1] = KERN_PROC2,
57801.99Skamil	name[2] = KERN_PROC_PID;
57811.99Skamil	name[3] = child;
57821.99Skamil	name[4] = sizeof(kp);
57831.99Skamil	name[5] = 1;
57841.1Skamil
57851.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
57861.1Skamil
57871.99Skamil	if (masked)
57881.99Skamil		kp_sigmask = kp.p_sigmask;
57891.1Skamil
57901.99Skamil	if (ignored)
57911.99Skamil		kp_sigignore = kp.p_sigignore;
57921.1Skamil
57931.99Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
57941.99Skamil	    trackfork ? "|PTRACE_FORK" : "",
57951.99Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
57961.99Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
57971.99Skamil	event.pe_set_event = 0;
57981.99Skamil	if (trackfork)
57991.99Skamil		event.pe_set_event |= PTRACE_FORK;
58001.99Skamil	if (trackvfork)
58011.99Skamil		event.pe_set_event |= PTRACE_VFORK;
58021.99Skamil	if (trackvforkdone)
58031.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
58041.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
58051.1Skamil
58061.99Skamil	DPRINTF("Before resuming the child process where it left off and "
58071.99Skamil	    "without signal to be sent\n");
58081.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58091.1Skamil
58101.99Skamil	if (trackfork || trackvfork) {
58111.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
58121.99Skamil		    child);
58131.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
58141.99Skamil		    child);
58151.1Skamil
58161.99Skamil		validate_status_stopped(status, SIGTRAP);
58171.1Skamil
58181.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
58191.1Skamil
58201.99Skamil		if (masked) {
58211.99Skamil			DPRINTF("kp_sigmask="
58221.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58231.99Skamil			    PRIx32 "\n",
58241.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
58251.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
58261.1Skamil
58271.99Skamil			DPRINTF("kp.p_sigmask="
58281.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58291.99Skamil			    PRIx32 "\n",
58301.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
58311.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
58321.1Skamil
58331.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
58341.99Skamil			    sizeof(kp_sigmask)));
58351.99Skamil		}
58361.1Skamil
58371.99Skamil		if (ignored) {
58381.99Skamil			DPRINTF("kp_sigignore="
58391.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58401.99Skamil			    PRIx32 "\n",
58411.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
58421.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
58431.1Skamil
58441.99Skamil			DPRINTF("kp.p_sigignore="
58451.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58461.99Skamil			    PRIx32 "\n",
58471.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
58481.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
58491.1Skamil
58501.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
58511.99Skamil			    sizeof(kp_sigignore)));
58521.99Skamil		}
58531.1Skamil
58541.99Skamil		SYSCALL_REQUIRE(
58551.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
58561.99Skamil		if (trackfork) {
58571.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
58581.99Skamil			       PTRACE_FORK);
58591.99Skamil		}
58601.99Skamil		if (trackvfork) {
58611.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
58621.99Skamil			       PTRACE_VFORK);
58631.99Skamil		}
58641.1Skamil
58651.99Skamil		child2 = state.pe_other_pid;
58661.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
58671.1Skamil
58681.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
58691.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
58701.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
58711.99Skamil		    child2);
58721.1Skamil
58731.99Skamil		validate_status_stopped(status, SIGTRAP);
58741.1Skamil
58751.99Skamil		name[3] = child2;
58761.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
58771.1Skamil
58781.99Skamil		if (masked) {
58791.99Skamil			DPRINTF("kp_sigmask="
58801.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58811.99Skamil			    PRIx32 "\n",
58821.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
58831.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
58841.1Skamil
58851.99Skamil			DPRINTF("kp.p_sigmask="
58861.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58871.99Skamil			    PRIx32 "\n",
58881.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
58891.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
58901.14Schristos
58911.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
58921.99Skamil			    sizeof(kp_sigmask)));
58931.99Skamil		}
58941.1Skamil
58951.99Skamil		if (ignored) {
58961.99Skamil			DPRINTF("kp_sigignore="
58971.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58981.99Skamil			    PRIx32 "\n",
58991.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
59001.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
59011.1Skamil
59021.99Skamil			DPRINTF("kp.p_sigignore="
59031.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59041.99Skamil			    PRIx32 "\n",
59051.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
59061.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
59071.1Skamil
59081.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
59091.99Skamil			    sizeof(kp_sigignore)));
59101.99Skamil		}
59111.1Skamil
59121.99Skamil		SYSCALL_REQUIRE(
59131.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
59141.99Skamil		if (trackfork) {
59151.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
59161.99Skamil			       PTRACE_FORK);
59171.99Skamil		}
59181.99Skamil		if (trackvfork) {
59191.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
59201.99Skamil			       PTRACE_VFORK);
59211.99Skamil		}
59221.1Skamil
59231.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
59241.1Skamil
59251.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
59261.99Skamil		    "and without signal to be sent\n");
59271.99Skamil		SYSCALL_REQUIRE(
59281.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
59291.1Skamil
59301.99Skamil		DPRINTF("Before resuming the child process where it left off "
59311.99Skamil		    "and without signal to be sent\n");
59321.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59331.1Skamil	}
59341.1Skamil
59351.99Skamil	if (trackvforkdone) {
59361.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
59371.99Skamil		    child);
59381.99Skamil		TWAIT_REQUIRE_SUCCESS(
59391.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
59401.1Skamil
59411.99Skamil		validate_status_stopped(status, SIGTRAP);
59421.1Skamil
59431.99Skamil		name[3] = child;
59441.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
59451.1Skamil
59461.102Skamil		/*
59471.102Skamil		 * SIGCHLD is now pending in the signal queue and
59481.102Skamil		 * the kernel presents it to userland as a masked signal.
59491.102Skamil		 */
59501.102Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
59511.102Skamil
59521.99Skamil		if (masked) {
59531.99Skamil			DPRINTF("kp_sigmask="
59541.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59551.99Skamil			    PRIx32 "\n",
59561.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
59571.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
59581.1Skamil
59591.99Skamil			DPRINTF("kp.p_sigmask="
59601.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59611.99Skamil			    PRIx32 "\n",
59621.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
59631.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
59641.1Skamil
59651.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
59661.99Skamil			    sizeof(kp_sigmask)));
59671.99Skamil		}
59681.1Skamil
59691.99Skamil		if (ignored) {
59701.99Skamil			DPRINTF("kp_sigignore="
59711.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59721.99Skamil			    PRIx32 "\n",
59731.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
59741.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
59751.1Skamil
59761.99Skamil			DPRINTF("kp.p_sigignore="
59771.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59781.99Skamil			    PRIx32 "\n",
59791.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
59801.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
59811.1Skamil
59821.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
59831.99Skamil			    sizeof(kp_sigignore)));
59841.99Skamil		}
59851.1Skamil
59861.99Skamil		SYSCALL_REQUIRE(
59871.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
59881.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
59891.1Skamil
59901.99Skamil		child2 = state.pe_other_pid;
59911.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
59921.99Skamil		    child2);
59931.1Skamil
59941.99Skamil		DPRINTF("Before resuming the child process where it left off "
59951.99Skamil		    "and without signal to be sent\n");
59961.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59971.99Skamil	}
59981.1Skamil
59991.99Skamil	if (trackfork || trackvfork) {
60001.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
60011.99Skamil		    "\n", TWAIT_FNAME);
60021.99Skamil		TWAIT_REQUIRE_SUCCESS(
60031.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
60041.1Skamil
60051.99Skamil		validate_status_exited(status, exitval2);
60061.1Skamil
60071.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
60081.99Skamil		    "process\n", TWAIT_FNAME);
60091.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
60101.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
60111.99Skamil	}
60121.1Skamil
60131.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60141.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
60151.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60161.1Skamil
60171.1Skamil	validate_status_stopped(status, SIGCHLD);
60181.1Skamil
60191.57Skamil	DPRINTF("Before resuming the child process where it left off and "
60201.1Skamil	    "without signal to be sent\n");
60211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60221.1Skamil
60231.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60241.1Skamil	    TWAIT_FNAME);
60251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60261.1Skamil
60271.1Skamil	validate_status_exited(status, exitval);
60281.1Skamil
60291.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60301.57Skamil	    TWAIT_FNAME);
60311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60321.1Skamil}
60331.1Skamil
60341.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone,		\
60351.99Skamil                   masked,ignored)					\
60361.99SkamilATF_TC(name);								\
60371.99SkamilATF_TC_HEAD(name, tc)							\
60381.99Skamil{									\
60391.99Skamil	atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught "	\
60401.99Skamil	    "regardless of signal %s%s", 				\
60411.99Skamil	    trackfork ? "PTRACE_FORK" : "",				\
60421.99Skamil	    trackvfork ? "PTRACE_VFORK" : "",				\
60431.99Skamil	    trackvforkdone ? "PTRACE_VFORK_DONE" : "",			\
60441.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
60451.99Skamil}									\
60461.99Skamil									\
60471.99SkamilATF_TC_BODY(name, tc)							\
60481.99Skamil{									\
60491.99Skamil									\
60501.99Skamil	fork2_body(trackfork, trackvfork, trackvforkdone, masked,	\
60511.99Skamil	           ignored);						\
60521.1Skamil}
60531.1Skamil
60541.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false)
60551.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true)
60561.110Skamil#if TEST_VFORK_ENABLED
60571.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false)
60581.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true)
60591.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false)
60601.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true)
60611.1Skamil#endif
60621.110Skamil#endif
60631.1Skamil
60641.99Skamil/// ----------------------------------------------------------------------------
60651.1Skamil
60661.83Skamilvolatile lwpid_t the_lwp_id = 0;
60671.83Skamil
60681.83Skamilstatic void
60691.83Skamillwp_main_func(void *arg)
60701.83Skamil{
60711.83Skamil	the_lwp_id = _lwp_self();
60721.83Skamil	_lwp_exit();
60731.83Skamil}
60741.83Skamil
60751.1SkamilATF_TC(signal9);
60761.1SkamilATF_TC_HEAD(signal9, tc)
60771.1Skamil{
60781.1Skamil	atf_tc_set_md_var(tc, "descr",
60791.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
60801.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
60811.1Skamil}
60821.1Skamil
60831.1SkamilATF_TC_BODY(signal9, tc)
60841.1Skamil{
60851.1Skamil	const int exitval = 5;
60861.1Skamil	const int sigval = SIGSTOP;
60871.1Skamil	const int sigmasked = SIGTRAP;
60881.1Skamil	pid_t child, wpid;
60891.1Skamil#if defined(TWAIT_HAVE_STATUS)
60901.1Skamil	int status;
60911.1Skamil#endif
60921.1Skamil	sigset_t intmask;
60931.1Skamil	ptrace_state_t state;
60941.1Skamil	const int slen = sizeof(state);
60951.1Skamil	ptrace_event_t event;
60961.1Skamil	const int elen = sizeof(event);
60971.1Skamil	ucontext_t uc;
60981.1Skamil	lwpid_t lid;
60991.1Skamil	static const size_t ssize = 16*1024;
61001.1Skamil	void *stack;
61011.1Skamil
61021.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61031.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61041.1Skamil	if (child == 0) {
61051.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61061.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61071.1Skamil
61081.1Skamil		sigemptyset(&intmask);
61091.1Skamil		sigaddset(&intmask, sigmasked);
61101.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61111.1Skamil
61121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61141.1Skamil
61151.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
61161.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
61171.1Skamil
61181.13Schristos		DPRINTF("Before making context for new lwp in child\n");
61191.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
61201.1Skamil
61211.13Schristos		DPRINTF("Before creating new in child\n");
61221.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
61231.1Skamil
61241.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
61251.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
61261.1Skamil
61271.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
61281.1Skamil		    "are the same\n", lid, the_lwp_id);
61291.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
61301.1Skamil
61311.13Schristos		DPRINTF("Before exiting of the child process\n");
61321.1Skamil		_exit(exitval);
61331.1Skamil	}
61341.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61351.1Skamil
61361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61381.1Skamil
61391.1Skamil	validate_status_stopped(status, sigval);
61401.1Skamil
61411.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
61421.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
61431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
61441.1Skamil
61451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61461.1Skamil	    "without signal to be sent\n");
61471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61481.1Skamil
61491.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61501.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
61511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61521.1Skamil
61531.1Skamil	validate_status_stopped(status, sigmasked);
61541.1Skamil
61551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
61561.1Skamil
61571.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
61581.1Skamil
61591.1Skamil	lid = state.pe_lwp;
61601.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
61611.1Skamil
61621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61631.1Skamil	    "without signal to be sent\n");
61641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61651.1Skamil
61661.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61671.1Skamil	    TWAIT_FNAME);
61681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61691.1Skamil
61701.1Skamil	validate_status_exited(status, exitval);
61711.1Skamil
61721.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61731.1Skamil	    TWAIT_FNAME);
61741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61751.1Skamil}
61761.1Skamil
61771.1SkamilATF_TC(signal10);
61781.1SkamilATF_TC_HEAD(signal10, tc)
61791.1Skamil{
61801.1Skamil	atf_tc_set_md_var(tc, "descr",
61811.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61821.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
61831.1Skamil}
61841.1Skamil
61851.1SkamilATF_TC_BODY(signal10, tc)
61861.1Skamil{
61871.1Skamil	const int exitval = 5;
61881.1Skamil	const int sigval = SIGSTOP;
61891.1Skamil	const int sigmasked = SIGTRAP;
61901.1Skamil	pid_t child, wpid;
61911.1Skamil#if defined(TWAIT_HAVE_STATUS)
61921.1Skamil	int status;
61931.1Skamil#endif
61941.1Skamil	sigset_t intmask;
61951.1Skamil	ptrace_state_t state;
61961.1Skamil	const int slen = sizeof(state);
61971.1Skamil	ptrace_event_t event;
61981.1Skamil	const int elen = sizeof(event);
61991.1Skamil	ucontext_t uc;
62001.1Skamil	lwpid_t lid;
62011.1Skamil	static const size_t ssize = 16*1024;
62021.1Skamil	void *stack;
62031.1Skamil
62041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62061.1Skamil	if (child == 0) {
62071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62091.1Skamil
62101.1Skamil		sigemptyset(&intmask);
62111.1Skamil		sigaddset(&intmask, sigmasked);
62121.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
62131.1Skamil
62141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62161.1Skamil
62171.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62181.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62191.1Skamil
62201.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62211.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
62221.1Skamil
62231.13Schristos		DPRINTF("Before creating new in child\n");
62241.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62251.1Skamil
62261.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62271.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62281.1Skamil
62291.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62301.1Skamil		    "are the same\n", lid, the_lwp_id);
62311.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
62321.1Skamil
62331.13Schristos		DPRINTF("Before exiting of the child process\n");
62341.1Skamil		_exit(exitval);
62351.1Skamil	}
62361.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62371.1Skamil
62381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62401.1Skamil
62411.1Skamil	validate_status_stopped(status, sigval);
62421.1Skamil
62431.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
62441.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
62451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62461.1Skamil
62471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62481.1Skamil	    "without signal to be sent\n");
62491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62501.1Skamil
62511.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62521.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
62531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62541.1Skamil
62551.1Skamil	validate_status_stopped(status, sigmasked);
62561.1Skamil
62571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
62581.1Skamil
62591.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
62601.1Skamil
62611.1Skamil	lid = state.pe_lwp;
62621.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
62631.1Skamil
62641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62651.1Skamil	    "without signal to be sent\n");
62661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62671.1Skamil
62681.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62691.1Skamil	    TWAIT_FNAME);
62701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62711.1Skamil
62721.1Skamil	validate_status_exited(status, exitval);
62731.1Skamil
62741.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62751.1Skamil	    TWAIT_FNAME);
62761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62771.1Skamil}
62781.1Skamil
62791.1Skamilstatic void
62801.1Skamillwp_main_stop(void *arg)
62811.1Skamil{
62821.1Skamil	the_lwp_id = _lwp_self();
62831.1Skamil
62841.1Skamil	raise(SIGTRAP);
62851.1Skamil
62861.1Skamil	_lwp_exit();
62871.1Skamil}
62881.1Skamil
62891.1SkamilATF_TC(suspend1);
62901.1SkamilATF_TC_HEAD(suspend1, tc)
62911.1Skamil{
62921.1Skamil	atf_tc_set_md_var(tc, "descr",
62931.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
62941.1Skamil	    "resumed by a tracee");
62951.1Skamil}
62961.1Skamil
62971.1SkamilATF_TC_BODY(suspend1, tc)
62981.1Skamil{
62991.1Skamil	const int exitval = 5;
63001.1Skamil	const int sigval = SIGSTOP;
63011.1Skamil	pid_t child, wpid;
63021.1Skamil#if defined(TWAIT_HAVE_STATUS)
63031.1Skamil	int status;
63041.1Skamil#endif
63051.1Skamil	ucontext_t uc;
63061.1Skamil	lwpid_t lid;
63071.1Skamil	static const size_t ssize = 16*1024;
63081.1Skamil	void *stack;
63091.1Skamil	struct ptrace_lwpinfo pl;
63101.1Skamil	struct ptrace_siginfo psi;
63111.1Skamil	volatile int go = 0;
63121.1Skamil
63131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63151.1Skamil	if (child == 0) {
63161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63181.1Skamil
63191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63211.1Skamil
63221.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63231.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63241.1Skamil
63251.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63261.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
63271.1Skamil
63281.13Schristos		DPRINTF("Before creating new in child\n");
63291.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63301.1Skamil
63311.1Skamil		while (go == 0)
63321.1Skamil			continue;
63331.1Skamil
63341.1Skamil		raise(SIGINT);
63351.1Skamil
63361.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
63371.1Skamil
63381.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
63391.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
63401.1Skamil
63411.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
63421.1Skamil		    "are the same\n", lid, the_lwp_id);
63431.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63441.1Skamil
63451.13Schristos		DPRINTF("Before exiting of the child process\n");
63461.1Skamil		_exit(exitval);
63471.1Skamil	}
63481.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63491.1Skamil
63501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63521.1Skamil
63531.1Skamil	validate_status_stopped(status, sigval);
63541.1Skamil
63551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63561.1Skamil	    "without signal to be sent\n");
63571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63581.1Skamil
63591.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63601.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63621.1Skamil
63631.1Skamil	validate_status_stopped(status, SIGTRAP);
63641.1Skamil
63651.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
63661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
63671.1Skamil
63681.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
63691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
63701.1Skamil
63711.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
63721.1Skamil	    child, getpid());
63731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
63741.1Skamil
63751.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63761.1Skamil	    "without signal to be sent\n");
63771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63781.1Skamil
63791.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63801.1Skamil	    "SIGINT\n", TWAIT_FNAME);
63811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63821.1Skamil
63831.1Skamil	validate_status_stopped(status, SIGINT);
63841.1Skamil
63851.1Skamil	pl.pl_lwpid = 0;
63861.1Skamil
63871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
63881.1Skamil	while (pl.pl_lwpid != 0) {
63891.1Skamil
63901.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
63911.1Skamil		switch (pl.pl_lwpid) {
63921.1Skamil		case 1:
63931.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
63941.1Skamil			break;
63951.1Skamil		case 2:
63961.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
63971.1Skamil			break;
63981.1Skamil		}
63991.1Skamil	}
64001.1Skamil
64011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64021.1Skamil	    "without signal to be sent\n");
64031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64041.1Skamil
64051.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
64061.1Skamil	    TWAIT_FNAME);
64071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64081.1Skamil
64091.1Skamil	validate_status_exited(status, exitval);
64101.1Skamil
64111.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64121.1Skamil	    TWAIT_FNAME);
64131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64141.1Skamil}
64151.1Skamil
64161.1SkamilATF_TC(suspend2);
64171.1SkamilATF_TC_HEAD(suspend2, tc)
64181.1Skamil{
64191.1Skamil	atf_tc_set_md_var(tc, "descr",
64201.1Skamil	    "Verify that the while the only thread within a process is "
64211.1Skamil	    "suspended, the whole process cannot be unstopped");
64221.1Skamil}
64231.1Skamil
64241.1SkamilATF_TC_BODY(suspend2, tc)
64251.1Skamil{
64261.1Skamil	const int exitval = 5;
64271.1Skamil	const int sigval = SIGSTOP;
64281.1Skamil	pid_t child, wpid;
64291.1Skamil#if defined(TWAIT_HAVE_STATUS)
64301.1Skamil	int status;
64311.1Skamil#endif
64321.1Skamil	struct ptrace_siginfo psi;
64331.1Skamil
64341.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64351.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64361.1Skamil	if (child == 0) {
64371.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64381.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64391.1Skamil
64401.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64411.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64421.1Skamil
64431.13Schristos		DPRINTF("Before exiting of the child process\n");
64441.1Skamil		_exit(exitval);
64451.1Skamil	}
64461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64471.1Skamil
64481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64501.1Skamil
64511.1Skamil	validate_status_stopped(status, sigval);
64521.1Skamil
64531.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
64541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
64551.1Skamil
64561.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
64571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
64581.1Skamil
64591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64601.1Skamil	    "without signal to be sent\n");
64611.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
64621.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
64631.1Skamil
64641.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
64651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
64661.1Skamil
64671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64681.1Skamil	    "without signal to be sent\n");
64691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64701.1Skamil
64711.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
64721.1Skamil	    TWAIT_FNAME);
64731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64741.1Skamil
64751.1Skamil	validate_status_exited(status, exitval);
64761.1Skamil
64771.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64781.1Skamil	    TWAIT_FNAME);
64791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64801.1Skamil}
64811.1Skamil
64821.1SkamilATF_TC(resume1);
64831.1SkamilATF_TC_HEAD(resume1, tc)
64841.1Skamil{
64851.1Skamil	atf_tc_set_md_var(tc, "descr",
64861.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
64871.1Skamil	    "resumed by the debugger");
64881.1Skamil}
64891.1Skamil
64901.1SkamilATF_TC_BODY(resume1, tc)
64911.1Skamil{
64921.1Skamil	struct msg_fds fds;
64931.1Skamil	const int exitval = 5;
64941.1Skamil	const int sigval = SIGSTOP;
64951.1Skamil	pid_t child, wpid;
64961.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
64971.1Skamil#if defined(TWAIT_HAVE_STATUS)
64981.1Skamil	int status;
64991.1Skamil#endif
65001.1Skamil	ucontext_t uc;
65011.1Skamil	lwpid_t lid;
65021.1Skamil	static const size_t ssize = 16*1024;
65031.1Skamil	void *stack;
65041.1Skamil	struct ptrace_lwpinfo pl;
65051.1Skamil	struct ptrace_siginfo psi;
65061.1Skamil
65071.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
65081.1Skamil
65091.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
65101.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
65111.1Skamil	if (child == 0) {
65121.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65131.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65141.1Skamil
65151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65171.1Skamil
65181.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
65191.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
65201.1Skamil
65211.13Schristos		DPRINTF("Before making context for new lwp in child\n");
65221.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
65231.1Skamil
65241.13Schristos		DPRINTF("Before creating new in child\n");
65251.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
65261.1Skamil
65271.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
65281.1Skamil
65291.1Skamil		raise(SIGINT);
65301.1Skamil
65311.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
65321.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
65331.1Skamil
65341.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
65351.1Skamil		    "are the same\n", lid, the_lwp_id);
65361.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
65371.1Skamil
65381.13Schristos		DPRINTF("Before exiting of the child process\n");
65391.1Skamil		_exit(exitval);
65401.1Skamil	}
65411.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65421.1Skamil
65431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65451.1Skamil
65461.1Skamil	validate_status_stopped(status, sigval);
65471.1Skamil
65481.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65491.1Skamil	    "without signal to be sent\n");
65501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65511.1Skamil
65521.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65531.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
65541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65551.1Skamil
65561.1Skamil	validate_status_stopped(status, SIGTRAP);
65571.1Skamil
65581.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
65591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
65601.1Skamil
65611.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
65621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65631.1Skamil
65641.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
65651.1Skamil
65661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65671.1Skamil	    "without signal to be sent\n");
65681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65691.1Skamil
65701.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65711.1Skamil	    "SIGINT\n", TWAIT_FNAME);
65721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65731.1Skamil
65741.1Skamil	validate_status_stopped(status, SIGINT);
65751.1Skamil
65761.1Skamil	pl.pl_lwpid = 0;
65771.1Skamil
65781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65791.1Skamil	while (pl.pl_lwpid != 0) {
65801.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65811.1Skamil		switch (pl.pl_lwpid) {
65821.1Skamil		case 1:
65831.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
65841.1Skamil			break;
65851.1Skamil		case 2:
65861.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
65871.1Skamil			break;
65881.1Skamil		}
65891.1Skamil	}
65901.1Skamil
65911.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
65921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
65931.1Skamil
65941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65951.1Skamil	    "without signal to be sent\n");
65961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65971.1Skamil
65981.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65991.1Skamil	    TWAIT_FNAME);
66001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66011.1Skamil
66021.1Skamil	validate_status_exited(status, exitval);
66031.1Skamil
66041.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66051.1Skamil	    TWAIT_FNAME);
66061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66071.1Skamil
66081.1Skamil	msg_close(&fds);
66091.1Skamil}
66101.1Skamil
66111.1SkamilATF_TC(syscall1);
66121.1SkamilATF_TC_HEAD(syscall1, tc)
66131.1Skamil{
66141.1Skamil	atf_tc_set_md_var(tc, "descr",
66151.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
66161.1Skamil}
66171.1Skamil
66181.1SkamilATF_TC_BODY(syscall1, tc)
66191.1Skamil{
66201.1Skamil	const int exitval = 5;
66211.1Skamil	const int sigval = SIGSTOP;
66221.1Skamil	pid_t child, wpid;
66231.1Skamil#if defined(TWAIT_HAVE_STATUS)
66241.1Skamil	int status;
66251.1Skamil#endif
66261.1Skamil	struct ptrace_siginfo info;
66271.1Skamil	memset(&info, 0, sizeof(info));
66281.1Skamil
66291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66311.1Skamil	if (child == 0) {
66321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66341.1Skamil
66351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66371.1Skamil
66381.1Skamil		syscall(SYS_getpid);
66391.1Skamil
66401.13Schristos		DPRINTF("Before exiting of the child process\n");
66411.1Skamil		_exit(exitval);
66421.1Skamil	}
66431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66441.1Skamil
66451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66471.1Skamil
66481.1Skamil	validate_status_stopped(status, sigval);
66491.1Skamil
66501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66511.1Skamil	    "without signal to be sent\n");
66521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
66531.1Skamil
66541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66561.1Skamil
66571.1Skamil	validate_status_stopped(status, SIGTRAP);
66581.1Skamil
66591.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
66601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
66611.1Skamil
66621.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
66631.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
66641.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
66651.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
66661.1Skamil
66671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66681.1Skamil	    "without signal to be sent\n");
66691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
66701.1Skamil
66711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66731.1Skamil
66741.1Skamil	validate_status_stopped(status, SIGTRAP);
66751.1Skamil
66761.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
66771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
66781.1Skamil
66791.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
66801.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
66811.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
66821.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
66831.1Skamil
66841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66851.1Skamil	    "without signal to be sent\n");
66861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66871.1Skamil
66881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66901.1Skamil
66911.1Skamil	validate_status_exited(status, exitval);
66921.1Skamil
66931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66951.1Skamil}
66961.1Skamil
66971.1SkamilATF_TC(syscallemu1);
66981.1SkamilATF_TC_HEAD(syscallemu1, tc)
66991.1Skamil{
67001.1Skamil	atf_tc_set_md_var(tc, "descr",
67011.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
67021.1Skamil}
67031.1Skamil
67041.1SkamilATF_TC_BODY(syscallemu1, tc)
67051.1Skamil{
67061.1Skamil	const int exitval = 5;
67071.1Skamil	const int sigval = SIGSTOP;
67081.1Skamil	pid_t child, wpid;
67091.1Skamil#if defined(TWAIT_HAVE_STATUS)
67101.1Skamil	int status;
67111.1Skamil#endif
67121.1Skamil
67131.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
67141.6Skamil	/* syscallemu does not work on sparc (32-bit) */
67151.6Skamil	atf_tc_expect_fail("PR kern/52166");
67161.6Skamil#endif
67171.6Skamil
67181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67201.1Skamil	if (child == 0) {
67211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67231.1Skamil
67241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67261.1Skamil
67271.1Skamil		syscall(SYS_exit, 100);
67281.1Skamil
67291.13Schristos		DPRINTF("Before exiting of the child process\n");
67301.1Skamil		_exit(exitval);
67311.1Skamil	}
67321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67331.1Skamil
67341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67361.1Skamil
67371.1Skamil	validate_status_stopped(status, sigval);
67381.1Skamil
67391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67401.1Skamil	    "without signal to be sent\n");
67411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67421.1Skamil
67431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67451.1Skamil
67461.1Skamil	validate_status_stopped(status, SIGTRAP);
67471.1Skamil
67481.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
67491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
67501.1Skamil
67511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67521.1Skamil	    "without signal to be sent\n");
67531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67541.1Skamil
67551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67571.1Skamil
67581.1Skamil	validate_status_stopped(status, SIGTRAP);
67591.1Skamil
67601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67611.1Skamil	    "without signal to be sent\n");
67621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67631.1Skamil
67641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67661.1Skamil
67671.1Skamil	validate_status_exited(status, exitval);
67681.1Skamil
67691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67711.1Skamil}
67721.1Skamil
67731.103Skamil/// ----------------------------------------------------------------------------
67741.103Skamil
67751.106Skamilstatic void
67761.106Skamilclone_body(int flags, bool trackfork, bool trackvfork,
67771.106Skamil    bool trackvforkdone)
67781.106Skamil{
67791.106Skamil	const int exitval = 5;
67801.106Skamil	const int exitval2 = 15;
67811.106Skamil	const int sigval = SIGSTOP;
67821.106Skamil	pid_t child, child2 = 0, wpid;
67831.106Skamil#if defined(TWAIT_HAVE_STATUS)
67841.106Skamil	int status;
67851.106Skamil#endif
67861.106Skamil	ptrace_state_t state;
67871.106Skamil	const int slen = sizeof(state);
67881.106Skamil	ptrace_event_t event;
67891.106Skamil	const int elen = sizeof(event);
67901.106Skamil
67911.106Skamil	const size_t stack_size = 1024 * 1024;
67921.106Skamil	void *stack, *stack_base;
67931.106Skamil
67941.106Skamil	stack = malloc(stack_size);
67951.106Skamil	ATF_REQUIRE(stack != NULL);
67961.106Skamil
67971.106Skamil#ifdef __MACHINE_STACK_GROWS_UP
67981.106Skamil	stack_base = stack;
67991.106Skamil#else
68001.106Skamil	stack_base = (char *)stack + stack_size;
68011.106Skamil#endif
68021.106Skamil
68031.106Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
68041.106Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
68051.106Skamil	if (child == 0) {
68061.106Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68071.106Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68081.106Skamil
68091.106Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68101.106Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68111.106Skamil
68121.106Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
68131.106Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
68141.106Skamil
68151.106Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
68161.106Skamil		    child2);
68171.106Skamil
68181.106Skamil		// XXX WALLSIG?
68191.106Skamil		FORKEE_REQUIRE_SUCCESS
68201.106Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
68211.106Skamil
68221.106Skamil		forkee_status_exited(status, exitval2);
68231.106Skamil
68241.106Skamil		DPRINTF("Before exiting of the child process\n");
68251.106Skamil		_exit(exitval);
68261.106Skamil	}
68271.106Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
68281.106Skamil
68291.106Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68301.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68311.106Skamil
68321.106Skamil	validate_status_stopped(status, sigval);
68331.106Skamil
68341.106Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
68351.106Skamil	    trackfork ? "|PTRACE_FORK" : "",
68361.106Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
68371.106Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
68381.106Skamil	event.pe_set_event = 0;
68391.106Skamil	if (trackfork)
68401.106Skamil		event.pe_set_event |= PTRACE_FORK;
68411.106Skamil	if (trackvfork)
68421.106Skamil		event.pe_set_event |= PTRACE_VFORK;
68431.106Skamil	if (trackvforkdone)
68441.106Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
68451.106Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
68461.106Skamil
68471.106Skamil	DPRINTF("Before resuming the child process where it left off and "
68481.106Skamil	    "without signal to be sent\n");
68491.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68501.106Skamil
68511.106Skamil#if defined(TWAIT_HAVE_PID)
68521.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
68531.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
68541.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
68551.106Skamil		    child);
68561.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
68571.106Skamil		    child);
68581.106Skamil
68591.106Skamil		validate_status_stopped(status, SIGTRAP);
68601.106Skamil
68611.106Skamil		SYSCALL_REQUIRE(
68621.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
68631.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
68641.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
68651.106Skamil			       PTRACE_FORK);
68661.106Skamil		}
68671.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
68681.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
68691.106Skamil			       PTRACE_VFORK);
68701.106Skamil		}
68711.106Skamil
68721.106Skamil		child2 = state.pe_other_pid;
68731.106Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
68741.106Skamil
68751.106Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
68761.106Skamil		    "%d\n", TWAIT_FNAME, child2, child);
68771.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
68781.106Skamil		    child2);
68791.106Skamil
68801.106Skamil		validate_status_stopped(status, SIGTRAP);
68811.106Skamil
68821.106Skamil		SYSCALL_REQUIRE(
68831.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
68841.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
68851.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
68861.106Skamil			       PTRACE_FORK);
68871.106Skamil		}
68881.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
68891.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
68901.106Skamil			       PTRACE_VFORK);
68911.106Skamil		}
68921.106Skamil
68931.106Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
68941.106Skamil
68951.106Skamil		DPRINTF("Before resuming the forkee process where it left off "
68961.106Skamil		    "and without signal to be sent\n");
68971.106Skamil		SYSCALL_REQUIRE(
68981.106Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
68991.106Skamil
69001.106Skamil		DPRINTF("Before resuming the child process where it left off "
69011.106Skamil		    "and without signal to be sent\n");
69021.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69031.106Skamil	}
69041.106Skamil#endif
69051.106Skamil
69061.106Skamil	if (trackvforkdone && (flags & CLONE_VFORK)) {
69071.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
69081.106Skamil		    child);
69091.106Skamil		TWAIT_REQUIRE_SUCCESS(
69101.106Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
69111.106Skamil
69121.106Skamil		validate_status_stopped(status, SIGTRAP);
69131.106Skamil
69141.106Skamil		SYSCALL_REQUIRE(
69151.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
69161.106Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
69171.106Skamil
69181.106Skamil		child2 = state.pe_other_pid;
69191.106Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
69201.106Skamil		    child2);
69211.106Skamil
69221.106Skamil		DPRINTF("Before resuming the child process where it left off "
69231.106Skamil		    "and without signal to be sent\n");
69241.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69251.106Skamil	}
69261.106Skamil
69271.103Skamil#if defined(TWAIT_HAVE_PID)
69281.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
69291.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
69301.106Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
69311.106Skamil		    "\n", TWAIT_FNAME);
69321.106Skamil		TWAIT_REQUIRE_SUCCESS(
69331.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
69341.106Skamil
69351.106Skamil		validate_status_exited(status, exitval2);
69361.106Skamil
69371.106Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
69381.106Skamil		    "process\n", TWAIT_FNAME);
69391.106Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
69401.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
69411.106Skamil	}
69421.106Skamil#endif
69431.106Skamil
69441.106Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
69451.106Skamil	    "SIGCHLD\n", TWAIT_FNAME);
69461.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69471.106Skamil
69481.106Skamil	validate_status_stopped(status, SIGCHLD);
69491.106Skamil
69501.106Skamil	DPRINTF("Before resuming the child process where it left off and "
69511.106Skamil	    "without signal to be sent\n");
69521.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69531.106Skamil
69541.106Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
69551.106Skamil	    TWAIT_FNAME);
69561.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69571.106Skamil
69581.106Skamil	validate_status_exited(status, exitval);
69591.103Skamil
69601.106Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
69611.106Skamil	    TWAIT_FNAME);
69621.106Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69631.106Skamil}
69641.103Skamil
69651.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone)			\
69661.106SkamilATF_TC(name);								\
69671.106SkamilATF_TC_HEAD(name, tc)							\
69681.106Skamil{									\
69691.106Skamil	atf_tc_set_md_var(tc, "descr", "Verify clone(%s) "		\
69701.106Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
69711.106Skamil	    #flags,							\
69721.106Skamil	    tfork ? "|PTRACE_FORK" : "",				\
69731.106Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
69741.106Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
69751.106Skamil}									\
69761.106Skamil									\
69771.106SkamilATF_TC_BODY(name, tc)							\
69781.106Skamil{									\
69791.106Skamil									\
69801.106Skamil	clone_body(flags, tfork, tvfork, tvforkdone);			\
69811.103Skamil}
69821.103Skamil
69831.106SkamilCLONE_TEST(clone1, 0, false, false, false)
69841.106Skamil#if defined(TWAIT_HAVE_PID)
69851.106SkamilCLONE_TEST(clone2, 0, true, false, false)
69861.106SkamilCLONE_TEST(clone3, 0, false, true, false)
69871.106SkamilCLONE_TEST(clone4, 0, true, true, false)
69881.106Skamil#endif
69891.106SkamilCLONE_TEST(clone5, 0, false, false, true)
69901.106Skamil#if defined(TWAIT_HAVE_PID)
69911.106SkamilCLONE_TEST(clone6, 0, true, false, true)
69921.106SkamilCLONE_TEST(clone7, 0, false, true, true)
69931.106SkamilCLONE_TEST(clone8, 0, true, true, true)
69941.106Skamil#endif
69951.106Skamil
69961.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false)
69971.106Skamil#if defined(TWAIT_HAVE_PID)
69981.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false)
69991.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false)
70001.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false)
70011.106Skamil#endif
70021.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true)
70031.106Skamil#if defined(TWAIT_HAVE_PID)
70041.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true)
70051.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true)
70061.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true)
70071.106Skamil#endif
70081.106Skamil
70091.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false)
70101.106Skamil#if defined(TWAIT_HAVE_PID)
70111.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false)
70121.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false)
70131.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false)
70141.106Skamil#endif
70151.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true)
70161.106Skamil#if defined(TWAIT_HAVE_PID)
70171.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true)
70181.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true)
70191.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true)
70201.106Skamil#endif
70211.106Skamil
70221.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false)
70231.106Skamil#if defined(TWAIT_HAVE_PID)
70241.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false)
70251.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false)
70261.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false)
70271.106Skamil#endif
70281.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true)
70291.106Skamil#if defined(TWAIT_HAVE_PID)
70301.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true)
70311.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true)
70321.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true)
70331.106Skamil#endif
70341.106Skamil
70351.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false)
70361.106Skamil#if defined(TWAIT_HAVE_PID)
70371.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false)
70381.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false)
70391.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false)
70401.106Skamil#endif
70411.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true)
70421.106Skamil#if defined(TWAIT_HAVE_PID)
70431.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true)
70441.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true)
70451.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true)
70461.106Skamil#endif
70471.106Skamil
70481.110Skamil#if TEST_VFORK_ENABLED
70491.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false)
70501.106Skamil#if defined(TWAIT_HAVE_PID)
70511.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false)
70521.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false)
70531.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false)
70541.106Skamil#endif
70551.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true)
70561.106Skamil#if defined(TWAIT_HAVE_PID)
70571.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true)
70581.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true)
70591.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true)
70601.106Skamil#endif
70611.110Skamil#endif
70621.106Skamil
70631.106Skamil/// ----------------------------------------------------------------------------
70641.106Skamil
70651.106Skamil#if defined(TWAIT_HAVE_PID)
70661.103Skamilstatic void
70671.106Skamilclone_body2(int flags, bool masked, bool ignored)
70681.103Skamil{
70691.103Skamil	const int exitval = 5;
70701.103Skamil	const int exitval2 = 15;
70711.103Skamil	const int sigval = SIGSTOP;
70721.103Skamil	pid_t child, child2 = 0, wpid;
70731.103Skamil#if defined(TWAIT_HAVE_STATUS)
70741.103Skamil	int status;
70751.103Skamil#endif
70761.103Skamil	ptrace_state_t state;
70771.103Skamil	const int slen = sizeof(state);
70781.103Skamil	ptrace_event_t event;
70791.103Skamil	const int elen = sizeof(event);
70801.103Skamil	struct sigaction sa;
70811.103Skamil	struct ptrace_siginfo info;
70821.103Skamil	sigset_t intmask;
70831.103Skamil	struct kinfo_proc2 kp;
70841.103Skamil	size_t len = sizeof(kp);
70851.103Skamil
70861.103Skamil	int name[6];
70871.103Skamil	const size_t namelen = __arraycount(name);
70881.103Skamil	ki_sigset_t kp_sigmask;
70891.103Skamil	ki_sigset_t kp_sigignore;
70901.103Skamil
70911.103Skamil	const size_t stack_size = 1024 * 1024;
70921.103Skamil	void *stack, *stack_base;
70931.103Skamil
70941.103Skamil	stack = malloc(stack_size);
70951.103Skamil	ATF_REQUIRE(stack != NULL);
70961.103Skamil
70971.103Skamil#ifdef __MACHINE_STACK_GROWS_UP
70981.103Skamil	stack_base = stack;
70991.103Skamil#else
71001.103Skamil	stack_base = (char *)stack + stack_size;
71011.103Skamil#endif
71021.103Skamil
71031.103Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
71041.103Skamil	if (child == 0) {
71051.103Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
71061.103Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
71071.103Skamil
71081.103Skamil		if (masked) {
71091.103Skamil			sigemptyset(&intmask);
71101.103Skamil			sigaddset(&intmask, SIGTRAP);
71111.103Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
71121.103Skamil		}
71131.103Skamil
71141.103Skamil		if (ignored) {
71151.103Skamil			memset(&sa, 0, sizeof(sa));
71161.103Skamil			sa.sa_handler = SIG_IGN;
71171.103Skamil			sigemptyset(&sa.sa_mask);
71181.103Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
71191.103Skamil		}
71201.103Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
71211.103Skamil		FORKEE_ASSERT(raise(sigval) == 0);
71221.103Skamil
71231.103Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
71241.103Skamil		    flags);
71251.103Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
71261.103Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
71271.103Skamil
71281.103Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
71291.103Skamil		    child2);
71301.103Skamil
71311.103Skamil		// XXX WALLSIG?
71321.103Skamil		FORKEE_REQUIRE_SUCCESS
71331.103Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
71341.103Skamil
71351.103Skamil		forkee_status_exited(status, exitval2);
71361.103Skamil
71371.103Skamil		DPRINTF("Before exiting of the child process\n");
71381.103Skamil		_exit(exitval);
71391.103Skamil	}
71401.103Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
71411.103Skamil
71421.103Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
71431.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
71441.103Skamil
71451.103Skamil	validate_status_stopped(status, sigval);
71461.103Skamil
71471.103Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
71481.103Skamil	SYSCALL_REQUIRE(
71491.103Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
71501.103Skamil
71511.103Skamil	DPRINTF("Before checking siginfo_t\n");
71521.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
71531.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
71541.103Skamil
71551.103Skamil	name[0] = CTL_KERN,
71561.103Skamil	name[1] = KERN_PROC2,
71571.103Skamil	name[2] = KERN_PROC_PID;
71581.103Skamil	name[3] = child;
71591.103Skamil	name[4] = sizeof(kp);
71601.103Skamil	name[5] = 1;
71611.103Skamil
71621.103Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
71631.103Skamil
71641.103Skamil	if (masked)
71651.103Skamil		kp_sigmask = kp.p_sigmask;
71661.103Skamil
71671.103Skamil	if (ignored)
71681.103Skamil		kp_sigignore = kp.p_sigignore;
71691.103Skamil
71701.103Skamil	DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in "
71711.103Skamil	    "EVENT_MASK for the child %d\n", child);
71721.103Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
71731.103Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
71741.103Skamil
71751.103Skamil	DPRINTF("Before resuming the child process where it left off and "
71761.103Skamil	    "without signal to be sent\n");
71771.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
71781.103Skamil
71791.103Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
71801.103Skamil	    child);
71811.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
71821.103Skamil	    child);
71831.103Skamil
71841.103Skamil	validate_status_stopped(status, SIGTRAP);
71851.103Skamil
71861.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
71871.103Skamil
71881.103Skamil	if (masked) {
71891.103Skamil		DPRINTF("kp_sigmask="
71901.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71911.103Skamil		    PRIx32 "\n",
71921.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
71931.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
71941.103Skamil
71951.103Skamil		DPRINTF("kp.p_sigmask="
71961.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71971.103Skamil		    PRIx32 "\n",
71981.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
71991.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
72001.103Skamil
72011.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
72021.103Skamil		    sizeof(kp_sigmask)));
72031.103Skamil	}
72041.103Skamil
72051.103Skamil	if (ignored) {
72061.103Skamil		DPRINTF("kp_sigignore="
72071.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72081.103Skamil		    PRIx32 "\n",
72091.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
72101.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
72111.103Skamil
72121.103Skamil		DPRINTF("kp.p_sigignore="
72131.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72141.103Skamil		    PRIx32 "\n",
72151.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
72161.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
72171.103Skamil
72181.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
72191.103Skamil		    sizeof(kp_sigignore)));
72201.103Skamil	}
72211.103Skamil
72221.103Skamil	SYSCALL_REQUIRE(
72231.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
72241.103Skamil	DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event,
72251.103Skamil	    child2);
72261.103Skamil	if (!(flags & CLONE_VFORK)) {
72271.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
72281.103Skamil		       PTRACE_FORK);
72291.103Skamil	} else {
72301.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
72311.103Skamil		       PTRACE_VFORK);
72321.103Skamil	}
72331.103Skamil
72341.103Skamil	child2 = state.pe_other_pid;
72351.103Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
72361.103Skamil
72371.103Skamil	DPRINTF("Before calling %s() for the forkee %d of the child "
72381.103Skamil	    "%d\n", TWAIT_FNAME, child2, child);
72391.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
72401.103Skamil	    child2);
72411.103Skamil
72421.103Skamil	validate_status_stopped(status, SIGTRAP);
72431.103Skamil
72441.103Skamil	name[3] = child2;
72451.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
72461.103Skamil
72471.103Skamil	if (masked) {
72481.103Skamil		DPRINTF("kp_sigmask="
72491.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72501.103Skamil		    PRIx32 "\n",
72511.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
72521.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
72531.103Skamil
72541.103Skamil		DPRINTF("kp.p_sigmask="
72551.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72561.103Skamil		    PRIx32 "\n",
72571.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
72581.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
72591.103Skamil
72601.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
72611.103Skamil		    sizeof(kp_sigmask)));
72621.103Skamil	}
72631.103Skamil
72641.103Skamil	if (ignored) {
72651.103Skamil		DPRINTF("kp_sigignore="
72661.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72671.103Skamil		    PRIx32 "\n",
72681.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
72691.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
72701.103Skamil
72711.103Skamil		DPRINTF("kp.p_sigignore="
72721.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72731.103Skamil		    PRIx32 "\n",
72741.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
72751.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
72761.103Skamil
72771.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
72781.103Skamil		    sizeof(kp_sigignore)));
72791.103Skamil	}
72801.103Skamil
72811.103Skamil	SYSCALL_REQUIRE(
72821.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
72831.103Skamil	if (!(flags & CLONE_VFORK)) {
72841.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
72851.103Skamil		       PTRACE_FORK);
72861.103Skamil	} else {
72871.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
72881.103Skamil		       PTRACE_VFORK);
72891.103Skamil	}
72901.103Skamil
72911.103Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
72921.103Skamil
72931.103Skamil	DPRINTF("Before resuming the forkee process where it left off "
72941.103Skamil	    "and without signal to be sent\n");
72951.103Skamil	SYSCALL_REQUIRE(
72961.103Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
72971.103Skamil
72981.103Skamil	DPRINTF("Before resuming the child process where it left off "
72991.103Skamil	    "and without signal to be sent\n");
73001.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
73011.103Skamil
73021.103Skamil	if (flags & CLONE_VFORK) {
73031.103Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
73041.103Skamil		    child);
73051.103Skamil		TWAIT_REQUIRE_SUCCESS(
73061.103Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
73071.103Skamil
73081.103Skamil		validate_status_stopped(status, SIGTRAP);
73091.103Skamil
73101.103Skamil		name[3] = child;
73111.103Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
73121.103Skamil
73131.103Skamil		/*
73141.103Skamil		 * SIGCHLD is now pending in the signal queue and
73151.103Skamil		 * the kernel presents it to userland as a masked signal.
73161.103Skamil		 */
73171.103Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
73181.103Skamil
73191.103Skamil		if (masked) {
73201.103Skamil			DPRINTF("kp_sigmask="
73211.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73221.103Skamil			    PRIx32 "\n",
73231.103Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
73241.103Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
73251.103Skamil
73261.103Skamil			DPRINTF("kp.p_sigmask="
73271.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73281.103Skamil			    PRIx32 "\n",
73291.103Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
73301.103Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
73311.103Skamil
73321.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
73331.103Skamil			    sizeof(kp_sigmask)));
73341.103Skamil		}
73351.103Skamil
73361.103Skamil		if (ignored) {
73371.103Skamil			DPRINTF("kp_sigignore="
73381.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73391.103Skamil			    PRIx32 "\n",
73401.103Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
73411.103Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
73421.103Skamil
73431.103Skamil			DPRINTF("kp.p_sigignore="
73441.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73451.103Skamil			    PRIx32 "\n",
73461.103Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
73471.103Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
73481.103Skamil
73491.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
73501.103Skamil			    sizeof(kp_sigignore)));
73511.103Skamil		}
73521.103Skamil
73531.103Skamil		SYSCALL_REQUIRE(
73541.103Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
73551.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
73561.103Skamil
73571.103Skamil		child2 = state.pe_other_pid;
73581.103Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
73591.103Skamil		    child2);
73601.103Skamil
73611.103Skamil		DPRINTF("Before resuming the child process where it left off "
73621.103Skamil		    "and without signal to be sent\n");
73631.103Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
73641.103Skamil	}
73651.103Skamil
73661.103Skamil	DPRINTF("Before calling %s() for the forkee - expected exited"
73671.103Skamil	    "\n", TWAIT_FNAME);
73681.103Skamil	TWAIT_REQUIRE_SUCCESS(
73691.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
73701.103Skamil
73711.103Skamil	validate_status_exited(status, exitval2);
73721.103Skamil
73731.103Skamil	DPRINTF("Before calling %s() for the forkee - expected no "
73741.103Skamil	    "process\n", TWAIT_FNAME);
73751.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
73761.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
73771.103Skamil
73781.103Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
73791.103Skamil	    "SIGCHLD\n", TWAIT_FNAME);
73801.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
73811.103Skamil
73821.103Skamil	validate_status_stopped(status, SIGCHLD);
73831.103Skamil
73841.103Skamil	DPRINTF("Before resuming the child process where it left off and "
73851.103Skamil	    "without signal to be sent\n");
73861.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
73871.103Skamil
73881.103Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
73891.103Skamil	    TWAIT_FNAME);
73901.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
73911.103Skamil
73921.103Skamil	validate_status_exited(status, exitval);
73931.103Skamil
73941.103Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
73951.103Skamil	    TWAIT_FNAME);
73961.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
73971.103Skamil}
73981.103Skamil
73991.106Skamil#define CLONE_TEST2(name,flags,masked,ignored)				\
74001.103SkamilATF_TC(name);								\
74011.103SkamilATF_TC_HEAD(name, tc)							\
74021.103Skamil{									\
74031.103Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\
74041.103Skamil	    " regardless of signal %s%s", 				\
74051.103Skamil	    #flags, masked ? "masked" : "", ignored ? "ignored" : "");	\
74061.103Skamil}									\
74071.103Skamil									\
74081.103SkamilATF_TC_BODY(name, tc)							\
74091.103Skamil{									\
74101.103Skamil									\
74111.106Skamil	clone_body2(flags, masked, ignored);				\
74121.103Skamil}
74131.103Skamil
74141.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false)
74151.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true)
74161.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false)
74171.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true)
74181.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false)
74191.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true)
74201.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false)
74211.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true)
74221.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX
74231.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true)  // XXX
74241.110Skamil#if TEST_VFORK_ENABLED
74251.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false)
74261.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true)
74271.103Skamil#endif
74281.110Skamil#endif
74291.103Skamil
74301.103Skamil/// ----------------------------------------------------------------------------
74311.103Skamil
74321.111Skamil#if TEST_VFORK_ENABLED
74331.107Skamil#if defined(TWAIT_HAVE_PID)
74341.107Skamilstatic void
74351.107Skamiltraceme_vfork_clone_body(int flags)
74361.107Skamil{
74371.107Skamil	const int exitval = 5;
74381.107Skamil	const int exitval2 = 15;
74391.107Skamil	pid_t child, child2 = 0, wpid;
74401.107Skamil#if defined(TWAIT_HAVE_STATUS)
74411.107Skamil	int status;
74421.107Skamil#endif
74431.107Skamil
74441.107Skamil	const size_t stack_size = 1024 * 1024;
74451.107Skamil	void *stack, *stack_base;
74461.107Skamil
74471.107Skamil	stack = malloc(stack_size);
74481.107Skamil	ATF_REQUIRE(stack != NULL);
74491.107Skamil
74501.107Skamil#ifdef __MACHINE_STACK_GROWS_UP
74511.107Skamil	stack_base = stack;
74521.107Skamil#else
74531.107Skamil	stack_base = (char *)stack + stack_size;
74541.107Skamil#endif
74551.107Skamil
74561.107Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
74571.107Skamil	if (child == 0) {
74581.107Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
74591.107Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
74601.107Skamil
74611.107Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
74621.107Skamil		    flags);
74631.107Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
74641.107Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
74651.107Skamil
74661.107Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
74671.107Skamil		    child2);
74681.107Skamil
74691.107Skamil		// XXX WALLSIG?
74701.107Skamil		FORKEE_REQUIRE_SUCCESS
74711.107Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
74721.107Skamil
74731.107Skamil		forkee_status_exited(status, exitval2);
74741.107Skamil
74751.107Skamil		DPRINTF("Before exiting of the child process\n");
74761.107Skamil		_exit(exitval);
74771.107Skamil	}
74781.107Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
74791.107Skamil
74801.107Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
74811.107Skamil	    TWAIT_FNAME);
74821.107Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
74831.107Skamil
74841.107Skamil	validate_status_exited(status, exitval);
74851.107Skamil
74861.107Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
74871.107Skamil	    TWAIT_FNAME);
74881.107Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
74891.107Skamil}
74901.107Skamil
74911.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags)				\
74921.107SkamilATF_TC(name);								\
74931.107SkamilATF_TC_HEAD(name, tc)							\
74941.107Skamil{									\
74951.107Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is "	\
74961.107Skamil	    "handled correctly with vfork(2)ed tracer", 		\
74971.107Skamil	    #flags);							\
74981.107Skamil}									\
74991.107Skamil									\
75001.107SkamilATF_TC_BODY(name, tc)							\
75011.107Skamil{									\
75021.107Skamil									\
75031.107Skamil	traceme_vfork_clone_body(flags);				\
75041.107Skamil}
75051.107Skamil
75061.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0)
75071.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM)
75081.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS)
75091.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES)
75101.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND)  // XXX
75111.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK)
75121.107Skamil#endif
75131.110Skamil#endif
75141.107Skamil
75151.107Skamil/// ----------------------------------------------------------------------------
75161.107Skamil
75171.122Skamilstatic void
75181.122Skamiluser_va0_disable(int operation)
75191.122Skamil{
75201.122Skamil	pid_t child, wpid;
75211.122Skamil#if defined(TWAIT_HAVE_STATUS)
75221.122Skamil	int status;
75231.122Skamil#endif
75241.122Skamil	const int sigval = SIGSTOP;
75251.122Skamil	int rv;
75261.122Skamil
75271.122Skamil	struct ptrace_siginfo info;
75281.122Skamil
75291.122Skamil	if (get_user_va0_disable() == 0)
75301.122Skamil		atf_tc_skip("vm.user_va0_disable is set to 0");
75311.122Skamil
75321.122Skamil	memset(&info, 0, sizeof(info));
75331.122Skamil
75341.122Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
75351.122Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
75361.122Skamil	if (child == 0) {
75371.122Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
75381.122Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
75391.122Skamil
75401.122Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
75411.122Skamil		FORKEE_ASSERT(raise(sigval) == 0);
75421.122Skamil
75431.122Skamil		/* NOTREACHED */
75441.122Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
75451.122Skamil		__unreachable();
75461.122Skamil	}
75471.122Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
75481.122Skamil
75491.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
75501.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
75511.122Skamil
75521.122Skamil	validate_status_stopped(status, sigval);
75531.122Skamil
75541.122Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
75551.122Skamil		"child\n");
75561.122Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
75571.122Skamil		sizeof(info)) != -1);
75581.122Skamil
75591.122Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
75601.122Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
75611.122Skamil		"si_errno=%#x\n",
75621.122Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
75631.122Skamil		info.psi_siginfo.si_errno);
75641.122Skamil
75651.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
75661.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
75671.122Skamil
75681.122Skamil	DPRINTF("Before resuming the child process in PC=0x0 "
75691.122Skamil	    "and without signal to be sent\n");
75701.122Skamil	errno = 0;
75711.122Skamil	rv = ptrace(operation, child, (void *)0, 0);
75721.122Skamil	ATF_REQUIRE_EQ(errno, EINVAL);
75731.122Skamil	ATF_REQUIRE_EQ(rv, -1);
75741.122Skamil
75751.122Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
75761.122Skamil
75771.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
75781.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
75791.122Skamil	validate_status_signaled(status, SIGKILL, 0);
75801.122Skamil
75811.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
75821.122Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
75831.122Skamil}
75841.122Skamil
75851.122Skamil#define USER_VA0_DISABLE(test, operation)				\
75861.122SkamilATF_TC(test);								\
75871.122SkamilATF_TC_HEAD(test, tc)							\
75881.122Skamil{									\
75891.122Skamil	atf_tc_set_md_var(tc, "descr",					\
75901.122Skamil	    "Verify behavior of " #operation " with PC set to 0x0");	\
75911.122Skamil}									\
75921.122Skamil									\
75931.122SkamilATF_TC_BODY(test, tc)							\
75941.122Skamil{									\
75951.122Skamil									\
75961.122Skamil	user_va0_disable(operation);					\
75971.122Skamil}
75981.122Skamil
75991.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE)
76001.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL)
76011.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH)
76021.122Skamil
76031.122Skamil/// ----------------------------------------------------------------------------
76041.122Skamil
76051.1Skamil#include "t_ptrace_amd64_wait.h"
76061.1Skamil#include "t_ptrace_i386_wait.h"
76071.1Skamil#include "t_ptrace_x86_wait.h"
76081.1Skamil
76091.1SkamilATF_TP_ADD_TCS(tp)
76101.1Skamil{
76111.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
76121.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
76131.33Skamil
76141.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
76151.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
76161.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
76171.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
76181.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
76191.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
76201.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
76211.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
76221.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
76231.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
76241.33Skamil
76251.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
76261.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
76271.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
76281.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
76291.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
76301.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
76311.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
76321.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
76331.87Skamil
76341.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
76351.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
76361.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
76371.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
76381.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
76391.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
76401.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
76411.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
76421.86Skamil
76431.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
76441.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
76451.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
76461.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
76471.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
76481.59Skamil
76491.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
76501.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
76511.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
76521.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
76531.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
76541.88Skamil
76551.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
76561.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
76571.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
76581.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
76591.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
76601.88Skamil
76611.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
76621.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
76631.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
76641.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
76651.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
76661.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
76671.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
76681.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
76691.50Skamil
76701.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
76711.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
76721.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
76731.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
76741.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
76751.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
76761.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
76771.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
76781.50Skamil
76791.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
76801.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
76811.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
76821.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
76831.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
76841.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
76851.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
76861.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
76871.50Skamil
76881.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
76891.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
76901.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
76911.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
76921.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
76931.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
76941.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
76951.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
76961.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
76971.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
76981.1Skamil
76991.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
77001.37Skamil
77011.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
77021.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
77031.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
77041.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
77051.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
77061.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
77071.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
77081.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
77091.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
77101.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
77111.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
77121.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
77131.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
77141.40Skamil
77151.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
77161.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
77171.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
77181.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
77191.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
77201.41Skamil
77211.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
77221.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
77231.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
77241.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
77251.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
77261.92Skamil
77271.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
77281.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
77291.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
77301.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
77311.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
77321.92Skamil
77331.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
77341.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
77351.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
77361.43Skamil
77371.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
77381.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
77391.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
77401.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
77411.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
77421.59Skamil
77431.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77441.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
77451.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77461.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
77471.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77481.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
77491.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77501.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
77511.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77521.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
77531.94Skamil
77541.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77551.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
77561.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77571.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
77581.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77591.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
77601.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77611.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
77621.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77631.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
77641.94Skamil
77651.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
77661.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
77671.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
77681.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
77691.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
77701.51Skamil
77711.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
77721.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
77731.51Skamil
77741.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
77751.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
77761.51Skamil
77771.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77781.51Skamil		tracee_sees_its_original_parent_getppid);
77791.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77801.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
77811.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77821.51Skamil		tracee_sees_its_original_parent_procfs_status);
77831.1Skamil
77841.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
77851.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
77861.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
77871.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
77881.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
77891.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
77901.125Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn);
77911.1Skamil
77921.31Skamil	ATF_TP_ADD_TC(tp, fork1);
77931.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
77941.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
77951.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
77961.31Skamil	ATF_TP_ADD_TC(tp, fork5);
77971.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
77981.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
77991.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
78001.125Skamil	ATF_TP_ADD_TC(tp, fork9);
78011.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork10);
78021.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork11);
78031.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork12);
78041.125Skamil	ATF_TP_ADD_TC(tp, fork13);
78051.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork14);
78061.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork15);
78071.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork16);
78081.31Skamil
78091.109Skamil#if TEST_VFORK_ENABLED
78101.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
78111.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
78121.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
78131.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
78141.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
78151.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
78161.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
78171.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
78181.125Skamil	ATF_TP_ADD_TC(tp, vfork9);
78191.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork10);
78201.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork11);
78211.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork12);
78221.125Skamil	ATF_TP_ADD_TC(tp, vfork13);
78231.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork14);
78241.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork15);
78251.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork16);
78261.116Skamil#endif
78271.1Skamil
78281.124Skamil	ATF_TP_ADD_TC(tp, posix_spawn1);
78291.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn2);
78301.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn3);
78311.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn4);
78321.124Skamil	ATF_TP_ADD_TC(tp, posix_spawn5);
78331.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn6);
78341.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn7);
78351.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn8);
78361.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9);
78371.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10);
78381.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11);
78391.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12);
78401.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13);
78411.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14);
78421.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15);
78431.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16);
78441.124Skamil
78451.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker);
78461.116Skamil#if TEST_VFORK_ENABLED
78471.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker);
78481.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone);
78491.116Skamil#endif
78501.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker);
78511.116Skamil#if TEST_VFORK_ENABLED
78521.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker);
78531.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone);
78541.116Skamil#endif
78551.116Skamil
78561.116Skamil#if TEST_VFORK_ENABLED
78571.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_fork);
78581.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_vfork);
78591.109Skamil#endif
78601.108Skamil
78611.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
78621.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
78631.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
78641.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
78651.54Skamil
78661.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
78671.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
78681.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
78691.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
78701.54Skamil
78711.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
78721.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
78731.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
78741.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
78751.54Skamil
78761.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
78771.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
78781.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
78791.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
78801.54Skamil
78811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
78821.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
78831.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
78841.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
78851.54Skamil
78861.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
78871.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
78881.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
78891.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
78901.54Skamil
78911.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
78921.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
78931.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
78941.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
78951.54Skamil
78961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
78971.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
78981.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
78991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
79001.54Skamil
79011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
79021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
79031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
79041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
79051.54Skamil
79061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
79071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
79081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
79091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
79101.1Skamil
79111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
79121.1Skamil
79131.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i);
79141.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d);
79151.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i);
79161.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d);
79171.101Skamil
79181.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i);
79191.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d);
79201.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i);
79211.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d);
79221.101Skamil
79231.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv);
79241.101Skamil
79251.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i);
79261.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d);
79271.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i);
79281.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d);
79291.115Skamil
79301.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i);
79311.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d);
79321.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i);
79331.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d);
79341.115Skamil
79351.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
79361.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
79371.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
79381.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
79391.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
79401.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
79411.1Skamil
79421.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
79431.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
79441.1Skamil
79451.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
79461.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
79471.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
79481.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
79491.1Skamil
79501.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
79511.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
79521.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
79531.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
79541.2Skamil
79551.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
79561.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
79571.95Skamil
79581.1Skamil	ATF_TP_ADD_TC(tp, kill1);
79591.1Skamil	ATF_TP_ADD_TC(tp, kill2);
79601.75Skamil	ATF_TP_ADD_TC(tp, kill3);
79611.1Skamil
79621.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
79631.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
79641.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
79651.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
79661.77Skamil
79671.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
79681.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
79691.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
79701.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
79711.1Skamil
79721.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
79731.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
79741.79Skamil
79751.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
79761.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
79771.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
79781.1Skamil
79791.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_nolwpevents);
79801.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpexit);
79811.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate);
79821.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit);
79831.1Skamil
79841.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
79851.84Skamil
79861.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
79871.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
79881.109Skamil#if TEST_VFORK_ENABLED
79891.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
79901.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
79911.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
79921.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
79931.109Skamil#endif
79941.99Skamil
79951.1Skamil	ATF_TP_ADD_TC(tp, signal9);
79961.1Skamil	ATF_TP_ADD_TC(tp, signal10);
79971.1Skamil
79981.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
79991.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
80001.1Skamil
80011.1Skamil	ATF_TP_ADD_TC(tp, resume1);
80021.1Skamil
80031.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
80041.1Skamil
80051.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
80061.1Skamil
80071.106Skamil	ATF_TP_ADD_TC(tp, clone1);
80081.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone2);
80091.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone3);
80101.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone4);
80111.106Skamil	ATF_TP_ADD_TC(tp, clone5);
80121.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone6);
80131.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone7);
80141.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone8);
80151.106Skamil
80161.106Skamil	ATF_TP_ADD_TC(tp, clone_vm1);
80171.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2);
80181.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3);
80191.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4);
80201.106Skamil	ATF_TP_ADD_TC(tp, clone_vm5);
80211.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6);
80221.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7);
80231.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8);
80241.106Skamil
80251.106Skamil	ATF_TP_ADD_TC(tp, clone_fs1);
80261.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2);
80271.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3);
80281.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4);
80291.106Skamil	ATF_TP_ADD_TC(tp, clone_fs5);
80301.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6);
80311.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7);
80321.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8);
80331.106Skamil
80341.106Skamil	ATF_TP_ADD_TC(tp, clone_files1);
80351.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2);
80361.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3);
80371.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4);
80381.106Skamil	ATF_TP_ADD_TC(tp, clone_files5);
80391.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6);
80401.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7);
80411.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8);
80421.106Skamil
80431.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand1); // XXX
80441.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX
80451.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX
80461.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX
80471.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand5); // XXX
80481.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX
80491.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX
80501.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX
80511.106Skamil
80521.109Skamil#if TEST_VFORK_ENABLED
80531.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork1);
80541.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2);
80551.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3);
80561.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4);
80571.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork5);
80581.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6);
80591.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7);
80601.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8);
80611.109Skamil#endif
80621.106Skamil
80631.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored);
80641.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked);
80651.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored);
80661.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked);
80671.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored);
80681.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked);
80691.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored);
80701.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked);
80711.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX
80721.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX
80731.109Skamil#if TEST_VFORK_ENABLED
80741.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored);
80751.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked);
80761.109Skamil#endif
80771.103Skamil
80781.109Skamil#if TEST_VFORK_ENABLED
80791.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone);
80801.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm);
80811.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs);
80821.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files);
80831.107Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX
80841.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork);
80851.109Skamil#endif
80861.107Skamil
80871.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue);
80881.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall);
80891.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach);
80901.122Skamil
80911.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
80921.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
80931.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
80941.1Skamil
80951.1Skamil	return atf_no_error();
80961.1Skamil}
8097