t_ptrace_wait.c revision 1.128
11.128Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.128 2019/06/18 21:14:26 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.128Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.128 2019/06/18 21:14:26 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.127Skamil#define TEST_VFORK_ENABLED 1
1041.110Skamil#endif
1051.109Skamil
1061.128Skamil#ifndef TEST_LWP_ENABLED
1071.128Skamil#define TEST_LWP_ENABLED 0
1081.128Skamil#endif
1091.128Skamil
1101.34Skamil/// ----------------------------------------------------------------------------
1111.34Skamil
1121.33Skamilstatic void
1131.33Skamiltraceme_raise(int sigval)
1141.1Skamil{
1151.1Skamil	const int exitval = 5;
1161.1Skamil	pid_t child, wpid;
1171.1Skamil#if defined(TWAIT_HAVE_STATUS)
1181.1Skamil	int status;
1191.1Skamil#endif
1201.1Skamil
1211.45Skamil	struct ptrace_siginfo info;
1221.45Skamil	memset(&info, 0, sizeof(info));
1231.45Skamil
1241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1261.1Skamil	if (child == 0) {
1271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1291.1Skamil
1301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1321.1Skamil
1331.36Skamil		switch (sigval) {
1341.36Skamil		case SIGKILL:
1351.36Skamil			/* NOTREACHED */
1361.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1371.70Smrg			__unreachable();
1381.36Skamil		default:
1391.36Skamil			DPRINTF("Before exiting of the child process\n");
1401.36Skamil			_exit(exitval);
1411.36Skamil		}
1421.1Skamil	}
1431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1441.1Skamil
1451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1471.1Skamil
1481.36Skamil	switch (sigval) {
1491.36Skamil	case SIGKILL:
1501.36Skamil		validate_status_signaled(status, sigval, 0);
1511.36Skamil		break;
1521.36Skamil	default:
1531.36Skamil		validate_status_stopped(status, sigval);
1541.1Skamil
1551.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1561.61Skre			"child\n");
1571.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1581.61Skre			sizeof(info)) != -1);
1591.45Skamil
1601.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1611.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1621.61Skre			"si_errno=%#x\n",
1631.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1641.61Skre			info.psi_siginfo.si_errno);
1651.45Skamil
1661.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1671.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1681.45Skamil
1691.36Skamil		DPRINTF("Before resuming the child process where it left off "
1701.36Skamil		    "and without signal to be sent\n");
1711.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1721.1Skamil
1731.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1741.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1751.61Skre		    child);
1761.36Skamil		break;
1771.36Skamil	}
1781.1Skamil
1791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1811.1Skamil}
1821.1Skamil
1831.61Skre#define TRACEME_RAISE(test, sig)					\
1841.61SkreATF_TC(test);								\
1851.61SkreATF_TC_HEAD(test, tc)							\
1861.61Skre{									\
1871.61Skre	atf_tc_set_md_var(tc, "descr",					\
1881.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1891.61Skre}									\
1901.61Skre									\
1911.61SkreATF_TC_BODY(test, tc)							\
1921.61Skre{									\
1931.61Skre									\
1941.61Skre	traceme_raise(sig);						\
1951.33Skamil}
1961.33Skamil
1971.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1981.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1991.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
2001.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
2011.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
2021.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
2031.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
2041.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
2051.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
2061.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
2071.33Skamil
2081.34Skamil/// ----------------------------------------------------------------------------
2091.1Skamil
2101.1Skamilstatic void
2111.87Skamiltraceme_raisesignal_ignored(int sigignored)
2121.87Skamil{
2131.87Skamil	const int exitval = 5;
2141.87Skamil	const int sigval = SIGSTOP;
2151.87Skamil	pid_t child, wpid;
2161.87Skamil	struct sigaction sa;
2171.87Skamil#if defined(TWAIT_HAVE_STATUS)
2181.87Skamil	int status;
2191.87Skamil#endif
2201.87Skamil	struct ptrace_siginfo info;
2211.87Skamil
2221.87Skamil	memset(&info, 0, sizeof(info));
2231.87Skamil
2241.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2251.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2261.87Skamil	if (child == 0) {
2271.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2281.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2291.87Skamil
2301.87Skamil		memset(&sa, 0, sizeof(sa));
2311.87Skamil		sa.sa_handler = SIG_IGN;
2321.87Skamil		sigemptyset(&sa.sa_mask);
2331.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2341.87Skamil
2351.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2361.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2371.87Skamil
2381.87Skamil		DPRINTF("Before raising %s from child\n",
2391.87Skamil		    strsignal(sigignored));
2401.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2411.87Skamil
2421.87Skamil		DPRINTF("Before exiting of the child process\n");
2431.87Skamil		_exit(exitval);
2441.87Skamil	}
2451.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2461.87Skamil
2471.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2481.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2491.87Skamil
2501.87Skamil	validate_status_stopped(status, sigval);
2511.87Skamil
2521.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2531.87Skamil	SYSCALL_REQUIRE(
2541.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2551.87Skamil
2561.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2571.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2581.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2591.87Skamil	    info.psi_siginfo.si_errno);
2601.87Skamil
2611.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2621.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2631.87Skamil
2641.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2651.87Skamil	    "without signal to be sent\n");
2661.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2671.87Skamil
2681.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2691.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2701.87Skamil
2711.87Skamil	validate_status_stopped(status, sigignored);
2721.87Skamil
2731.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2741.87Skamil	SYSCALL_REQUIRE(
2751.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2761.87Skamil
2771.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2781.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2791.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2801.87Skamil	    info.psi_siginfo.si_errno);
2811.87Skamil
2821.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2831.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2841.87Skamil
2851.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2861.87Skamil	    "without signal to be sent\n");
2871.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2881.87Skamil
2891.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2901.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2911.87Skamil
2921.87Skamil	validate_status_exited(status, exitval);
2931.87Skamil
2941.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2951.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2961.87Skamil}
2971.87Skamil
2981.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2991.87SkamilATF_TC(test);								\
3001.87SkamilATF_TC_HEAD(test, tc)							\
3011.87Skamil{									\
3021.87Skamil	atf_tc_set_md_var(tc, "descr",					\
3031.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
3041.87Skamil	    "does not stop tracer from catching this raised signal");	\
3051.87Skamil}									\
3061.87Skamil									\
3071.87SkamilATF_TC_BODY(test, tc)							\
3081.87Skamil{									\
3091.87Skamil									\
3101.87Skamil	traceme_raisesignal_ignored(sig);				\
3111.87Skamil}
3121.87Skamil
3131.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
3141.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
3151.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
3161.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
3171.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
3181.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
3191.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3201.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3211.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3221.87Skamil
3231.87Skamil/// ----------------------------------------------------------------------------
3241.87Skamil
3251.87Skamilstatic void
3261.86Skamiltraceme_raisesignal_masked(int sigmasked)
3271.86Skamil{
3281.86Skamil	const int exitval = 5;
3291.86Skamil	const int sigval = SIGSTOP;
3301.86Skamil	pid_t child, wpid;
3311.86Skamil#if defined(TWAIT_HAVE_STATUS)
3321.86Skamil	int status;
3331.86Skamil#endif
3341.86Skamil	sigset_t intmask;
3351.86Skamil	struct ptrace_siginfo info;
3361.86Skamil
3371.86Skamil	memset(&info, 0, sizeof(info));
3381.86Skamil
3391.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3401.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3411.86Skamil	if (child == 0) {
3421.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3431.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3441.86Skamil
3451.86Skamil		sigemptyset(&intmask);
3461.86Skamil		sigaddset(&intmask, sigmasked);
3471.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3481.86Skamil
3491.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3501.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3511.86Skamil
3521.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3531.86Skamil		    strsignal(sigmasked));
3541.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3551.86Skamil
3561.86Skamil		DPRINTF("Before exiting of the child process\n");
3571.86Skamil		_exit(exitval);
3581.86Skamil	}
3591.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3601.86Skamil
3611.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3621.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3631.86Skamil
3641.86Skamil	validate_status_stopped(status, sigval);
3651.86Skamil
3661.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3671.86Skamil	SYSCALL_REQUIRE(
3681.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3691.86Skamil
3701.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3711.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3721.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3731.86Skamil	    info.psi_siginfo.si_errno);
3741.86Skamil
3751.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3761.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3771.86Skamil
3781.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3791.86Skamil	    "without signal to be sent\n");
3801.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3811.86Skamil
3821.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3831.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3841.86Skamil
3851.86Skamil	validate_status_exited(status, exitval);
3861.86Skamil
3871.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3881.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3891.86Skamil}
3901.86Skamil
3911.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3921.86SkamilATF_TC(test);								\
3931.86SkamilATF_TC_HEAD(test, tc)							\
3941.86Skamil{									\
3951.86Skamil	atf_tc_set_md_var(tc, "descr",					\
3961.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3971.86Skamil	    "stops tracer from catching this raised signal");		\
3981.86Skamil}									\
3991.86Skamil									\
4001.86SkamilATF_TC_BODY(test, tc)							\
4011.86Skamil{									\
4021.86Skamil									\
4031.86Skamil	traceme_raisesignal_masked(sig);				\
4041.86Skamil}
4051.86Skamil
4061.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4071.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
4081.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
4091.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
4101.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
4111.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
4121.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
4131.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
4141.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
4151.86Skamil
4161.86Skamil/// ----------------------------------------------------------------------------
4171.86Skamil
4181.86Skamilstatic void
4191.59Skamiltraceme_crash(int sig)
4201.59Skamil{
4211.59Skamil	pid_t child, wpid;
4221.59Skamil#if defined(TWAIT_HAVE_STATUS)
4231.59Skamil	int status;
4241.59Skamil#endif
4251.59Skamil	struct ptrace_siginfo info;
4261.61Skre
4271.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4281.71Skamil	if (sig == SIGILL)
4291.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4301.71Skamil#endif
4311.71Skamil
4321.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
4331.114Skamil		atf_tc_skip("FP exceptions are not supported");
4341.114Skamil
4351.59Skamil	memset(&info, 0, sizeof(info));
4361.59Skamil
4371.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4381.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4391.59Skamil	if (child == 0) {
4401.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4411.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4421.59Skamil
4431.59Skamil		DPRINTF("Before executing a trap\n");
4441.59Skamil		switch (sig) {
4451.59Skamil		case SIGTRAP:
4461.59Skamil			trigger_trap();
4471.59Skamil			break;
4481.59Skamil		case SIGSEGV:
4491.59Skamil			trigger_segv();
4501.59Skamil			break;
4511.59Skamil		case SIGILL:
4521.59Skamil			trigger_ill();
4531.59Skamil			break;
4541.59Skamil		case SIGFPE:
4551.59Skamil			trigger_fpe();
4561.59Skamil			break;
4571.59Skamil		case SIGBUS:
4581.59Skamil			trigger_bus();
4591.59Skamil			break;
4601.59Skamil		default:
4611.59Skamil			/* NOTREACHED */
4621.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4631.59Skamil		}
4641.59Skamil
4651.59Skamil		/* NOTREACHED */
4661.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4671.59Skamil	}
4681.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4691.59Skamil
4701.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4711.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4721.59Skamil
4731.59Skamil	validate_status_stopped(status, sig);
4741.59Skamil
4751.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4761.61Skre	SYSCALL_REQUIRE(
4771.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4781.59Skamil
4791.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4801.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4811.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4821.61Skre	    info.psi_siginfo.si_errno);
4831.59Skamil
4841.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4851.59Skamil	switch (sig) {
4861.59Skamil	case SIGTRAP:
4871.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4881.59Skamil		break;
4891.59Skamil	case SIGSEGV:
4901.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4911.59Skamil		break;
4921.71Skamil	case SIGILL:
4931.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
4941.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
4951.71Skamil		break;
4961.59Skamil	case SIGFPE:
4971.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4981.59Skamil		break;
4991.59Skamil	case SIGBUS:
5001.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
5011.59Skamil		break;
5021.59Skamil	}
5031.59Skamil
5041.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
5051.59Skamil
5061.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5071.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5081.59Skamil
5091.59Skamil	validate_status_signaled(status, SIGKILL, 0);
5101.59Skamil
5111.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5121.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5131.59Skamil}
5141.59Skamil
5151.61Skre#define TRACEME_CRASH(test, sig)					\
5161.61SkreATF_TC(test);								\
5171.61SkreATF_TC_HEAD(test, tc)							\
5181.61Skre{									\
5191.61Skre	atf_tc_set_md_var(tc, "descr",					\
5201.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
5211.61Skre}									\
5221.61Skre									\
5231.61SkreATF_TC_BODY(test, tc)							\
5241.61Skre{									\
5251.61Skre									\
5261.61Skre	traceme_crash(sig);						\
5271.59Skamil}
5281.59Skamil
5291.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5301.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5311.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5321.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5331.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5341.59Skamil
5351.59Skamil/// ----------------------------------------------------------------------------
5361.59Skamil
5371.59Skamilstatic void
5381.88Skamiltraceme_signalmasked_crash(int sig)
5391.88Skamil{
5401.89Skamil	const int sigval = SIGSTOP;
5411.88Skamil	pid_t child, wpid;
5421.88Skamil#if defined(TWAIT_HAVE_STATUS)
5431.88Skamil	int status;
5441.88Skamil#endif
5451.88Skamil	struct ptrace_siginfo info;
5461.88Skamil	sigset_t intmask;
5471.89Skamil	struct kinfo_proc2 kp;
5481.89Skamil	size_t len = sizeof(kp);
5491.89Skamil
5501.89Skamil	int name[6];
5511.89Skamil	const size_t namelen = __arraycount(name);
5521.89Skamil	ki_sigset_t kp_sigmask;
5531.88Skamil
5541.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5551.88Skamil	if (sig == SIGILL)
5561.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5571.88Skamil#endif
5581.88Skamil
5591.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
5601.114Skamil		atf_tc_skip("FP exceptions are not supported");
5611.114Skamil
5621.88Skamil	memset(&info, 0, sizeof(info));
5631.88Skamil
5641.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5651.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5661.88Skamil	if (child == 0) {
5671.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5681.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5691.88Skamil
5701.88Skamil		sigemptyset(&intmask);
5711.88Skamil		sigaddset(&intmask, sig);
5721.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5731.88Skamil
5741.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5751.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5761.89Skamil
5771.88Skamil		DPRINTF("Before executing a trap\n");
5781.88Skamil		switch (sig) {
5791.88Skamil		case SIGTRAP:
5801.88Skamil			trigger_trap();
5811.88Skamil			break;
5821.88Skamil		case SIGSEGV:
5831.88Skamil			trigger_segv();
5841.88Skamil			break;
5851.88Skamil		case SIGILL:
5861.88Skamil			trigger_ill();
5871.88Skamil			break;
5881.88Skamil		case SIGFPE:
5891.88Skamil			trigger_fpe();
5901.88Skamil			break;
5911.88Skamil		case SIGBUS:
5921.88Skamil			trigger_bus();
5931.88Skamil			break;
5941.88Skamil		default:
5951.88Skamil			/* NOTREACHED */
5961.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5971.88Skamil		}
5981.88Skamil
5991.88Skamil		/* NOTREACHED */
6001.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
6011.88Skamil	}
6021.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
6031.88Skamil
6041.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6051.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6061.88Skamil
6071.89Skamil	validate_status_stopped(status, sigval);
6081.89Skamil
6091.89Skamil	name[0] = CTL_KERN,
6101.89Skamil	name[1] = KERN_PROC2,
6111.89Skamil	name[2] = KERN_PROC_PID;
6121.89Skamil	name[3] = child;
6131.89Skamil	name[4] = sizeof(kp);
6141.89Skamil	name[5] = 1;
6151.89Skamil
6161.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6171.89Skamil
6181.89Skamil	kp_sigmask = kp.p_sigmask;
6191.89Skamil
6201.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6211.89Skamil	SYSCALL_REQUIRE(
6221.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6231.89Skamil
6241.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6251.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6261.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6271.89Skamil	    info.psi_siginfo.si_errno);
6281.89Skamil
6291.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6301.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6311.89Skamil
6321.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6331.89Skamil	    "without signal to be sent\n");
6341.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6351.89Skamil
6361.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6371.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6381.89Skamil
6391.88Skamil	validate_status_stopped(status, sig);
6401.88Skamil
6411.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6421.88Skamil	SYSCALL_REQUIRE(
6431.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6441.88Skamil
6451.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6461.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6471.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6481.88Skamil	    info.psi_siginfo.si_errno);
6491.88Skamil
6501.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6511.89Skamil
6521.89Skamil	DPRINTF("kp_sigmask="
6531.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6541.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6551.89Skamil	    kp_sigmask.__bits[3]);
6561.89Skamil
6571.89Skamil	DPRINTF("kp.p_sigmask="
6581.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6591.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6601.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6611.89Skamil
6621.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6631.89Skamil
6641.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6651.88Skamil	switch (sig) {
6661.88Skamil	case SIGTRAP:
6671.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6681.88Skamil		break;
6691.88Skamil	case SIGSEGV:
6701.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6711.88Skamil		break;
6721.88Skamil	case SIGILL:
6731.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
6741.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
6751.88Skamil		break;
6761.88Skamil	case SIGFPE:
6771.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6781.88Skamil		break;
6791.88Skamil	case SIGBUS:
6801.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6811.88Skamil		break;
6821.88Skamil	}
6831.88Skamil
6841.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6851.88Skamil
6861.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6871.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6881.88Skamil
6891.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6901.88Skamil
6911.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6921.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6931.88Skamil}
6941.88Skamil
6951.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6961.88SkamilATF_TC(test);								\
6971.88SkamilATF_TC_HEAD(test, tc)							\
6981.88Skamil{									\
6991.88Skamil	atf_tc_set_md_var(tc, "descr",					\
7001.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
7011.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
7021.88Skamil}									\
7031.88Skamil									\
7041.88SkamilATF_TC_BODY(test, tc)							\
7051.88Skamil{									\
7061.88Skamil									\
7071.88Skamil	traceme_signalmasked_crash(sig);				\
7081.88Skamil}
7091.88Skamil
7101.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
7111.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
7121.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
7131.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
7141.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
7151.88Skamil
7161.88Skamil/// ----------------------------------------------------------------------------
7171.88Skamil
7181.88Skamilstatic void
7191.88Skamiltraceme_signalignored_crash(int sig)
7201.88Skamil{
7211.90Skamil	const int sigval = SIGSTOP;
7221.88Skamil	pid_t child, wpid;
7231.88Skamil#if defined(TWAIT_HAVE_STATUS)
7241.88Skamil	int status;
7251.88Skamil#endif
7261.88Skamil	struct sigaction sa;
7271.88Skamil	struct ptrace_siginfo info;
7281.90Skamil	struct kinfo_proc2 kp;
7291.90Skamil	size_t len = sizeof(kp);
7301.90Skamil
7311.90Skamil	int name[6];
7321.90Skamil	const size_t namelen = __arraycount(name);
7331.90Skamil	ki_sigset_t kp_sigignore;
7341.88Skamil
7351.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7361.88Skamil	if (sig == SIGILL)
7371.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7381.88Skamil#endif
7391.88Skamil
7401.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
7411.114Skamil		atf_tc_skip("FP exceptions are not supported");
7421.114Skamil
7431.88Skamil	memset(&info, 0, sizeof(info));
7441.88Skamil
7451.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7461.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7471.88Skamil	if (child == 0) {
7481.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7491.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7501.88Skamil
7511.88Skamil		memset(&sa, 0, sizeof(sa));
7521.88Skamil		sa.sa_handler = SIG_IGN;
7531.88Skamil		sigemptyset(&sa.sa_mask);
7541.88Skamil
7551.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7561.88Skamil
7571.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7581.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7591.90Skamil
7601.88Skamil		DPRINTF("Before executing a trap\n");
7611.88Skamil		switch (sig) {
7621.88Skamil		case SIGTRAP:
7631.88Skamil			trigger_trap();
7641.88Skamil			break;
7651.88Skamil		case SIGSEGV:
7661.88Skamil			trigger_segv();
7671.88Skamil			break;
7681.88Skamil		case SIGILL:
7691.88Skamil			trigger_ill();
7701.88Skamil			break;
7711.88Skamil		case SIGFPE:
7721.88Skamil			trigger_fpe();
7731.88Skamil			break;
7741.88Skamil		case SIGBUS:
7751.88Skamil			trigger_bus();
7761.88Skamil			break;
7771.88Skamil		default:
7781.88Skamil			/* NOTREACHED */
7791.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7801.88Skamil		}
7811.88Skamil
7821.88Skamil		/* NOTREACHED */
7831.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7841.88Skamil	}
7851.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7861.88Skamil
7871.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7881.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7891.88Skamil
7901.90Skamil	validate_status_stopped(status, sigval);
7911.90Skamil
7921.90Skamil	name[0] = CTL_KERN,
7931.90Skamil	name[1] = KERN_PROC2,
7941.90Skamil	name[2] = KERN_PROC_PID;
7951.90Skamil	name[3] = child;
7961.90Skamil	name[4] = sizeof(kp);
7971.90Skamil	name[5] = 1;
7981.90Skamil
7991.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8001.90Skamil
8011.90Skamil	kp_sigignore = kp.p_sigignore;
8021.90Skamil
8031.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
8041.90Skamil	SYSCALL_REQUIRE(
8051.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8061.90Skamil
8071.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8081.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8091.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8101.90Skamil	    info.psi_siginfo.si_errno);
8111.90Skamil
8121.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8131.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
8141.90Skamil
8151.90Skamil	DPRINTF("Before resuming the child process where it left off and "
8161.90Skamil	    "without signal to be sent\n");
8171.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8181.90Skamil
8191.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8201.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8211.90Skamil
8221.88Skamil	validate_status_stopped(status, sig);
8231.88Skamil
8241.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
8251.88Skamil	SYSCALL_REQUIRE(
8261.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8271.88Skamil
8281.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8291.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8301.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8311.88Skamil	    info.psi_siginfo.si_errno);
8321.88Skamil
8331.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8341.90Skamil
8351.90Skamil	DPRINTF("kp_sigignore="
8361.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8371.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8381.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8391.90Skamil
8401.90Skamil	DPRINTF("kp.p_sigignore="
8411.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8421.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8431.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8441.90Skamil
8451.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8461.90Skamil
8471.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8481.88Skamil	switch (sig) {
8491.88Skamil	case SIGTRAP:
8501.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8511.88Skamil		break;
8521.88Skamil	case SIGSEGV:
8531.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8541.88Skamil		break;
8551.88Skamil	case SIGILL:
8561.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
8571.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
8581.88Skamil		break;
8591.88Skamil	case SIGFPE:
8601.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8611.88Skamil		break;
8621.88Skamil	case SIGBUS:
8631.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8641.88Skamil		break;
8651.88Skamil	}
8661.88Skamil
8671.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8681.88Skamil
8691.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8701.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8711.88Skamil
8721.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8731.88Skamil
8741.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8751.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8761.88Skamil}
8771.88Skamil
8781.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8791.88SkamilATF_TC(test);								\
8801.88SkamilATF_TC_HEAD(test, tc)							\
8811.88Skamil{									\
8821.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8831.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8841.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8851.88Skamil}									\
8861.88Skamil									\
8871.88SkamilATF_TC_BODY(test, tc)							\
8881.88Skamil{									\
8891.88Skamil									\
8901.88Skamil	traceme_signalignored_crash(sig);				\
8911.88Skamil}
8921.88Skamil
8931.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8941.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8951.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8961.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8971.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8981.88Skamil
8991.88Skamil/// ----------------------------------------------------------------------------
9001.88Skamil
9011.88Skamilstatic void
9021.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
9031.1Skamil{
9041.1Skamil	const int exitval = 5;
9051.34Skamil	const int sigval = SIGSTOP;
9061.1Skamil	pid_t child, wpid;
9071.1Skamil	struct sigaction sa;
9081.1Skamil#if defined(TWAIT_HAVE_STATUS)
9091.1Skamil	int status;
9101.1Skamil#endif
9111.61Skre	struct ptrace_siginfo info;
9121.1Skamil
9131.45Skamil	memset(&info, 0, sizeof(info));
9141.45Skamil
9151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
9161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
9171.1Skamil	if (child == 0) {
9181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9201.1Skamil
9211.34Skamil		sa.sa_handler = sah;
9221.1Skamil		sa.sa_flags = SA_SIGINFO;
9231.1Skamil		sigemptyset(&sa.sa_mask);
9241.1Skamil
9251.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
9261.1Skamil
9271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9291.1Skamil
9301.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9311.1Skamil
9321.13Schristos		DPRINTF("Before exiting of the child process\n");
9331.1Skamil		_exit(exitval);
9341.1Skamil	}
9351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9361.1Skamil
9371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9391.1Skamil
9401.1Skamil	validate_status_stopped(status, sigval);
9411.1Skamil
9421.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9431.61Skre	SYSCALL_REQUIRE(
9441.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9451.45Skamil
9461.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9471.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9481.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9491.45Skamil	    info.psi_siginfo.si_errno);
9501.45Skamil
9511.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9521.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9531.45Skamil
9541.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9551.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9571.1Skamil
9581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9601.1Skamil
9611.1Skamil	validate_status_exited(status, exitval);
9621.1Skamil
9631.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9651.1Skamil}
9661.1Skamil
9671.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9681.61SkreATF_TC(test);								\
9691.61SkreATF_TC_HEAD(test, tc)							\
9701.61Skre{									\
9711.61Skre	atf_tc_set_md_var(tc, "descr",					\
9721.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9731.61Skre	    "handled correctly and caught by a signal handler");	\
9741.61Skre}									\
9751.61Skre									\
9761.61Skrestatic int test##_caught = 0;						\
9771.61Skre									\
9781.61Skrestatic void								\
9791.61Skretest##_sighandler(int arg)						\
9801.61Skre{									\
9811.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9821.61Skre									\
9831.61Skre	++ test##_caught;						\
9841.61Skre}									\
9851.61Skre									\
9861.61SkreATF_TC_BODY(test, tc)							\
9871.61Skre{									\
9881.61Skre									\
9891.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9901.34Skamil}
9911.34Skamil
9921.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9931.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9941.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9951.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9961.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9971.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9981.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9991.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
10001.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
10011.34Skamil
10021.34Skamil/// ----------------------------------------------------------------------------
10031.34Skamil
10041.35Skamilstatic void
10051.50Skamiltraceme_sendsignal_masked(int sigsent)
10061.50Skamil{
10071.50Skamil	const int exitval = 5;
10081.50Skamil	const int sigval = SIGSTOP;
10091.50Skamil	pid_t child, wpid;
10101.50Skamil	sigset_t set;
10111.50Skamil#if defined(TWAIT_HAVE_STATUS)
10121.50Skamil	int status;
10131.50Skamil#endif
10141.61Skre	struct ptrace_siginfo info;
10151.50Skamil
10161.50Skamil	memset(&info, 0, sizeof(info));
10171.50Skamil
10181.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10191.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10201.50Skamil	if (child == 0) {
10211.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10221.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10231.50Skamil
10241.50Skamil		sigemptyset(&set);
10251.50Skamil		sigaddset(&set, sigsent);
10261.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
10271.50Skamil
10281.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10291.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10301.50Skamil
10311.50Skamil		_exit(exitval);
10321.50Skamil	}
10331.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10341.50Skamil
10351.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10361.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10371.50Skamil
10381.50Skamil	validate_status_stopped(status, sigval);
10391.50Skamil
10401.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10411.61Skre	SYSCALL_REQUIRE(
10421.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10431.50Skamil
10441.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10451.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10461.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10471.50Skamil	    info.psi_siginfo.si_errno);
10481.50Skamil
10491.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10501.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10511.50Skamil
10521.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10531.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10541.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10551.50Skamil
10561.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10571.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10581.50Skamil
10591.50Skamil	validate_status_exited(status, exitval);
10601.50Skamil
10611.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10621.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10631.50Skamil}
10641.50Skamil
10651.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10661.61SkreATF_TC(test);								\
10671.61SkreATF_TC_HEAD(test, tc)							\
10681.61Skre{									\
10691.61Skre	atf_tc_set_md_var(tc, "descr",					\
10701.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10711.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10721.61Skre}									\
10731.61Skre									\
10741.61SkreATF_TC_BODY(test, tc)							\
10751.61Skre{									\
10761.61Skre									\
10771.61Skre	traceme_sendsignal_masked(sig);					\
10781.50Skamil}
10791.50Skamil
10801.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10811.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10821.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10831.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10841.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10851.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10861.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10871.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10881.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10891.50Skamil
10901.50Skamil/// ----------------------------------------------------------------------------
10911.50Skamil
10921.50Skamilstatic void
10931.50Skamiltraceme_sendsignal_ignored(int sigsent)
10941.50Skamil{
10951.50Skamil	const int exitval = 5;
10961.50Skamil	const int sigval = SIGSTOP;
10971.50Skamil	pid_t child, wpid;
10981.50Skamil	struct sigaction sa;
10991.50Skamil#if defined(TWAIT_HAVE_STATUS)
11001.50Skamil	int status;
11011.50Skamil#endif
11021.61Skre	struct ptrace_siginfo info;
11031.50Skamil
11041.50Skamil	memset(&info, 0, sizeof(info));
11051.50Skamil
11061.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
11071.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
11081.50Skamil	if (child == 0) {
11091.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11101.61Skre
11111.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11121.50Skamil
11131.50Skamil		memset(&sa, 0, sizeof(sa));
11141.50Skamil		sa.sa_handler = SIG_IGN;
11151.50Skamil		sigemptyset(&sa.sa_mask);
11161.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
11171.50Skamil
11181.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11191.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11201.50Skamil
11211.50Skamil		_exit(exitval);
11221.50Skamil	}
11231.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11241.50Skamil
11251.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11261.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11271.50Skamil
11281.50Skamil	validate_status_stopped(status, sigval);
11291.50Skamil
11301.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11311.61Skre	SYSCALL_REQUIRE(
11321.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11331.50Skamil
11341.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11351.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11361.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11371.50Skamil	    info.psi_siginfo.si_errno);
11381.50Skamil
11391.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11401.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11411.50Skamil
11421.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11431.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11441.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11451.50Skamil
11461.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11471.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11481.50Skamil
11491.50Skamil	validate_status_exited(status, exitval);
11501.50Skamil
11511.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11521.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11531.50Skamil}
11541.50Skamil
11551.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11561.61SkreATF_TC(test);								\
11571.61SkreATF_TC_HEAD(test, tc)							\
11581.61Skre{									\
11591.61Skre	atf_tc_set_md_var(tc, "descr",					\
11601.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11611.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11621.61Skre}									\
11631.61Skre									\
11641.61SkreATF_TC_BODY(test, tc)							\
11651.61Skre{									\
11661.61Skre									\
11671.61Skre	traceme_sendsignal_ignored(sig);				\
11681.50Skamil}
11691.50Skamil
11701.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11711.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11721.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11731.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11741.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11751.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11761.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11771.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11781.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11791.50Skamil
11801.50Skamil/// ----------------------------------------------------------------------------
11811.50Skamil
11821.50Skamilstatic void
11831.50Skamiltraceme_sendsignal_simple(int sigsent)
11841.1Skamil{
11851.35Skamil	const int sigval = SIGSTOP;
11861.35Skamil	int exitval = 0;
11871.1Skamil	pid_t child, wpid;
11881.1Skamil#if defined(TWAIT_HAVE_STATUS)
11891.1Skamil	int status;
11901.85Skamil	int expect_core;
11911.85Skamil
11921.85Skamil	switch (sigsent) {
11931.85Skamil	case SIGABRT:
11941.85Skamil	case SIGTRAP:
11951.85Skamil	case SIGBUS:
11961.85Skamil	case SIGILL:
11971.85Skamil	case SIGFPE:
11981.85Skamil	case SIGSEGV:
11991.85Skamil		expect_core = 1;
12001.85Skamil		break;
12011.85Skamil	default:
12021.85Skamil		expect_core = 0;
12031.85Skamil		break;
12041.85Skamil	}
12051.1Skamil#endif
12061.61Skre	struct ptrace_siginfo info;
12071.1Skamil
12081.45Skamil	memset(&info, 0, sizeof(info));
12091.45Skamil
12101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12121.1Skamil	if (child == 0) {
12131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12151.1Skamil
12161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12181.1Skamil
12191.35Skamil		switch (sigsent) {
12201.35Skamil		case SIGCONT:
12211.48Skamil		case SIGSTOP:
12221.35Skamil			_exit(exitval);
12231.35Skamil		default:
12241.35Skamil			/* NOTREACHED */
12251.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
12261.35Skamil		}
12271.1Skamil	}
12281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12291.1Skamil
12301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12321.1Skamil
12331.1Skamil	validate_status_stopped(status, sigval);
12341.1Skamil
12351.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12361.61Skre	SYSCALL_REQUIRE(
12371.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12381.45Skamil
12391.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12401.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12411.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12421.45Skamil	    info.psi_siginfo.si_errno);
12431.45Skamil
12441.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12451.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12461.45Skamil
12471.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12481.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12501.1Skamil
12511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12531.1Skamil
12541.35Skamil	switch (sigsent) {
12551.48Skamil	case SIGSTOP:
12561.48Skamil		validate_status_stopped(status, sigsent);
12571.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12581.61Skre		    "child\n");
12591.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12601.61Skre		    sizeof(info)) != -1);
12611.48Skamil
12621.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12631.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12641.61Skre		    "si_errno=%#x\n",
12651.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12661.61Skre		    info.psi_siginfo.si_errno);
12671.48Skamil
12681.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12691.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12701.48Skamil
12711.48Skamil		DPRINTF("Before resuming the child process where it left off "
12721.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12731.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12741.48Skamil
12751.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12761.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12771.61Skre		    child);
12781.48Skamil		/* FALLTHROUGH */
12791.35Skamil	case SIGCONT:
12801.35Skamil		validate_status_exited(status, exitval);
12811.35Skamil		break;
12821.35Skamil	default:
12831.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12841.35Skamil		break;
12851.35Skamil	}
12861.1Skamil
12871.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12881.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12891.1Skamil}
12901.1Skamil
12911.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12921.61SkreATF_TC(test);								\
12931.61SkreATF_TC_HEAD(test, tc)							\
12941.61Skre{									\
12951.61Skre	atf_tc_set_md_var(tc, "descr",					\
12961.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12971.61Skre	    "handled correctly in a child without a signal handler");	\
12981.61Skre}									\
12991.61Skre									\
13001.61SkreATF_TC_BODY(test, tc)							\
13011.61Skre{									\
13021.61Skre									\
13031.61Skre	traceme_sendsignal_simple(sig);					\
13041.35Skamil}
13051.35Skamil
13061.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
13071.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
13081.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
13091.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
13101.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
13111.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
13121.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
13131.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
13141.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
13151.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
13161.35Skamil
13171.35Skamil/// ----------------------------------------------------------------------------
13181.35Skamil
13191.37SkamilATF_TC(traceme_pid1_parent);
13201.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
13211.37Skamil{
13221.37Skamil	atf_tc_set_md_var(tc, "descr",
13231.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
13241.37Skamil}
13251.37Skamil
13261.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
13271.37Skamil{
13281.37Skamil	struct msg_fds parent_child;
13291.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13301.37Skamil	pid_t child1, child2, wpid;
13311.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13321.37Skamil#if defined(TWAIT_HAVE_STATUS)
13331.37Skamil	int status;
13341.37Skamil#endif
13351.37Skamil
13361.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13371.37Skamil
13381.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13391.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13401.37Skamil	if (child1 == 0) {
13411.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13421.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13431.37Skamil		if (child2 != 0) {
13441.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13451.61Skre			    getpid(), child2);
13461.37Skamil			_exit(exitval_child1);
13471.37Skamil		}
13481.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13491.37Skamil
13501.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13511.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13521.37Skamil
13531.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13541.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13551.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13561.37Skamil
13571.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13581.37Skamil
13591.37Skamil		_exit(exitval_child2);
13601.37Skamil	}
13611.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13621.37Skamil
13631.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13641.61Skre	TWAIT_REQUIRE_SUCCESS(
13651.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13661.37Skamil
13671.37Skamil	validate_status_exited(status, exitval_child1);
13681.37Skamil
13691.37Skamil	DPRINTF("Notify that child1 is dead\n");
13701.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13711.37Skamil
13721.37Skamil	DPRINTF("Wait for exiting of child2\n");
13731.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13741.37Skamil}
13751.37Skamil
13761.37Skamil/// ----------------------------------------------------------------------------
13771.37Skamil
13781.40Skamilstatic void
13791.40Skamiltraceme_vfork_raise(int sigval)
13801.40Skamil{
13811.46Skamil	const int exitval = 5, exitval_watcher = 10;
13821.46Skamil	pid_t child, parent, watcher, wpid;
13831.46Skamil	int rv;
13841.40Skamil#if defined(TWAIT_HAVE_STATUS)
13851.40Skamil	int status;
13861.85Skamil
13871.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13881.85Skamil	volatile int expect_core;
13891.85Skamil
13901.85Skamil	switch (sigval) {
13911.85Skamil	case SIGABRT:
13921.85Skamil	case SIGTRAP:
13931.85Skamil	case SIGBUS:
13941.85Skamil	case SIGILL:
13951.85Skamil	case SIGFPE:
13961.85Skamil	case SIGSEGV:
13971.85Skamil		expect_core = 1;
13981.85Skamil		break;
13991.85Skamil	default:
14001.85Skamil		expect_core = 0;
14011.85Skamil		break;
14021.85Skamil	}
14031.40Skamil#endif
14041.40Skamil
14051.46Skamil	/*
14061.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
14071.46Skamil	 * the SIGKILL signal to it.
14081.46Skamil	 *
14091.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
14101.46Skamil	 * simpler to reparent this process to initproc and forget about it.
14111.46Skamil	 */
14121.46Skamil	if (sigval == SIGSTOP) {
14131.46Skamil		parent = getpid();
14141.46Skamil
14151.46Skamil		watcher = fork();
14161.46Skamil		ATF_REQUIRE(watcher != 1);
14171.46Skamil		if (watcher == 0) {
14181.46Skamil			/* Double fork(2) trick to reparent to initproc */
14191.46Skamil			watcher = fork();
14201.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
14211.46Skamil			if (watcher != 0)
14221.46Skamil				_exit(exitval_watcher);
14231.46Skamil
14241.46Skamil			child = await_stopped_child(parent);
14251.46Skamil
14261.46Skamil			errno = 0;
14271.46Skamil			rv = kill(child, SIGKILL);
14281.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
14291.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14301.46Skamil
14311.46Skamil			/* This exit value will be collected by initproc */
14321.46Skamil			_exit(0);
14331.46Skamil		}
14341.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14351.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14361.61Skre		    watcher);
14371.46Skamil
14381.46Skamil		validate_status_exited(status, exitval_watcher);
14391.46Skamil
14401.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14411.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14421.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14431.46Skamil	}
14441.46Skamil
14451.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14461.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14471.40Skamil	if (child == 0) {
14481.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14491.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14501.40Skamil
14511.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14521.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14531.40Skamil
14541.40Skamil		switch (sigval) {
14551.46Skamil		case SIGSTOP:
14561.40Skamil		case SIGKILL:
14571.40Skamil		case SIGABRT:
14581.40Skamil		case SIGHUP:
14591.85Skamil		case SIGTRAP:
14601.85Skamil		case SIGBUS:
14611.85Skamil		case SIGILL:
14621.85Skamil		case SIGFPE:
14631.85Skamil		case SIGSEGV:
14641.40Skamil			/* NOTREACHED */
14651.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14661.70Smrg			__unreachable();
14671.40Skamil		default:
14681.40Skamil			DPRINTF("Before exiting of the child process\n");
14691.40Skamil			_exit(exitval);
14701.40Skamil		}
14711.40Skamil	}
14721.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14731.40Skamil
14741.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14751.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14761.40Skamil
14771.40Skamil	switch (sigval) {
14781.40Skamil	case SIGKILL:
14791.40Skamil	case SIGABRT:
14801.40Skamil	case SIGHUP:
14811.85Skamil	case SIGTRAP:
14821.85Skamil	case SIGBUS:
14831.85Skamil	case SIGILL:
14841.85Skamil	case SIGFPE:
14851.85Skamil	case SIGSEGV:
14861.40Skamil		validate_status_signaled(status, sigval, expect_core);
14871.40Skamil		break;
14881.40Skamil	case SIGSTOP:
14891.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14901.46Skamil		break;
14911.40Skamil	case SIGCONT:
14921.47Skamil	case SIGTSTP:
14931.47Skamil	case SIGTTIN:
14941.47Skamil	case SIGTTOU:
14951.40Skamil		validate_status_exited(status, exitval);
14961.40Skamil		break;
14971.40Skamil	default:
14981.40Skamil		/* NOTREACHED */
14991.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
15001.40Skamil		break;
15011.40Skamil	}
15021.40Skamil
15031.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15041.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15051.40Skamil}
15061.40Skamil
15071.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
15081.61SkreATF_TC(test);								\
15091.61SkreATF_TC_HEAD(test, tc)							\
15101.61Skre{									\
15111.61Skre	atf_tc_set_md_var(tc, "descr",					\
15121.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
15131.61Skre	    "vfork(2)ed child");					\
15141.61Skre}									\
15151.61Skre									\
15161.61SkreATF_TC_BODY(test, tc)							\
15171.61Skre{									\
15181.61Skre									\
15191.61Skre	traceme_vfork_raise(sig);					\
15201.40Skamil}
15211.40Skamil
15221.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
15231.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
15241.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
15251.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
15261.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
15271.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
15281.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
15291.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15301.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15311.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15321.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15331.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15341.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15351.40Skamil
15361.40Skamil/// ----------------------------------------------------------------------------
15371.40Skamil
15381.52Skamilstatic void
15391.52Skamiltraceme_vfork_crash(int sig)
15401.41Skamil{
15411.41Skamil	pid_t child, wpid;
15421.41Skamil#if defined(TWAIT_HAVE_STATUS)
15431.41Skamil	int status;
15441.41Skamil#endif
15451.41Skamil
15461.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15471.71Skamil	if (sig == SIGILL)
15481.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15491.71Skamil#endif
15501.71Skamil
15511.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
15521.114Skamil		atf_tc_skip("FP exceptions are not supported");
15531.114Skamil
15541.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15551.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15561.41Skamil	if (child == 0) {
15571.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15581.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15591.41Skamil
15601.52Skamil		DPRINTF("Before executing a trap\n");
15611.52Skamil		switch (sig) {
15621.52Skamil		case SIGTRAP:
15631.52Skamil			trigger_trap();
15641.52Skamil			break;
15651.52Skamil		case SIGSEGV:
15661.52Skamil			trigger_segv();
15671.52Skamil			break;
15681.52Skamil		case SIGILL:
15691.52Skamil			trigger_ill();
15701.52Skamil			break;
15711.52Skamil		case SIGFPE:
15721.52Skamil			trigger_fpe();
15731.52Skamil			break;
15741.52Skamil		case SIGBUS:
15751.52Skamil			trigger_bus();
15761.52Skamil			break;
15771.52Skamil		default:
15781.52Skamil			/* NOTREACHED */
15791.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15801.52Skamil		}
15811.41Skamil
15821.41Skamil		/* NOTREACHED */
15831.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15841.41Skamil	}
15851.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15861.41Skamil
15871.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15881.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15891.41Skamil
15901.52Skamil	validate_status_signaled(status, sig, 1);
15911.41Skamil
15921.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15931.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15941.41Skamil}
15951.41Skamil
15961.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15971.61SkreATF_TC(test);								\
15981.61SkreATF_TC_HEAD(test, tc)							\
15991.61Skre{									\
16001.61Skre	atf_tc_set_md_var(tc, "descr",					\
16011.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16021.61Skre	    "vfork(2)ed child");					\
16031.61Skre}									\
16041.61Skre									\
16051.61SkreATF_TC_BODY(test, tc)							\
16061.61Skre{									\
16071.61Skre									\
16081.61Skre	traceme_vfork_crash(sig);					\
16091.52Skamil}
16101.52Skamil
16111.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
16121.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
16131.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
16141.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
16151.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
16161.52Skamil
16171.41Skamil/// ----------------------------------------------------------------------------
16181.41Skamil
16191.92Skamilstatic void
16201.92Skamiltraceme_vfork_signalmasked_crash(int sig)
16211.92Skamil{
16221.92Skamil	pid_t child, wpid;
16231.92Skamil#if defined(TWAIT_HAVE_STATUS)
16241.92Skamil	int status;
16251.92Skamil#endif
16261.92Skamil	sigset_t intmask;
16271.92Skamil
16281.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16291.92Skamil	if (sig == SIGILL)
16301.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16311.92Skamil#endif
16321.92Skamil
16331.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
16341.114Skamil		atf_tc_skip("FP exceptions are not supported");
16351.114Skamil
16361.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16371.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16381.92Skamil	if (child == 0) {
16391.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16401.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16411.92Skamil
16421.92Skamil		sigemptyset(&intmask);
16431.92Skamil		sigaddset(&intmask, sig);
16441.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16451.92Skamil
16461.92Skamil		DPRINTF("Before executing a trap\n");
16471.92Skamil		switch (sig) {
16481.92Skamil		case SIGTRAP:
16491.92Skamil			trigger_trap();
16501.92Skamil			break;
16511.92Skamil		case SIGSEGV:
16521.92Skamil			trigger_segv();
16531.92Skamil			break;
16541.92Skamil		case SIGILL:
16551.92Skamil			trigger_ill();
16561.92Skamil			break;
16571.92Skamil		case SIGFPE:
16581.92Skamil			trigger_fpe();
16591.92Skamil			break;
16601.92Skamil		case SIGBUS:
16611.92Skamil			trigger_bus();
16621.92Skamil			break;
16631.92Skamil		default:
16641.92Skamil			/* NOTREACHED */
16651.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16661.92Skamil		}
16671.92Skamil
16681.92Skamil		/* NOTREACHED */
16691.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16701.92Skamil	}
16711.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16721.92Skamil
16731.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16741.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16751.92Skamil
16761.92Skamil	validate_status_signaled(status, sig, 1);
16771.92Skamil
16781.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16791.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16801.92Skamil}
16811.92Skamil
16821.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16831.92SkamilATF_TC(test);								\
16841.92SkamilATF_TC_HEAD(test, tc)							\
16851.92Skamil{									\
16861.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16871.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16881.92Skamil	    "vfork(2)ed child with a masked signal");			\
16891.92Skamil}									\
16901.92Skamil									\
16911.92SkamilATF_TC_BODY(test, tc)							\
16921.92Skamil{									\
16931.92Skamil									\
16941.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16951.92Skamil}
16961.92Skamil
16971.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16981.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16991.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
17001.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
17011.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
17021.92Skamil
17031.92Skamil/// ----------------------------------------------------------------------------
17041.92Skamil
17051.92Skamilstatic void
17061.92Skamiltraceme_vfork_signalignored_crash(int sig)
17071.92Skamil{
17081.92Skamil	pid_t child, wpid;
17091.92Skamil#if defined(TWAIT_HAVE_STATUS)
17101.92Skamil	int status;
17111.92Skamil#endif
17121.92Skamil	struct sigaction sa;
17131.92Skamil
17141.92Skamil#ifndef PTRACE_ILLEGAL_ASM
17151.92Skamil	if (sig == SIGILL)
17161.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
17171.92Skamil#endif
17181.92Skamil
17191.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
17201.114Skamil		atf_tc_skip("FP exceptions are not supported");
17211.114Skamil
17221.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17231.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17241.92Skamil	if (child == 0) {
17251.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17261.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17271.92Skamil
17281.92Skamil		memset(&sa, 0, sizeof(sa));
17291.92Skamil		sa.sa_handler = SIG_IGN;
17301.92Skamil		sigemptyset(&sa.sa_mask);
17311.92Skamil
17321.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
17331.92Skamil
17341.92Skamil		DPRINTF("Before executing a trap\n");
17351.92Skamil		switch (sig) {
17361.92Skamil		case SIGTRAP:
17371.92Skamil			trigger_trap();
17381.92Skamil			break;
17391.92Skamil		case SIGSEGV:
17401.92Skamil			trigger_segv();
17411.92Skamil			break;
17421.92Skamil		case SIGILL:
17431.92Skamil			trigger_ill();
17441.92Skamil			break;
17451.92Skamil		case SIGFPE:
17461.92Skamil			trigger_fpe();
17471.92Skamil			break;
17481.92Skamil		case SIGBUS:
17491.92Skamil			trigger_bus();
17501.92Skamil			break;
17511.92Skamil		default:
17521.92Skamil			/* NOTREACHED */
17531.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17541.92Skamil		}
17551.92Skamil
17561.92Skamil		/* NOTREACHED */
17571.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17581.92Skamil	}
17591.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17601.92Skamil
17611.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17621.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17631.92Skamil
17641.92Skamil	validate_status_signaled(status, sig, 1);
17651.92Skamil
17661.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17671.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17681.92Skamil}
17691.92Skamil
17701.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17711.92SkamilATF_TC(test);								\
17721.92SkamilATF_TC_HEAD(test, tc)							\
17731.92Skamil{									\
17741.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17751.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17761.92Skamil	    "vfork(2)ed child with ignored signal");			\
17771.92Skamil}									\
17781.92Skamil									\
17791.92SkamilATF_TC_BODY(test, tc)							\
17801.92Skamil{									\
17811.92Skamil									\
17821.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17831.92Skamil}
17841.92Skamil
17851.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17861.92Skamil    SIGTRAP)
17871.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17881.92Skamil    SIGSEGV)
17891.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17901.92Skamil    SIGILL)
17911.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17921.92Skamil    SIGFPE)
17931.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17941.92Skamil    SIGBUS)
17951.92Skamil
17961.92Skamil/// ----------------------------------------------------------------------------
17971.92Skamil
17981.96Skamilstatic void
17991.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
18001.43Skamil{
18011.43Skamil	const int sigval = SIGTRAP;
18021.43Skamil	pid_t child, wpid;
18031.43Skamil#if defined(TWAIT_HAVE_STATUS)
18041.43Skamil	int status;
18051.43Skamil#endif
18061.96Skamil	struct sigaction sa;
18071.61Skre	struct ptrace_siginfo info;
18081.96Skamil	sigset_t intmask;
18091.96Skamil	struct kinfo_proc2 kp;
18101.96Skamil	size_t len = sizeof(kp);
18111.96Skamil
18121.96Skamil	int name[6];
18131.96Skamil	const size_t namelen = __arraycount(name);
18141.96Skamil	ki_sigset_t kp_sigmask;
18151.96Skamil	ki_sigset_t kp_sigignore;
18161.43Skamil
18171.43Skamil	memset(&info, 0, sizeof(info));
18181.43Skamil
18191.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
18201.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
18211.43Skamil	if (child == 0) {
18221.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18231.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18241.43Skamil
18251.96Skamil		if (masked) {
18261.96Skamil			sigemptyset(&intmask);
18271.96Skamil			sigaddset(&intmask, sigval);
18281.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
18291.96Skamil		}
18301.96Skamil
18311.96Skamil		if (ignored) {
18321.96Skamil			memset(&sa, 0, sizeof(sa));
18331.96Skamil			sa.sa_handler = SIG_IGN;
18341.96Skamil			sigemptyset(&sa.sa_mask);
18351.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
18361.96Skamil		}
18371.96Skamil
18381.43Skamil		DPRINTF("Before calling execve(2) from child\n");
18391.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
18401.43Skamil
18411.43Skamil		/* NOTREACHED */
18421.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18431.43Skamil	}
18441.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18451.43Skamil
18461.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18471.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18481.43Skamil
18491.43Skamil	validate_status_stopped(status, sigval);
18501.43Skamil
18511.96Skamil	name[0] = CTL_KERN,
18521.96Skamil	name[1] = KERN_PROC2,
18531.96Skamil	name[2] = KERN_PROC_PID;
18541.96Skamil	name[3] = getpid();
18551.96Skamil	name[4] = sizeof(kp);
18561.96Skamil	name[5] = 1;
18571.96Skamil
18581.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18591.96Skamil
18601.96Skamil	if (masked)
18611.96Skamil		kp_sigmask = kp.p_sigmask;
18621.96Skamil
18631.96Skamil	if (ignored)
18641.96Skamil		kp_sigignore = kp.p_sigignore;
18651.96Skamil
18661.96Skamil	name[3] = getpid();
18671.96Skamil
18681.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18691.96Skamil
18701.96Skamil	if (masked) {
18711.96Skamil		DPRINTF("kp_sigmask="
18721.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18731.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18741.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18751.96Skamil
18761.96Skamil	        DPRINTF("kp.p_sigmask="
18771.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18781.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18791.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18801.96Skamil
18811.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18821.96Skamil		    sizeof(kp_sigmask)));
18831.96Skamil	}
18841.96Skamil
18851.96Skamil	if (ignored) {
18861.96Skamil		DPRINTF("kp_sigignore="
18871.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18881.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18891.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18901.96Skamil
18911.96Skamil	        DPRINTF("kp.p_sigignore="
18921.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18931.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
18941.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
18951.96Skamil
18961.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
18971.96Skamil		    sizeof(kp_sigignore)));
18981.96Skamil	}
18991.96Skamil
19001.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
19011.61Skre	SYSCALL_REQUIRE(
19021.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
19031.43Skamil
19041.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
19051.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
19061.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
19071.43Skamil	    info.psi_siginfo.si_errno);
19081.43Skamil
19091.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
19101.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
19111.43Skamil
19121.43Skamil	DPRINTF("Before resuming the child process where it left off and "
19131.43Skamil	    "without signal to be sent\n");
19141.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19151.43Skamil
19161.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19171.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19181.43Skamil
19191.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19201.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19211.43Skamil}
19221.43Skamil
19231.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
19241.96SkamilATF_TC(test);								\
19251.96SkamilATF_TC_HEAD(test, tc)							\
19261.96Skamil{									\
19271.96Skamil	atf_tc_set_md_var(tc, "descr",					\
19281.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
19291.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
19301.96Skamil	    masked ? " with ignored signal" : "");			\
19311.96Skamil}									\
19321.96Skamil									\
19331.96SkamilATF_TC_BODY(test, tc)							\
19341.96Skamil{									\
19351.96Skamil									\
19361.96Skamil	traceme_vfork_exec(masked, ignored);				\
19371.96Skamil}
19381.96Skamil
19391.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
19401.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19411.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19421.96Skamil
19431.43Skamil/// ----------------------------------------------------------------------------
19441.43Skamil
19451.1Skamil#if defined(TWAIT_HAVE_PID)
19461.51Skamilstatic void
19471.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19481.59Skamil{
19491.94Skamil	const int sigval = SIGSTOP;
19501.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19511.59Skamil	const int exitval = 10;
19521.59Skamil	pid_t tracee, tracer, wpid;
19531.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19541.59Skamil#if defined(TWAIT_HAVE_STATUS)
19551.59Skamil	int status;
19561.59Skamil#endif
19571.94Skamil	struct sigaction sa;
19581.59Skamil	struct ptrace_siginfo info;
19591.94Skamil	sigset_t intmask;
19601.94Skamil	struct kinfo_proc2 kp;
19611.94Skamil	size_t len = sizeof(kp);
19621.94Skamil
19631.94Skamil	int name[6];
19641.94Skamil	const size_t namelen = __arraycount(name);
19651.94Skamil	ki_sigset_t kp_sigmask;
19661.94Skamil	ki_sigset_t kp_sigignore;
19671.61Skre
19681.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19691.71Skamil	if (sig == SIGILL)
19701.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19711.71Skamil#endif
19721.71Skamil
19731.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
19741.114Skamil		atf_tc_skip("FP exceptions are not supported");
19751.114Skamil
19761.59Skamil	memset(&info, 0, sizeof(info));
19771.59Skamil
19781.59Skamil	DPRINTF("Spawn tracee\n");
19791.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19801.59Skamil	tracee = atf_utils_fork();
19811.59Skamil	if (tracee == 0) {
19821.59Skamil		// Wait for parent to let us crash
19831.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19841.61Skre
19851.94Skamil		if (masked) {
19861.94Skamil			sigemptyset(&intmask);
19871.94Skamil			sigaddset(&intmask, sig);
19881.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19891.94Skamil		}
19901.94Skamil
19911.94Skamil		if (ignored) {
19921.94Skamil			memset(&sa, 0, sizeof(sa));
19931.94Skamil			sa.sa_handler = SIG_IGN;
19941.94Skamil			sigemptyset(&sa.sa_mask);
19951.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
19961.94Skamil		}
19971.94Skamil
19981.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19991.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20001.94Skamil
20011.59Skamil		DPRINTF("Before executing a trap\n");
20021.59Skamil		switch (sig) {
20031.59Skamil		case SIGTRAP:
20041.59Skamil			trigger_trap();
20051.59Skamil			break;
20061.59Skamil		case SIGSEGV:
20071.59Skamil			trigger_segv();
20081.59Skamil			break;
20091.59Skamil		case SIGILL:
20101.59Skamil			trigger_ill();
20111.59Skamil			break;
20121.59Skamil		case SIGFPE:
20131.59Skamil			trigger_fpe();
20141.59Skamil			break;
20151.59Skamil		case SIGBUS:
20161.59Skamil			trigger_bus();
20171.59Skamil			break;
20181.59Skamil		default:
20191.59Skamil			/* NOTREACHED */
20201.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
20211.59Skamil		}
20221.59Skamil
20231.59Skamil		/* NOTREACHED */
20241.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
20251.59Skamil	}
20261.59Skamil
20271.59Skamil	DPRINTF("Spawn debugger\n");
20281.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
20291.59Skamil	tracer = atf_utils_fork();
20301.59Skamil	if (tracer == 0) {
20311.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
20321.59Skamil		tracer = atf_utils_fork();
20331.59Skamil		if (tracer != 0)
20341.61Skre			_exit(exitval);
20351.59Skamil
20361.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
20371.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
20381.59Skamil
20391.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
20401.59Skamil		FORKEE_REQUIRE_SUCCESS(
20411.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20421.59Skamil
20431.59Skamil		forkee_status_stopped(status, SIGSTOP);
20441.59Skamil
20451.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20461.94Skamil		    "traced process\n");
20471.94Skamil		SYSCALL_REQUIRE(
20481.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20491.94Skamil
20501.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20511.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20521.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20531.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20541.94Skamil
20551.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20561.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20571.94Skamil
20581.59Skamil		/* Resume tracee with PT_CONTINUE */
20591.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20601.59Skamil
20611.59Skamil		/* Inform parent that tracer has attached to tracee */
20621.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20631.59Skamil
20641.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20651.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20661.59Skamil
20671.59Skamil		/* Wait for tracee and assert that it exited */
20681.59Skamil		FORKEE_REQUIRE_SUCCESS(
20691.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20701.59Skamil
20711.94Skamil		forkee_status_stopped(status, sigval);
20721.94Skamil
20731.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20741.94Skamil		    "traced process\n");
20751.94Skamil		SYSCALL_REQUIRE(
20761.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20771.94Skamil
20781.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20791.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20801.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20811.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20821.94Skamil
20831.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20841.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20851.94Skamil
20861.94Skamil		name[0] = CTL_KERN,
20871.94Skamil		name[1] = KERN_PROC2,
20881.94Skamil		name[2] = KERN_PROC_PID;
20891.94Skamil		name[3] = tracee;
20901.94Skamil		name[4] = sizeof(kp);
20911.94Skamil		name[5] = 1;
20921.94Skamil
20931.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20941.94Skamil
20951.94Skamil		if (masked)
20961.94Skamil			kp_sigmask = kp.p_sigmask;
20971.94Skamil
20981.94Skamil		if (ignored)
20991.94Skamil			kp_sigignore = kp.p_sigignore;
21001.94Skamil
21011.94Skamil		/* Resume tracee with PT_CONTINUE */
21021.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
21031.94Skamil
21041.94Skamil		/* Wait for tracee and assert that it exited */
21051.94Skamil		FORKEE_REQUIRE_SUCCESS(
21061.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21071.94Skamil
21081.93Skamil		forkee_status_stopped(status, sig);
21091.59Skamil
21101.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
21111.61Skre		    "traced process\n");
21121.61Skre		SYSCALL_REQUIRE(
21131.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
21141.59Skamil
21151.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
21161.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
21171.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
21181.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
21191.59Skamil
21201.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
21211.94Skamil
21221.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
21231.94Skamil
21241.94Skamil		if (masked) {
21251.94Skamil			DPRINTF("kp_sigmask="
21261.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21271.94Skamil			    PRIx32 "\n",
21281.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
21291.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
21301.94Skamil
21311.94Skamil			DPRINTF("kp.p_sigmask="
21321.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21331.94Skamil			    PRIx32 "\n",
21341.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
21351.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
21361.94Skamil
21371.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
21381.94Skamil			    sizeof(kp_sigmask)));
21391.94Skamil		}
21401.94Skamil
21411.94Skamil		if (ignored) {
21421.94Skamil			DPRINTF("kp_sigignore="
21431.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21441.94Skamil			    PRIx32 "\n",
21451.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21461.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21471.94Skamil
21481.94Skamil			DPRINTF("kp.p_sigignore="
21491.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21501.94Skamil			    PRIx32 "\n",
21511.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21521.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21531.94Skamil
21541.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21551.94Skamil			    sizeof(kp_sigignore)));
21561.94Skamil		}
21571.94Skamil
21581.59Skamil		switch (sig) {
21591.59Skamil		case SIGTRAP:
21601.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21611.59Skamil			break;
21621.59Skamil		case SIGSEGV:
21631.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21641.59Skamil			break;
21651.71Skamil		case SIGILL:
21661.113Skamil			FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC &&
21671.112Skamil			            info.psi_siginfo.si_code <= ILL_BADSTK);
21681.71Skamil			break;
21691.59Skamil		case SIGFPE:
21701.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21711.59Skamil			break;
21721.59Skamil		case SIGBUS:
21731.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21741.59Skamil			break;
21751.59Skamil		}
21761.59Skamil
21771.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21781.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21791.93Skamil		FORKEE_REQUIRE_SUCCESS(
21801.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21811.59Skamil
21821.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21831.59Skamil
21841.71Skamil		/* Inform parent that tracer is exiting normally */
21851.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21861.71Skamil
21871.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21881.59Skamil		_exit(0 /* collect by initproc */);
21891.59Skamil	}
21901.59Skamil
21911.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21921.59Skamil	    "calling %s()\n", TWAIT_FNAME);
21931.59Skamil	TWAIT_REQUIRE_SUCCESS(
21941.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21951.59Skamil
21961.59Skamil	validate_status_exited(status, exitval);
21971.59Skamil
21981.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
21991.59Skamil	    TWAIT_FNAME);
22001.59Skamil	TWAIT_REQUIRE_SUCCESS(
22011.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
22021.59Skamil
22031.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
22041.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
22051.59Skamil
22061.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
22071.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
22081.59Skamil
22091.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
22101.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
22111.59Skamil
22121.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
22131.59Skamil	    TWAIT_FNAME);
22141.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22151.59Skamil
22161.59Skamil	validate_status_signaled(status, SIGKILL, 0);
22171.59Skamil
22181.71Skamil	DPRINTF("Await normal exit of tracer\n");
22191.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
22201.71Skamil
22211.59Skamil	msg_close(&parent_tracer);
22221.59Skamil	msg_close(&parent_tracee);
22231.59Skamil}
22241.59Skamil
22251.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
22261.61SkreATF_TC(test);								\
22271.61SkreATF_TC_HEAD(test, tc)							\
22281.61Skre{									\
22291.61Skre	atf_tc_set_md_var(tc, "descr",					\
22301.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22311.94Skamil	    "the debuggee");						\
22321.61Skre}									\
22331.61Skre									\
22341.61SkreATF_TC_BODY(test, tc)							\
22351.61Skre{									\
22361.61Skre									\
22371.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
22381.59Skamil}
22391.59Skamil
22401.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
22411.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
22421.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
22431.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
22441.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22451.94Skamil
22461.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22471.94SkamilATF_TC(test);								\
22481.94SkamilATF_TC_HEAD(test, tc)							\
22491.94Skamil{									\
22501.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22511.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22521.94Skamil	    "the debuggee with masked signal");				\
22531.94Skamil}									\
22541.94Skamil									\
22551.94SkamilATF_TC_BODY(test, tc)							\
22561.94Skamil{									\
22571.94Skamil									\
22581.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22591.94Skamil}
22601.94Skamil
22611.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22621.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22631.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22641.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22651.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22661.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22671.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22681.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22691.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22701.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22711.94Skamil
22721.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22731.94SkamilATF_TC(test);								\
22741.94SkamilATF_TC_HEAD(test, tc)							\
22751.94Skamil{									\
22761.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22771.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22781.94Skamil	    "the debuggee with signal ignored");			\
22791.94Skamil}									\
22801.94Skamil									\
22811.94SkamilATF_TC_BODY(test, tc)							\
22821.94Skamil{									\
22831.94Skamil									\
22841.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22851.94Skamil}
22861.94Skamil
22871.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22881.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22891.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22901.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22911.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22921.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
22931.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22941.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
22951.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22961.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
22971.59Skamil#endif
22981.59Skamil
22991.59Skamil/// ----------------------------------------------------------------------------
23001.59Skamil
23011.59Skamil#if defined(TWAIT_HAVE_PID)
23021.59Skamilstatic void
23031.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
23041.67Skamil                                             bool stopped)
23051.1Skamil{
23061.51Skamil	/*
23071.51Skamil	 * notimeout - disable timeout in await zombie function
23081.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
23091.67Skamil	 * stopped - attach to a stopped process
23101.51Skamil	 */
23111.1Skamil
23121.1Skamil	struct msg_fds parent_tracee, parent_tracer;
23131.1Skamil	const int exitval_tracee = 5;
23141.1Skamil	const int exitval_tracer = 10;
23151.1Skamil	pid_t tracee, tracer, wpid;
23161.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
23171.1Skamil#if defined(TWAIT_HAVE_STATUS)
23181.1Skamil	int status;
23191.1Skamil#endif
23201.1Skamil
23211.67Skamil	/*
23221.67Skamil	 * Only a subset of options are supported.
23231.67Skamil	 */
23241.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
23251.67Skamil	            (!notimeout && unrelated && !stopped) ||
23261.67Skamil	            (notimeout && !unrelated && !stopped) ||
23271.67Skamil	            (!notimeout && unrelated && stopped));
23281.67Skamil
23291.13Schristos	DPRINTF("Spawn tracee\n");
23301.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
23311.1Skamil	tracee = atf_utils_fork();
23321.1Skamil	if (tracee == 0) {
23331.67Skamil		if (stopped) {
23341.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
23351.67Skamil			raise(SIGSTOP);
23361.67Skamil		}
23371.67Skamil
23381.1Skamil		// Wait for parent to let us exit
23391.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
23401.1Skamil		_exit(exitval_tracee);
23411.1Skamil	}
23421.1Skamil
23431.13Schristos	DPRINTF("Spawn debugger\n");
23441.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23451.1Skamil	tracer = atf_utils_fork();
23461.1Skamil	if (tracer == 0) {
23471.51Skamil		if(unrelated) {
23481.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23491.51Skamil			tracer = atf_utils_fork();
23501.51Skamil			if (tracer != 0)
23511.51Skamil				_exit(exitval_tracer);
23521.51Skamil		}
23531.51Skamil
23541.67Skamil		if (stopped) {
23551.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23561.67Skamil			await_stopped(tracee);
23571.67Skamil		}
23581.67Skamil
23591.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23601.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23611.1Skamil
23621.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23631.1Skamil		FORKEE_REQUIRE_SUCCESS(
23641.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23651.1Skamil
23661.1Skamil		forkee_status_stopped(status, SIGSTOP);
23671.1Skamil
23681.1Skamil		/* Resume tracee with PT_CONTINUE */
23691.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23701.1Skamil
23711.1Skamil		/* Inform parent that tracer has attached to tracee */
23721.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23731.1Skamil
23741.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23751.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23761.1Skamil
23771.1Skamil		/* Wait for tracee and assert that it exited */
23781.1Skamil		FORKEE_REQUIRE_SUCCESS(
23791.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23801.1Skamil
23811.1Skamil		forkee_status_exited(status, exitval_tracee);
23821.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23831.1Skamil
23841.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23851.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23861.51Skamil	}
23871.51Skamil
23881.51Skamil	if (unrelated) {
23891.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23901.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23911.51Skamil		TWAIT_REQUIRE_SUCCESS(
23921.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23931.51Skamil
23941.51Skamil		validate_status_exited(status, exitval_tracer);
23951.51Skamil
23961.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
23971.51Skamil		    TWAIT_FNAME);
23981.51Skamil		TWAIT_REQUIRE_SUCCESS(
23991.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
24001.1Skamil	}
24011.1Skamil
24021.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
24031.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
24041.1Skamil
24051.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
24061.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
24071.1Skamil
24081.13Schristos	DPRINTF("Detect that tracee is zombie\n");
24091.51Skamil	if (notimeout)
24101.26Skamil		await_zombie_raw(tracee, 0);
24111.26Skamil	else
24121.26Skamil		await_zombie(tracee);
24131.1Skamil
24141.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
24151.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
24161.1Skamil	    TWAIT_FNAME);
24171.1Skamil	TWAIT_REQUIRE_SUCCESS(
24181.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
24191.1Skamil
24201.51Skamil	if (unrelated) {
24211.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
24221.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
24231.51Skamil	} else {
24241.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
24251.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
24261.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
24271.59Skamil			"%s()\n", TWAIT_FNAME);
24281.51Skamil
24291.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
24301.59Skamil			"tracee\n");
24311.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
24321.51Skamil		    tracer);
24331.1Skamil
24341.51Skamil		validate_status_exited(status, exitval_tracer);
24351.51Skamil	}
24361.1Skamil
24371.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
24381.1Skamil	    TWAIT_FNAME);
24391.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
24401.1Skamil
24411.1Skamil	validate_status_exited(status, exitval_tracee);
24421.1Skamil
24431.1Skamil	msg_close(&parent_tracer);
24441.1Skamil	msg_close(&parent_tracee);
24451.1Skamil}
24461.26Skamil
24471.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24481.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24491.51Skamil{
24501.51Skamil	atf_tc_set_md_var(tc, "descr",
24511.51Skamil	    "Assert that tracer sees process termination before the parent");
24521.51Skamil}
24531.51Skamil
24541.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24551.26Skamil{
24561.26Skamil
24571.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24581.26Skamil}
24591.26Skamil
24601.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24611.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24621.1Skamil{
24631.1Skamil	atf_tc_set_md_var(tc, "descr",
24641.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24651.51Skamil	    "process and no other error is reported");
24661.1Skamil}
24671.1Skamil
24681.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24691.1Skamil{
24701.51Skamil	time_t start, end;
24711.51Skamil	double diff;
24721.51Skamil	unsigned long N = 0;
24731.1Skamil
24741.51Skamil	/*
24751.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24761.51Skamil	 * This test body isn't specific to this race, however it's just good
24771.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24781.51Skamil	 */
24791.1Skamil
24801.51Skamil	start = time(NULL);
24811.51Skamil	while (true) {
24821.51Skamil		DPRINTF("Step: %lu\n", N);
24831.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24841.67Skamil		                                             false);
24851.51Skamil		end = time(NULL);
24861.51Skamil		diff = difftime(end, start);
24871.51Skamil		if (diff >= 5.0)
24881.51Skamil			break;
24891.51Skamil		++N;
24901.1Skamil	}
24911.51Skamil	DPRINTF("Iterations: %lu\n", N);
24921.51Skamil}
24931.1Skamil
24941.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
24951.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24961.51Skamil{
24971.51Skamil	atf_tc_set_md_var(tc, "descr",
24981.51Skamil	    "Assert that tracer sees process termination before the parent");
24991.51Skamil}
25001.1Skamil
25011.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
25021.51Skamil{
25031.1Skamil
25041.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
25051.67Skamil}
25061.67Skamil
25071.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
25081.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
25091.67Skamil{
25101.67Skamil	atf_tc_set_md_var(tc, "descr",
25111.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
25121.67Skamil}
25131.67Skamil
25141.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
25151.67Skamil{
25161.67Skamil
25171.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
25181.1Skamil}
25191.1Skamil#endif
25201.1Skamil
25211.51Skamil/// ----------------------------------------------------------------------------
25221.51Skamil
25231.66Skamilstatic void
25241.66Skamilparent_attach_to_its_child(bool stopped)
25251.1Skamil{
25261.1Skamil	struct msg_fds parent_tracee;
25271.1Skamil	const int exitval_tracee = 5;
25281.1Skamil	pid_t tracee, wpid;
25291.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25301.1Skamil#if defined(TWAIT_HAVE_STATUS)
25311.1Skamil	int status;
25321.1Skamil#endif
25331.1Skamil
25341.13Schristos	DPRINTF("Spawn tracee\n");
25351.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25361.1Skamil	tracee = atf_utils_fork();
25371.1Skamil	if (tracee == 0) {
25381.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25391.13Schristos		DPRINTF("Parent should now attach to tracee\n");
25401.1Skamil
25411.66Skamil		if (stopped) {
25421.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
25431.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
25441.66Skamil		}
25451.66Skamil
25461.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25471.1Skamil		/* Wait for message from the parent */
25481.1Skamil		_exit(exitval_tracee);
25491.1Skamil	}
25501.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25511.57Skamil
25521.66Skamil	if (stopped) {
25531.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25541.66Skamil		await_stopped(tracee);
25551.66Skamil	}
25561.66Skamil
25571.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25591.1Skamil
25601.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25611.1Skamil	    TWAIT_FNAME);
25621.1Skamil	TWAIT_REQUIRE_SUCCESS(
25631.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25641.1Skamil
25651.1Skamil	validate_status_stopped(status, SIGSTOP);
25661.1Skamil
25671.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25691.1Skamil
25701.13Schristos	DPRINTF("Let the tracee exit now\n");
25711.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25721.1Skamil
25731.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25741.1Skamil	TWAIT_REQUIRE_SUCCESS(
25751.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25761.1Skamil
25771.1Skamil	validate_status_exited(status, exitval_tracee);
25781.1Skamil
25791.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25811.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25821.1Skamil
25831.1Skamil	msg_close(&parent_tracee);
25841.1Skamil}
25851.1Skamil
25861.66SkamilATF_TC(parent_attach_to_its_child);
25871.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25881.66Skamil{
25891.66Skamil	atf_tc_set_md_var(tc, "descr",
25901.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25911.66Skamil}
25921.66Skamil
25931.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
25941.66Skamil{
25951.66Skamil
25961.66Skamil	parent_attach_to_its_child(false);
25971.66Skamil}
25981.66Skamil
25991.66SkamilATF_TC(parent_attach_to_its_stopped_child);
26001.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
26011.66Skamil{
26021.66Skamil	atf_tc_set_md_var(tc, "descr",
26031.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
26041.66Skamil}
26051.66Skamil
26061.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
26071.66Skamil{
26081.66Skamil
26091.66Skamil	parent_attach_to_its_child(true);
26101.66Skamil}
26111.66Skamil
26121.51Skamil/// ----------------------------------------------------------------------------
26131.51Skamil
26141.65Skamilstatic void
26151.65Skamilchild_attach_to_its_parent(bool stopped)
26161.1Skamil{
26171.1Skamil	struct msg_fds parent_tracee;
26181.1Skamil	const int exitval_tracer = 5;
26191.1Skamil	pid_t tracer, wpid;
26201.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
26211.1Skamil#if defined(TWAIT_HAVE_STATUS)
26221.1Skamil	int status;
26231.1Skamil#endif
26241.1Skamil
26251.13Schristos	DPRINTF("Spawn tracer\n");
26261.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
26271.1Skamil	tracer = atf_utils_fork();
26281.1Skamil	if (tracer == 0) {
26291.1Skamil		/* Wait for message from the parent */
26301.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
26311.1Skamil
26321.65Skamil		if (stopped) {
26331.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
26341.65Skamil			        getppid());
26351.65Skamil			await_stopped(getppid());
26361.65Skamil		}
26371.65Skamil
26381.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
26391.1Skamil		    getppid());
26401.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
26411.1Skamil
26421.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
26431.1Skamil		    TWAIT_FNAME);
26441.1Skamil		FORKEE_REQUIRE_SUCCESS(
26451.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26461.1Skamil
26471.1Skamil		forkee_status_stopped(status, SIGSTOP);
26481.1Skamil
26491.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26501.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26511.1Skamil		    != -1);
26521.1Skamil
26531.1Skamil		/* Tell parent we are ready */
26541.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26551.1Skamil
26561.1Skamil		_exit(exitval_tracer);
26571.1Skamil	}
26581.1Skamil
26591.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26601.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26611.65Skamil
26621.65Skamil	if (stopped) {
26631.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26641.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26651.65Skamil	}
26661.65Skamil
26671.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26681.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26691.1Skamil
26701.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26711.1Skamil	TWAIT_REQUIRE_SUCCESS(
26721.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26731.1Skamil
26741.1Skamil	validate_status_exited(status, exitval_tracer);
26751.1Skamil
26761.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26781.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26791.1Skamil
26801.1Skamil	msg_close(&parent_tracee);
26811.1Skamil}
26821.1Skamil
26831.65SkamilATF_TC(child_attach_to_its_parent);
26841.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26851.65Skamil{
26861.65Skamil	atf_tc_set_md_var(tc, "descr",
26871.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26881.65Skamil}
26891.65Skamil
26901.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26911.65Skamil{
26921.65Skamil
26931.65Skamil	child_attach_to_its_parent(false);
26941.65Skamil}
26951.65Skamil
26961.65SkamilATF_TC(child_attach_to_its_stopped_parent);
26971.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
26981.65Skamil{
26991.65Skamil	atf_tc_set_md_var(tc, "descr",
27001.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
27011.65Skamil}
27021.65Skamil
27031.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
27041.65Skamil{
27051.65Skamil	/*
27061.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
27071.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
27081.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
27091.65Skamil	 *
27101.65Skamil	 * As a workaround spawn this test as a subprocess.
27111.65Skamil	 */
27121.65Skamil
27131.65Skamil	const int exitval = 15;
27141.65Skamil	pid_t child, wpid;
27151.65Skamil#if defined(TWAIT_HAVE_STATUS)
27161.65Skamil	int status;
27171.65Skamil#endif
27181.65Skamil
27191.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
27201.65Skamil	if (child == 0) {
27211.65Skamil		child_attach_to_its_parent(true);
27221.65Skamil		_exit(exitval);
27231.65Skamil	} else {
27241.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27251.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27261.65Skamil
27271.65Skamil		validate_status_exited(status, exitval);
27281.65Skamil
27291.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
27301.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27311.65Skamil	}
27321.65Skamil}
27331.65Skamil
27341.51Skamil/// ----------------------------------------------------------------------------
27351.51Skamil
27361.1Skamil#if defined(TWAIT_HAVE_PID)
27371.1Skamil
27381.51Skamilenum tracee_sees_its_original_parent_type {
27391.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
27401.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
27411.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
27421.51Skamil};
27431.51Skamil
27441.51Skamilstatic void
27451.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27461.1Skamil{
27471.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27481.1Skamil	const int exitval_tracee = 5;
27491.1Skamil	const int exitval_tracer = 10;
27501.1Skamil	pid_t parent, tracee, tracer, wpid;
27511.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27521.1Skamil#if defined(TWAIT_HAVE_STATUS)
27531.1Skamil	int status;
27541.1Skamil#endif
27551.51Skamil	/* sysctl(3) - kinfo_proc2 */
27561.51Skamil	int name[CTL_MAXNAME];
27571.51Skamil	struct kinfo_proc2 kp;
27581.51Skamil	size_t len = sizeof(kp);
27591.51Skamil	unsigned int namelen;
27601.51Skamil
27611.51Skamil	/* procfs - status  */
27621.51Skamil	FILE *fp;
27631.51Skamil	struct stat st;
27641.51Skamil	const char *fname = "/proc/curproc/status";
27651.51Skamil	char s_executable[MAXPATHLEN];
27661.51Skamil	int s_pid, s_ppid;
27671.51Skamil	int rv;
27681.51Skamil
27691.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27701.61Skre		SYSCALL_REQUIRE(
27711.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27721.61Skre		if (rv != 0)
27731.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27741.51Skamil	}
27751.1Skamil
27761.13Schristos	DPRINTF("Spawn tracee\n");
27771.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27781.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27791.1Skamil	tracee = atf_utils_fork();
27801.1Skamil	if (tracee == 0) {
27811.1Skamil		parent = getppid();
27821.1Skamil
27831.1Skamil		/* Emit message to the parent */
27841.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27851.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27861.1Skamil
27871.51Skamil		switch (type) {
27881.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27891.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27901.51Skamil			break;
27911.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27921.51Skamil			namelen = 0;
27931.51Skamil			name[namelen++] = CTL_KERN;
27941.51Skamil			name[namelen++] = KERN_PROC2;
27951.51Skamil			name[namelen++] = KERN_PROC_PID;
27961.51Skamil			name[namelen++] = getpid();
27971.51Skamil			name[namelen++] = len;
27981.51Skamil			name[namelen++] = 1;
27991.51Skamil
28001.61Skre			FORKEE_ASSERT_EQ(
28011.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
28021.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
28031.51Skamil			break;
28041.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
28051.51Skamil			/*
28061.51Skamil			 * Format:
28071.51Skamil			 *  EXECUTABLE PID PPID ...
28081.51Skamil			 */
28091.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
28101.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
28111.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
28121.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
28131.51Skamil			break;
28141.51Skamil		}
28151.1Skamil
28161.1Skamil		_exit(exitval_tracee);
28171.1Skamil	}
28181.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
28191.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
28201.1Skamil
28211.13Schristos	DPRINTF("Spawn debugger\n");
28221.1Skamil	tracer = atf_utils_fork();
28231.1Skamil	if (tracer == 0) {
28241.1Skamil		/* No IPC to communicate with the child */
28251.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
28261.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
28271.1Skamil
28281.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
28291.1Skamil		FORKEE_REQUIRE_SUCCESS(
28301.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28311.1Skamil
28321.1Skamil		forkee_status_stopped(status, SIGSTOP);
28331.1Skamil
28341.1Skamil		/* Resume tracee with PT_CONTINUE */
28351.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
28361.1Skamil
28371.1Skamil		/* Inform parent that tracer has attached to tracee */
28381.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
28391.1Skamil
28401.1Skamil		/* Wait for parent to tell use that tracee should have exited */
28411.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
28421.1Skamil
28431.1Skamil		/* Wait for tracee and assert that it exited */
28441.1Skamil		FORKEE_REQUIRE_SUCCESS(
28451.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28461.1Skamil
28471.1Skamil		forkee_status_exited(status, exitval_tracee);
28481.1Skamil
28491.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28501.1Skamil		_exit(exitval_tracer);
28511.1Skamil	}
28521.1Skamil
28531.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28541.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28551.1Skamil
28561.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28571.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28581.1Skamil
28591.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28601.1Skamil	await_zombie(tracee);
28611.1Skamil
28621.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28631.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28641.1Skamil	TWAIT_REQUIRE_SUCCESS(
28651.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28661.1Skamil
28671.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28681.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28691.1Skamil
28701.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28721.1Skamil	    tracer);
28731.1Skamil
28741.1Skamil	validate_status_exited(status, exitval_tracer);
28751.1Skamil
28761.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28771.1Skamil	    TWAIT_FNAME);
28781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28791.1Skamil	    tracee);
28801.1Skamil
28811.1Skamil	validate_status_exited(status, exitval_tracee);
28821.1Skamil
28831.1Skamil	msg_close(&parent_tracer);
28841.1Skamil	msg_close(&parent_tracee);
28851.1Skamil}
28861.1Skamil
28871.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28881.61SkreATF_TC(test);								\
28891.61SkreATF_TC_HEAD(test, tc)							\
28901.61Skre{									\
28911.61Skre	atf_tc_set_md_var(tc, "descr",					\
28921.61Skre	    "Assert that tracee sees its original parent when being traced " \
28931.61Skre	    "(check " descr ")");					\
28941.61Skre}									\
28951.61Skre									\
28961.61SkreATF_TC_BODY(test, tc)							\
28971.61Skre{									\
28981.61Skre									\
28991.61Skre	tracee_sees_its_original_parent(type);				\
29001.1Skamil}
29011.1Skamil
29021.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29031.51Skamil	tracee_sees_its_original_parent_getppid,
29041.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
29051.51Skamil	"getppid(2)");
29061.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29071.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
29081.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
29091.51Skamil	"sysctl(3) and kinfo_proc2");
29101.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29111.51Skamil	tracee_sees_its_original_parent_procfs_status,
29121.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
29131.51Skamil	"the status file in procfs");
29141.1Skamil#endif
29151.1Skamil
29161.51Skamil/// ----------------------------------------------------------------------------
29171.1Skamil
29181.53Skamilstatic void
29191.53Skamileventmask_preserved(int event)
29201.1Skamil{
29211.1Skamil	const int exitval = 5;
29221.1Skamil	const int sigval = SIGSTOP;
29231.1Skamil	pid_t child, wpid;
29241.1Skamil#if defined(TWAIT_HAVE_STATUS)
29251.1Skamil	int status;
29261.1Skamil#endif
29271.1Skamil	ptrace_event_t set_event, get_event;
29281.1Skamil	const int len = sizeof(ptrace_event_t);
29291.1Skamil
29301.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29311.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29321.1Skamil	if (child == 0) {
29331.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29341.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29351.1Skamil
29361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29381.1Skamil
29391.13Schristos		DPRINTF("Before exiting of the child process\n");
29401.1Skamil		_exit(exitval);
29411.1Skamil	}
29421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29431.1Skamil
29441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29461.1Skamil
29471.1Skamil	validate_status_stopped(status, sigval);
29481.1Skamil
29491.53Skamil	set_event.pe_set_event = event;
29501.61Skre	SYSCALL_REQUIRE(
29511.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29521.61Skre	SYSCALL_REQUIRE(
29531.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29541.125Skamil	DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event,
29551.125Skamil	    get_event.pe_set_event);
29561.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29571.1Skamil
29581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29591.1Skamil	    "without signal to be sent\n");
29601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29611.1Skamil
29621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29641.1Skamil
29651.1Skamil	validate_status_exited(status, exitval);
29661.1Skamil
29671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29691.1Skamil}
29701.1Skamil
29711.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29721.61SkreATF_TC(test);								\
29731.61SkreATF_TC_HEAD(test, tc)							\
29741.61Skre{									\
29751.61Skre	atf_tc_set_md_var(tc, "descr",					\
29761.61Skre	    "Verify that eventmask " #event " is preserved");		\
29771.61Skre}									\
29781.61Skre									\
29791.61SkreATF_TC_BODY(test, tc)							\
29801.61Skre{									\
29811.61Skre									\
29821.61Skre	eventmask_preserved(event);					\
29831.1Skamil}
29841.1Skamil
29851.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29861.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29871.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29881.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29891.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29901.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29911.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN)
29921.1Skamil
29931.53Skamil/// ----------------------------------------------------------------------------
29941.1Skamil
29951.28Skamilstatic void
29961.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork,
29971.105Skamil    bool trackvforkdone)
29981.1Skamil{
29991.1Skamil	const int exitval = 5;
30001.125Skamil	const int exitval2 = 0; /* This matched exit status from /bin/echo */
30011.1Skamil	const int sigval = SIGSTOP;
30021.31Skamil	pid_t child, child2 = 0, wpid;
30031.1Skamil#if defined(TWAIT_HAVE_STATUS)
30041.1Skamil	int status;
30051.1Skamil#endif
30061.1Skamil	ptrace_state_t state;
30071.1Skamil	const int slen = sizeof(state);
30081.1Skamil	ptrace_event_t event;
30091.1Skamil	const int elen = sizeof(event);
30101.1Skamil
30111.124Skamil	char * const arg[] = { __UNCONST("/bin/echo"), NULL };
30121.124Skamil
30131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30151.1Skamil	if (child == 0) {
30161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30181.1Skamil
30191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30211.1Skamil
30221.125Skamil		if (strcmp(fn, "spawn") == 0) {
30231.124Skamil			FORKEE_ASSERT_EQ(posix_spawn(&child2,
30241.124Skamil			    arg[0], NULL, NULL, arg, NULL), 0);
30251.125Skamil		} else {
30261.125Skamil			if (strcmp(fn, "fork") == 0) {
30271.125Skamil				FORKEE_ASSERT((child2 = fork()) != -1);
30281.125Skamil			} else if (strcmp(fn, "vfork") == 0) {
30291.125Skamil				FORKEE_ASSERT((child2 = vfork()) != -1);
30301.125Skamil			}
30311.1Skamil
30321.124Skamil			if (child2 == 0)
30331.124Skamil				_exit(exitval2);
30341.124Skamil		}
30351.1Skamil		FORKEE_REQUIRE_SUCCESS
30361.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30371.1Skamil
30381.1Skamil		forkee_status_exited(status, exitval2);
30391.1Skamil
30401.13Schristos		DPRINTF("Before exiting of the child process\n");
30411.1Skamil		_exit(exitval);
30421.1Skamil	}
30431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30441.1Skamil
30451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30471.1Skamil
30481.1Skamil	validate_status_stopped(status, sigval);
30491.1Skamil
30501.125Skamil	DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n",
30511.125Skamil	    trackspawn ? "|PTRACE_POSIX_SPAWN" : "",
30521.61Skre	    trackfork ? "|PTRACE_FORK" : "",
30531.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
30541.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
30551.30Skamil	event.pe_set_event = 0;
30561.125Skamil	if (trackspawn)
30571.125Skamil		event.pe_set_event |= PTRACE_POSIX_SPAWN;
30581.30Skamil	if (trackfork)
30591.30Skamil		event.pe_set_event |= PTRACE_FORK;
30601.30Skamil	if (trackvfork)
30611.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30621.30Skamil	if (trackvforkdone)
30631.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30651.1Skamil
30661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30671.1Skamil	    "without signal to be sent\n");
30681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30691.1Skamil
30701.29Skamil#if defined(TWAIT_HAVE_PID)
30711.125Skamil	if ((trackspawn && strcmp(fn, "spawn") == 0) ||
30721.125Skamil	    (trackfork && strcmp(fn, "fork") == 0) ||
30731.125Skamil	    (trackvfork && strcmp(fn, "vfork") == 0)) {
30741.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30751.61Skre		    child);
30761.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30771.61Skre		    child);
30781.1Skamil
30791.29Skamil		validate_status_stopped(status, SIGTRAP);
30801.1Skamil
30811.61Skre		SYSCALL_REQUIRE(
30821.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30831.125Skamil		if (trackspawn && strcmp(fn, "spawn") == 0) {
30841.125Skamil			ATF_REQUIRE_EQ(
30851.125Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
30861.125Skamil			       PTRACE_POSIX_SPAWN);
30871.125Skamil		}
30881.125Skamil		if (trackfork && strcmp(fn, "fork") == 0) {
30891.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30901.30Skamil			       PTRACE_FORK);
30911.30Skamil		}
30921.125Skamil		if (trackvfork && strcmp(fn, "vfork") == 0) {
30931.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30941.30Skamil			       PTRACE_VFORK);
30951.30Skamil		}
30961.29Skamil
30971.29Skamil		child2 = state.pe_other_pid;
30981.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
30991.29Skamil
31001.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
31011.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
31021.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
31031.29Skamil		    child2);
31041.1Skamil
31051.29Skamil		validate_status_stopped(status, SIGTRAP);
31061.1Skamil
31071.61Skre		SYSCALL_REQUIRE(
31081.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
31091.125Skamil		if (trackspawn && strcmp(fn, "spawn") == 0) {
31101.125Skamil			ATF_REQUIRE_EQ(
31111.125Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
31121.125Skamil			       PTRACE_POSIX_SPAWN);
31131.125Skamil		}
31141.125Skamil		if (trackfork && strcmp(fn, "fork") == 0) {
31151.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
31161.30Skamil			       PTRACE_FORK);
31171.30Skamil		}
31181.125Skamil		if (trackvfork && strcmp(fn, "vfork") == 0) {
31191.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
31201.30Skamil			       PTRACE_VFORK);
31211.30Skamil		}
31221.30Skamil
31231.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
31241.29Skamil
31251.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
31261.29Skamil		    "and without signal to be sent\n");
31271.61Skre		SYSCALL_REQUIRE(
31281.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
31291.29Skamil
31301.29Skamil		DPRINTF("Before resuming the child process where it left off "
31311.61Skre		    "and without signal to be sent\n");
31321.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31331.30Skamil	}
31341.30Skamil#endif
31351.30Skamil
31361.125Skamil	if (trackvforkdone && strcmp(fn, "vfork") == 0) {
31371.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
31381.61Skre		    child);
31391.61Skre		TWAIT_REQUIRE_SUCCESS(
31401.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
31411.30Skamil
31421.30Skamil		validate_status_stopped(status, SIGTRAP);
31431.30Skamil
31441.61Skre		SYSCALL_REQUIRE(
31451.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
31461.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
31471.30Skamil
31481.30Skamil		child2 = state.pe_other_pid;
31491.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
31501.61Skre		    child2);
31511.30Skamil
31521.30Skamil		DPRINTF("Before resuming the child process where it left off "
31531.61Skre		    "and without signal to be sent\n");
31541.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31551.30Skamil	}
31561.29Skamil
31571.30Skamil#if defined(TWAIT_HAVE_PID)
31581.125Skamil	if ((trackspawn && strcmp(fn, "spawn") == 0) ||
31591.125Skamil	    (trackfork && strcmp(fn, "fork") == 0) ||
31601.125Skamil	    (trackvfork && strcmp(fn, "vfork") == 0)) {
31611.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
31621.61Skre		    "\n", TWAIT_FNAME);
31631.61Skre		TWAIT_REQUIRE_SUCCESS(
31641.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
31651.29Skamil
31661.29Skamil		validate_status_exited(status, exitval2);
31671.29Skamil
31681.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
31691.61Skre		    "process\n", TWAIT_FNAME);
31701.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
31711.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
31721.29Skamil	}
31731.29Skamil#endif
31741.1Skamil
31751.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31761.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31781.1Skamil
31791.1Skamil	validate_status_stopped(status, SIGCHLD);
31801.1Skamil
31811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31821.1Skamil	    "without signal to be sent\n");
31831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31841.1Skamil
31851.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31861.1Skamil	    TWAIT_FNAME);
31871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31881.1Skamil
31891.1Skamil	validate_status_exited(status, exitval);
31901.1Skamil
31911.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31921.1Skamil	    TWAIT_FNAME);
31931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31941.1Skamil}
31951.28Skamil
31961.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone)		\
31971.61SkreATF_TC(name);								\
31981.61SkreATF_TC_HEAD(name, tc)							\
31991.61Skre{									\
32001.125Skamil	atf_tc_set_md_var(tc, "descr", "Verify " fun "() "		\
32011.125Skamil	    "called with 0%s%s%s%s in EVENT_MASK",			\
32021.126Skamil	    tspawn ? "|PTRACE_POSIX_SPAWN" : "",			\
32031.105Skamil	    tfork ? "|PTRACE_FORK" : "",				\
32041.105Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
32051.105Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
32061.61Skre}									\
32071.61Skre									\
32081.61SkreATF_TC_BODY(name, tc)							\
32091.61Skre{									\
32101.61Skre									\
32111.125Skamil	fork_body(fun, tspawn, tfork, tvfork, tvforkdone);		\
32121.32Skamil}
32131.32Skamil
32141.125SkamilFORK_TEST(fork1, "fork", false, false, false, false)
32151.31Skamil#if defined(TWAIT_HAVE_PID)
32161.125SkamilFORK_TEST(fork2, "fork", false, true, false, false)
32171.125SkamilFORK_TEST(fork3, "fork", false, false, true, false)
32181.125SkamilFORK_TEST(fork4, "fork", false, true, true, false)
32191.31Skamil#endif
32201.125SkamilFORK_TEST(fork5, "fork", false, false, false, true)
32211.31Skamil#if defined(TWAIT_HAVE_PID)
32221.125SkamilFORK_TEST(fork6, "fork", false, true, false, true)
32231.125SkamilFORK_TEST(fork7, "fork", false, false, true, true)
32241.125SkamilFORK_TEST(fork8, "fork", false, true, true, true)
32251.125Skamil#endif
32261.125SkamilFORK_TEST(fork9, "fork", true, false, false, false)
32271.125Skamil#if defined(TWAIT_HAVE_PID)
32281.125SkamilFORK_TEST(fork10, "fork", true, true, false, false)
32291.125SkamilFORK_TEST(fork11, "fork", true, false, true, false)
32301.125SkamilFORK_TEST(fork12, "fork", true, true, true, false)
32311.125Skamil#endif
32321.125SkamilFORK_TEST(fork13, "fork", true, false, false, true)
32331.125Skamil#if defined(TWAIT_HAVE_PID)
32341.125SkamilFORK_TEST(fork14, "fork", true, true, false, true)
32351.125SkamilFORK_TEST(fork15, "fork", true, false, true, true)
32361.125SkamilFORK_TEST(fork16, "fork", true, true, true, true)
32371.31Skamil#endif
32381.1Skamil
32391.110Skamil#if TEST_VFORK_ENABLED
32401.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false)
32411.31Skamil#if defined(TWAIT_HAVE_PID)
32421.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false)
32431.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false)
32441.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false)
32451.31Skamil#endif
32461.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true)
32471.31Skamil#if defined(TWAIT_HAVE_PID)
32481.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true)
32491.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true)
32501.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true)
32511.31Skamil#endif
32521.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false)
32531.125Skamil#if defined(TWAIT_HAVE_PID)
32541.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false)
32551.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false)
32561.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false)
32571.110Skamil#endif
32581.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true)
32591.124Skamil#if defined(TWAIT_HAVE_PID)
32601.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true)
32611.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true)
32621.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true)
32631.124Skamil#endif
32641.125Skamil#endif
32651.125Skamil
32661.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false)
32671.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false)
32681.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false)
32691.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false)
32701.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true)
32711.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true)
32721.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true)
32731.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true)
32741.124Skamil#if defined(TWAIT_HAVE_PID)
32751.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false)
32761.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false)
32771.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false)
32781.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false)
32791.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true)
32801.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true)
32811.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true)
32821.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true)
32831.124Skamil#endif
32841.124Skamil
32851.54Skamil/// ----------------------------------------------------------------------------
32861.31Skamil
32871.116Skamil#if defined(TWAIT_HAVE_PID)
32881.116Skamilstatic void
32891.126Skamilfork_detach_forker_body(const char *fn, bool kill_process)
32901.116Skamil{
32911.116Skamil	const int exitval = 5;
32921.126Skamil	const int exitval2 = 0; /* Matches exit value from /bin/echo */
32931.116Skamil	const int sigval = SIGSTOP;
32941.116Skamil	pid_t child, child2 = 0, wpid;
32951.116Skamil#if defined(TWAIT_HAVE_STATUS)
32961.116Skamil	int status;
32971.116Skamil#endif
32981.116Skamil	ptrace_state_t state;
32991.116Skamil	const int slen = sizeof(state);
33001.116Skamil	ptrace_event_t event;
33011.116Skamil	const int elen = sizeof(event);
33021.116Skamil
33031.116Skamil	int op;
33041.116Skamil
33051.126Skamil	char * const arg[] = { __UNCONST("/bin/echo"), NULL };
33061.116Skamil
33071.116Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
33081.116Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
33091.116Skamil	if (child == 0) {
33101.116Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33111.116Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33121.116Skamil
33131.116Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33141.116Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33151.116Skamil
33161.126Skamil		if (strcmp(fn, "spawn") == 0) {
33171.126Skamil			FORKEE_ASSERT_EQ(posix_spawn(&child2,
33181.126Skamil			    arg[0], NULL, NULL, arg, NULL), 0);
33191.126Skamil		} else  {
33201.126Skamil			if (strcmp(fn, "fork") == 0) {
33211.126Skamil				FORKEE_ASSERT((child2 = fork()) != -1);
33221.126Skamil			} else {
33231.126Skamil				FORKEE_ASSERT((child2 = vfork()) != -1);
33241.126Skamil			}
33251.116Skamil
33261.126Skamil			if (child2 == 0)
33271.126Skamil				_exit(exitval2);
33281.126Skamil		}
33291.116Skamil
33301.116Skamil		FORKEE_REQUIRE_SUCCESS
33311.116Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
33321.116Skamil
33331.116Skamil		forkee_status_exited(status, exitval2);
33341.116Skamil
33351.116Skamil		DPRINTF("Before exiting of the child process\n");
33361.116Skamil		_exit(exitval);
33371.116Skamil	}
33381.116Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33391.116Skamil
33401.116Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33411.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33421.116Skamil
33431.116Skamil	validate_status_stopped(status, sigval);
33441.116Skamil
33451.116Skamil	DPRINTF("Set EVENT_MASK for the child %d\n", child);
33461.126Skamil	event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK
33471.126Skamil		| PTRACE_VFORK_DONE;
33481.116Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
33491.116Skamil
33501.116Skamil	DPRINTF("Before resuming the child process where it left off and "
33511.116Skamil	    "without signal to be sent\n");
33521.116Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33531.116Skamil
33541.116Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
33551.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33561.116Skamil
33571.116Skamil	validate_status_stopped(status, SIGTRAP);
33581.116Skamil
33591.116Skamil	SYSCALL_REQUIRE(
33601.116Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
33611.126Skamil
33621.126Skamil	if (strcmp(fn, "spawn") == 0)
33631.126Skamil		op = PTRACE_POSIX_SPAWN;
33641.126Skamil	else if (strcmp(fn, "fork") == 0)
33651.126Skamil		op = PTRACE_FORK;
33661.126Skamil	else
33671.126Skamil		op = PTRACE_VFORK;
33681.126Skamil
33691.116Skamil	ATF_REQUIRE_EQ(state.pe_report_event & op, op);
33701.116Skamil
33711.116Skamil	child2 = state.pe_other_pid;
33721.116Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
33731.116Skamil
33741.126Skamil	if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 ||
33751.126Skamil	    strcmp(fn, "vfork") == 0)
33761.116Skamil		op = kill_process ? PT_KILL : PT_DETACH;
33771.116Skamil	else
33781.116Skamil		op = PT_CONTINUE;
33791.116Skamil	SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1);
33801.116Skamil
33811.116Skamil	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
33821.116Skamil	    TWAIT_FNAME, child2, child);
33831.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
33841.116Skamil
33851.116Skamil	validate_status_stopped(status, SIGTRAP);
33861.116Skamil
33871.116Skamil	SYSCALL_REQUIRE(
33881.116Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
33891.126Skamil	if (strcmp(fn, "spawn") == 0)
33901.126Skamil		op = PTRACE_POSIX_SPAWN;
33911.126Skamil	else if (strcmp(fn, "fork") == 0)
33921.126Skamil		op = PTRACE_FORK;
33931.126Skamil	else
33941.126Skamil		op = PTRACE_VFORK;
33951.126Skamil
33961.116Skamil	ATF_REQUIRE_EQ(state.pe_report_event & op, op);
33971.116Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
33981.116Skamil
33991.116Skamil	DPRINTF("Before resuming the forkee process where it left off "
34001.116Skamil	    "and without signal to be sent\n");
34011.116Skamil 	SYSCALL_REQUIRE(
34021.116Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
34031.116Skamil
34041.126Skamil	if (strcmp(fn, "vforkdone") == 0) {
34051.116Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
34061.116Skamil		    child);
34071.116Skamil		TWAIT_REQUIRE_SUCCESS(
34081.116Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
34091.116Skamil
34101.116Skamil		validate_status_stopped(status, SIGTRAP);
34111.116Skamil
34121.116Skamil		SYSCALL_REQUIRE(
34131.116Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
34141.116Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
34151.116Skamil
34161.116Skamil		child2 = state.pe_other_pid;
34171.116Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
34181.116Skamil		    child2);
34191.116Skamil
34201.116Skamil		op = kill_process ? PT_KILL : PT_DETACH;
34211.116Skamil		DPRINTF("Before resuming the child process where it left off "
34221.116Skamil		    "and without signal to be sent\n");
34231.116Skamil		SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1);
34241.116Skamil	}
34251.116Skamil
34261.116Skamil	DPRINTF("Before calling %s() for the forkee - expected exited\n",
34271.116Skamil	    TWAIT_FNAME);
34281.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
34291.116Skamil
34301.116Skamil	validate_status_exited(status, exitval2);
34311.116Skamil
34321.116Skamil	DPRINTF("Before calling %s() for the forkee - expected no process\n",
34331.116Skamil	    TWAIT_FNAME);
34341.116Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0));
34351.116Skamil
34361.116Skamil	DPRINTF("Before calling %s() for the forkee - expected exited\n",
34371.116Skamil	    TWAIT_FNAME);
34381.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34391.116Skamil
34401.116Skamil	if (kill_process) {
34411.116Skamil		validate_status_signaled(status, SIGKILL, 0);
34421.116Skamil	} else {
34431.116Skamil		validate_status_exited(status, exitval);
34441.116Skamil	}
34451.116Skamil
34461.116Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
34471.116Skamil	    TWAIT_FNAME);
34481.116Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34491.116Skamil}
34501.116Skamil
34511.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess)				\
34521.116SkamilATF_TC(name);								\
34531.116SkamilATF_TC_HEAD(name, tc)							\
34541.116Skamil{									\
34551.126Skamil	atf_tc_set_md_var(tc, "descr", "Verify %s " event,		\
34561.126Skamil	    kprocess ? "killed" : "detached");				\
34571.116Skamil}									\
34581.116Skamil									\
34591.116SkamilATF_TC_BODY(name, tc)							\
34601.116Skamil{									\
34611.116Skamil									\
34621.126Skamil	fork_detach_forker_body(event, kprocess);			\
34631.116Skamil}
34641.116Skamil
34651.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false)
34661.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false)
34671.116Skamil#if TEST_VFORK_ENABLED
34681.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false)
34691.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false)
34701.116Skamil#endif
34711.126Skamil
34721.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true)
34731.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true)
34741.116Skamil#if TEST_VFORK_ENABLED
34751.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true)
34761.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true)
34771.116Skamil#endif
34781.116Skamil#endif
34791.116Skamil
34801.116Skamil/// ----------------------------------------------------------------------------
34811.116Skamil
34821.110Skamil#if TEST_VFORK_ENABLED
34831.108Skamilstatic void
34841.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void))
34851.108Skamil{
34861.108Skamil	const int exitval = 5;
34871.108Skamil	const int exitval2 = 15;
34881.108Skamil	pid_t child, child2 = 0, wpid;
34891.108Skamil#if defined(TWAIT_HAVE_STATUS)
34901.108Skamil	int status;
34911.108Skamil#endif
34921.108Skamil
34931.108Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
34941.108Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
34951.108Skamil	if (child == 0) {
34961.108Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34971.108Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34981.108Skamil
34991.108Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
35001.108Skamil
35011.108Skamil		if (child2 == 0)
35021.108Skamil			_exit(exitval2);
35031.108Skamil
35041.108Skamil		FORKEE_REQUIRE_SUCCESS
35051.108Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
35061.108Skamil
35071.108Skamil		forkee_status_exited(status, exitval2);
35081.108Skamil
35091.108Skamil		DPRINTF("Before exiting of the child process\n");
35101.108Skamil		_exit(exitval);
35111.108Skamil	}
35121.108Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35131.108Skamil
35141.108Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
35151.108Skamil	    TWAIT_FNAME);
35161.108Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35171.108Skamil
35181.108Skamil	validate_status_exited(status, exitval);
35191.108Skamil
35201.108Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
35211.108Skamil	    TWAIT_FNAME);
35221.108Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35231.108Skamil}
35241.108Skamil
35251.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun)				\
35261.108SkamilATF_TC(name);								\
35271.108SkamilATF_TC_HEAD(name, tc)							\
35281.108Skamil{									\
35291.108Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
35301.108Skamil	    "called from vfork(2)ed child");				\
35311.108Skamil}									\
35321.108Skamil									\
35331.108SkamilATF_TC_BODY(name, tc)							\
35341.108Skamil{									\
35351.108Skamil									\
35361.108Skamil	traceme_vfork_fork_body(fun);					\
35371.108Skamil}
35381.108Skamil
35391.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork)
35401.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork)
35411.110Skamil#endif
35421.108Skamil
35431.108Skamil/// ----------------------------------------------------------------------------
35441.108Skamil
35451.54Skamilenum bytes_transfer_type {
35461.54Skamil	BYTES_TRANSFER_DATA,
35471.54Skamil	BYTES_TRANSFER_DATAIO,
35481.54Skamil	BYTES_TRANSFER_TEXT,
35491.54Skamil	BYTES_TRANSFER_TEXTIO,
35501.54Skamil	BYTES_TRANSFER_AUXV
35511.54Skamil};
35521.31Skamil
35531.54Skamilstatic int __used
35541.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
35551.54Skamil{
35561.54Skamil	int e, f, g, h;
35571.1Skamil
35581.54Skamil	a *= 4;
35591.54Skamil	b += 3;
35601.54Skamil	c -= 2;
35611.54Skamil	d /= 1;
35621.1Skamil
35631.54Skamil	e = strtol("10", NULL, 10);
35641.54Skamil	f = strtol("20", NULL, 10);
35651.54Skamil	g = strtol("30", NULL, 10);
35661.54Skamil	h = strtol("40", NULL, 10);
35671.1Skamil
35681.54Skamil	return (a + b * c - d) + (e * f - g / h);
35691.1Skamil}
35701.1Skamil
35711.54Skamilstatic void
35721.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
35731.1Skamil{
35741.1Skamil	const int exitval = 5;
35751.1Skamil	const int sigval = SIGSTOP;
35761.1Skamil	pid_t child, wpid;
35771.54Skamil	bool skip = false;
35781.1Skamil
35791.54Skamil	int lookup_me = 0;
35801.54Skamil	uint8_t lookup_me8 = 0;
35811.54Skamil	uint16_t lookup_me16 = 0;
35821.54Skamil	uint32_t lookup_me32 = 0;
35831.54Skamil	uint64_t lookup_me64 = 0;
35841.1Skamil
35851.54Skamil	int magic = 0x13579246;
35861.54Skamil	uint8_t magic8 = 0xab;
35871.54Skamil	uint16_t magic16 = 0x1234;
35881.54Skamil	uint32_t magic32 = 0x98765432;
35891.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
35901.1Skamil
35911.54Skamil	struct ptrace_io_desc io;
35921.1Skamil#if defined(TWAIT_HAVE_STATUS)
35931.1Skamil	int status;
35941.1Skamil#endif
35951.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
35961.60Skre	AuxInfo ai[513], *aip;
35971.55Schristos
35981.55Schristos	ATF_REQUIRE(size < sizeof(ai));
35991.1Skamil
36001.54Skamil	/* Prepare variables for .TEXT transfers */
36011.54Skamil	switch (type) {
36021.54Skamil	case BYTES_TRANSFER_TEXT:
36031.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
36041.54Skamil		break;
36051.54Skamil	case BYTES_TRANSFER_TEXTIO:
36061.54Skamil		switch (size) {
36071.54Skamil		case 8:
36081.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
36091.54Skamil			break;
36101.54Skamil		case 16:
36111.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
36121.54Skamil			break;
36131.54Skamil		case 32:
36141.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
36151.54Skamil			break;
36161.54Skamil		case 64:
36171.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
36181.54Skamil			break;
36191.54Skamil		}
36201.54Skamil		break;
36211.54Skamil	default:
36221.54Skamil		break;
36231.54Skamil	}
36241.1Skamil
36251.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
36261.54Skamil	switch (type) {
36271.54Skamil	case BYTES_TRANSFER_TEXTIO:
36281.54Skamil	case BYTES_TRANSFER_DATAIO:
36291.54Skamil		io.piod_op = operation;
36301.54Skamil		switch (size) {
36311.54Skamil		case 8:
36321.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36331.54Skamil			               (void *)bytes_transfer_dummy :
36341.54Skamil			               &lookup_me8;
36351.54Skamil			io.piod_addr = &lookup_me8;
36361.54Skamil			io.piod_len = sizeof(lookup_me8);
36371.54Skamil			break;
36381.54Skamil		case 16:
36391.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36401.54Skamil			               (void *)bytes_transfer_dummy :
36411.54Skamil			               &lookup_me16;
36421.54Skamil			io.piod_addr = &lookup_me16;
36431.54Skamil			io.piod_len = sizeof(lookup_me16);
36441.54Skamil			break;
36451.54Skamil		case 32:
36461.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36471.54Skamil			               (void *)bytes_transfer_dummy :
36481.54Skamil			               &lookup_me32;
36491.54Skamil			io.piod_addr = &lookup_me32;
36501.54Skamil			io.piod_len = sizeof(lookup_me32);
36511.54Skamil			break;
36521.54Skamil		case 64:
36531.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36541.54Skamil			               (void *)bytes_transfer_dummy :
36551.54Skamil			               &lookup_me64;
36561.54Skamil			io.piod_addr = &lookup_me64;
36571.54Skamil			io.piod_len = sizeof(lookup_me64);
36581.54Skamil			break;
36591.54Skamil		default:
36601.54Skamil			break;
36611.54Skamil		}
36621.54Skamil		break;
36631.54Skamil	case BYTES_TRANSFER_AUXV:
36641.54Skamil		io.piod_op = operation;
36651.54Skamil		io.piod_offs = 0;
36661.54Skamil		io.piod_addr = ai;
36671.54Skamil		io.piod_len = size;
36681.54Skamil		break;
36691.54Skamil	default:
36701.54Skamil		break;
36711.1Skamil	}
36721.1Skamil
36731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36751.1Skamil	if (child == 0) {
36761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36781.1Skamil
36791.54Skamil		switch (type) {
36801.54Skamil		case BYTES_TRANSFER_DATA:
36811.54Skamil			switch (operation) {
36821.54Skamil			case PT_READ_D:
36831.54Skamil			case PT_READ_I:
36841.54Skamil				lookup_me = magic;
36851.54Skamil				break;
36861.54Skamil			default:
36871.54Skamil				break;
36881.54Skamil			}
36891.54Skamil			break;
36901.54Skamil		case BYTES_TRANSFER_DATAIO:
36911.54Skamil			switch (operation) {
36921.54Skamil			case PIOD_READ_D:
36931.54Skamil			case PIOD_READ_I:
36941.54Skamil				switch (size) {
36951.54Skamil				case 8:
36961.54Skamil					lookup_me8 = magic8;
36971.54Skamil					break;
36981.54Skamil				case 16:
36991.54Skamil					lookup_me16 = magic16;
37001.54Skamil					break;
37011.54Skamil				case 32:
37021.54Skamil					lookup_me32 = magic32;
37031.54Skamil					break;
37041.54Skamil				case 64:
37051.54Skamil					lookup_me64 = magic64;
37061.54Skamil					break;
37071.54Skamil				default:
37081.54Skamil					break;
37091.54Skamil				}
37101.54Skamil				break;
37111.54Skamil			default:
37121.54Skamil				break;
37131.54Skamil			}
37141.54Skamil		default:
37151.54Skamil			break;
37161.54Skamil		}
37171.54Skamil
37181.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37191.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37201.1Skamil
37211.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
37221.54Skamil		switch (type) {
37231.54Skamil		case BYTES_TRANSFER_DATA:
37241.54Skamil			switch (operation) {
37251.54Skamil			case PT_WRITE_D:
37261.54Skamil			case PT_WRITE_I:
37271.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
37281.54Skamil				break;
37291.54Skamil			default:
37301.54Skamil				break;
37311.54Skamil			}
37321.54Skamil			break;
37331.54Skamil		case BYTES_TRANSFER_DATAIO:
37341.54Skamil			switch (operation) {
37351.54Skamil			case PIOD_WRITE_D:
37361.54Skamil			case PIOD_WRITE_I:
37371.54Skamil				switch (size) {
37381.54Skamil				case 8:
37391.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
37401.54Skamil					break;
37411.54Skamil				case 16:
37421.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
37431.54Skamil					break;
37441.54Skamil				case 32:
37451.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
37461.54Skamil					break;
37471.54Skamil				case 64:
37481.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
37491.54Skamil					break;
37501.54Skamil				default:
37511.54Skamil					break;
37521.54Skamil				}
37531.54Skamil				break;
37541.54Skamil			default:
37551.54Skamil				break;
37561.54Skamil			}
37571.54Skamil			break;
37581.54Skamil		case BYTES_TRANSFER_TEXT:
37591.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
37601.54Skamil			                     sizeof(magic)) == 0);
37611.54Skamil			break;
37621.54Skamil		case BYTES_TRANSFER_TEXTIO:
37631.54Skamil			switch (size) {
37641.54Skamil			case 8:
37651.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
37661.54Skamil				                     bytes_transfer_dummy,
37671.54Skamil				                     sizeof(magic8)) == 0);
37681.54Skamil				break;
37691.54Skamil			case 16:
37701.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
37711.54Skamil				                     bytes_transfer_dummy,
37721.54Skamil				                     sizeof(magic16)) == 0);
37731.54Skamil				break;
37741.54Skamil			case 32:
37751.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
37761.54Skamil				                     bytes_transfer_dummy,
37771.54Skamil				                     sizeof(magic32)) == 0);
37781.54Skamil				break;
37791.54Skamil			case 64:
37801.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
37811.54Skamil				                     bytes_transfer_dummy,
37821.54Skamil				                     sizeof(magic64)) == 0);
37831.54Skamil				break;
37841.54Skamil			}
37851.54Skamil			break;
37861.54Skamil		default:
37871.54Skamil			break;
37881.54Skamil		}
37891.54Skamil
37901.13Schristos		DPRINTF("Before exiting of the child process\n");
37911.1Skamil		_exit(exitval);
37921.1Skamil	}
37931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37941.1Skamil
37951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37971.1Skamil
37981.1Skamil	validate_status_stopped(status, sigval);
37991.1Skamil
38001.54Skamil	/* Check PaX MPROTECT */
38011.54Skamil	if (!can_we_write_to_text(child)) {
38021.54Skamil		switch (type) {
38031.54Skamil		case BYTES_TRANSFER_TEXTIO:
38041.54Skamil			switch (operation) {
38051.54Skamil			case PIOD_WRITE_D:
38061.54Skamil			case PIOD_WRITE_I:
38071.54Skamil				skip = true;
38081.54Skamil				break;
38091.54Skamil			default:
38101.54Skamil				break;
38111.54Skamil			}
38121.54Skamil			break;
38131.54Skamil		case BYTES_TRANSFER_TEXT:
38141.54Skamil			switch (operation) {
38151.54Skamil			case PT_WRITE_D:
38161.54Skamil			case PT_WRITE_I:
38171.54Skamil				skip = true;
38181.54Skamil				break;
38191.54Skamil			default:
38201.54Skamil				break;
38211.54Skamil			}
38221.54Skamil			break;
38231.54Skamil		default:
38241.54Skamil			break;
38251.54Skamil		}
38261.54Skamil	}
38271.1Skamil
38281.54Skamil	/* Bailout cleanly killing the child process */
38291.54Skamil	if (skip) {
38301.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
38311.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38321.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
38331.54Skamil		                      child);
38341.1Skamil
38351.54Skamil		validate_status_signaled(status, SIGKILL, 0);
38361.1Skamil
38371.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
38381.54Skamil	}
38391.1Skamil
38401.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
38411.54Skamil	       "parent=%d\n", child, getpid());
38421.1Skamil
38431.54Skamil	switch (type) {
38441.54Skamil	case BYTES_TRANSFER_TEXTIO:
38451.54Skamil	case BYTES_TRANSFER_DATAIO:
38461.54Skamil	case BYTES_TRANSFER_AUXV:
38471.54Skamil		switch (operation) {
38481.54Skamil		case PIOD_WRITE_D:
38491.54Skamil		case PIOD_WRITE_I:
38501.54Skamil			switch (size) {
38511.54Skamil			case 8:
38521.54Skamil				lookup_me8 = magic8;
38531.54Skamil				break;
38541.54Skamil			case 16:
38551.54Skamil				lookup_me16 = magic16;
38561.54Skamil				break;
38571.54Skamil			case 32:
38581.54Skamil				lookup_me32 = magic32;
38591.54Skamil				break;
38601.54Skamil			case 64:
38611.54Skamil				lookup_me64 = magic64;
38621.54Skamil				break;
38631.54Skamil			default:
38641.54Skamil				break;
38651.54Skamil			}
38661.54Skamil			break;
38671.54Skamil		default:
38681.54Skamil			break;
38691.54Skamil		}
38701.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
38711.54Skamil		switch (operation) {
38721.54Skamil		case PIOD_READ_D:
38731.54Skamil		case PIOD_READ_I:
38741.54Skamil			switch (size) {
38751.54Skamil			case 8:
38761.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
38771.54Skamil				break;
38781.54Skamil			case 16:
38791.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
38801.54Skamil				break;
38811.54Skamil			case 32:
38821.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
38831.54Skamil				break;
38841.54Skamil			case 64:
38851.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
38861.54Skamil				break;
38871.54Skamil			default:
38881.54Skamil				break;
38891.54Skamil			}
38901.54Skamil			break;
38911.54Skamil		case PIOD_READ_AUXV:
38921.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
38931.54Skamil			        io.piod_len);
38941.54Skamil			ATF_REQUIRE(io.piod_len > 0);
38951.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
38961.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
38971.54Skamil				    (long long int)aip->a_type,
38981.54Skamil				    (long long int)aip->a_v);
38991.54Skamil			break;
39001.54Skamil		default:
39011.54Skamil			break;
39021.54Skamil		}
39031.54Skamil		break;
39041.54Skamil	case BYTES_TRANSFER_TEXT:
39051.54Skamil		switch (operation) {
39061.54Skamil		case PT_READ_D:
39071.54Skamil		case PT_READ_I:
39081.54Skamil			errno = 0;
39091.54Skamil			lookup_me = ptrace(operation, child,
39101.54Skamil			                   bytes_transfer_dummy, 0);
39111.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
39121.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
39131.54Skamil			break;
39141.54Skamil		case PT_WRITE_D:
39151.54Skamil		case PT_WRITE_I:
39161.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
39171.54Skamil			                       bytes_transfer_dummy, magic)
39181.54Skamil			                != -1);
39191.54Skamil			break;
39201.54Skamil		default:
39211.54Skamil			break;
39221.54Skamil		}
39231.54Skamil		break;
39241.54Skamil	case BYTES_TRANSFER_DATA:
39251.54Skamil		switch (operation) {
39261.54Skamil		case PT_READ_D:
39271.54Skamil		case PT_READ_I:
39281.54Skamil			errno = 0;
39291.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
39301.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
39311.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
39321.54Skamil			break;
39331.54Skamil		case PT_WRITE_D:
39341.54Skamil		case PT_WRITE_I:
39351.54Skamil			lookup_me = magic;
39361.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
39371.54Skamil			                       magic) != -1);
39381.54Skamil			break;
39391.54Skamil		default:
39401.54Skamil			break;
39411.54Skamil		}
39421.54Skamil		break;
39431.54Skamil	default:
39441.54Skamil		break;
39451.54Skamil	}
39461.1Skamil
39471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39481.1Skamil	    "without signal to be sent\n");
39491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39501.1Skamil
39511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39531.1Skamil
39541.1Skamil	validate_status_exited(status, exitval);
39551.1Skamil
39561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39581.1Skamil}
39591.1Skamil
39601.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
39611.61SkreATF_TC(test);								\
39621.61SkreATF_TC_HEAD(test, tc)							\
39631.61Skre{									\
39641.61Skre	atf_tc_set_md_var(tc, "descr",					\
39651.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
39661.61Skre	    " of type " #type);						\
39671.61Skre}									\
39681.61Skre									\
39691.61SkreATF_TC_BODY(test, tc)							\
39701.61Skre{									\
39711.61Skre									\
39721.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
39731.1Skamil}
39741.1Skamil
39751.54Skamil// DATA
39761.1Skamil
39771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
39781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
39791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
39801.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
39811.54Skamil
39821.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
39831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
39841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
39851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
39861.54Skamil
39871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
39881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
39891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
39901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
39911.54Skamil
39921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
39931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
39941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
39951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
39961.54Skamil
39971.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
39981.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
39991.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
40001.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
40011.54Skamil
40021.54Skamil// TEXT
40031.54Skamil
40041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
40051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
40061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
40071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
40081.54Skamil
40091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
40101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
40131.54Skamil
40141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
40151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
40161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
40171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
40181.54Skamil
40191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
40201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
40211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
40221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
40231.54Skamil
40241.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
40251.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
40261.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
40271.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
40281.1Skamil
40291.54Skamil// AUXV
40301.1Skamil
40311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
40321.1Skamil
40331.54Skamil/// ----------------------------------------------------------------------------
40341.1Skamil
40351.101Skamilstatic void
40361.101Skamilbytes_transfer_alignment(const char *operation)
40371.101Skamil{
40381.101Skamil	const int exitval = 5;
40391.101Skamil	const int sigval = SIGSTOP;
40401.101Skamil	pid_t child, wpid;
40411.101Skamil#if defined(TWAIT_HAVE_STATUS)
40421.101Skamil	int status;
40431.101Skamil#endif
40441.101Skamil	char *buffer;
40451.101Skamil	int vector;
40461.101Skamil	size_t len;
40471.101Skamil	size_t i;
40481.101Skamil	int op;
40491.101Skamil
40501.101Skamil	struct ptrace_io_desc io;
40511.101Skamil	struct ptrace_siginfo info;
40521.101Skamil
40531.101Skamil	memset(&io, 0, sizeof(io));
40541.101Skamil	memset(&info, 0, sizeof(info));
40551.101Skamil
40561.101Skamil	/* Testing misaligned byte transfer crossing page boundaries */
40571.101Skamil	len = sysconf(_SC_PAGESIZE) * 2;
40581.101Skamil	buffer = malloc(len);
40591.101Skamil	ATF_REQUIRE(buffer != NULL);
40601.101Skamil
40611.101Skamil	/* Initialize the buffer with random data */
40621.101Skamil	for (i = 0; i < len; i++)
40631.101Skamil		buffer[i] = i & 0xff;
40641.101Skamil
40651.101Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
40661.101Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
40671.101Skamil	if (child == 0) {
40681.101Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40691.101Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40701.101Skamil
40711.101Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40721.101Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40731.101Skamil
40741.101Skamil		DPRINTF("Before exiting of the child process\n");
40751.101Skamil		_exit(exitval);
40761.101Skamil	}
40771.101Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40781.101Skamil
40791.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40801.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40811.101Skamil
40821.101Skamil	validate_status_stopped(status, sigval);
40831.101Skamil
40841.101Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40851.101Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
40861.101Skamil		!= -1);
40871.101Skamil
40881.101Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
40891.101Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
40901.101Skamil		"si_errno=%#x\n",
40911.101Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
40921.101Skamil		info.psi_siginfo.si_errno);
40931.101Skamil
40941.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
40951.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
40961.101Skamil
40971.101Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
40981.101Skamil	    strcmp(operation, "PT_READ_D") == 0) {
40991.101Skamil		if (strcmp(operation, "PT_READ_I"))
41001.101Skamil			op = PT_READ_I;
41011.101Skamil		else
41021.101Skamil			op = PT_READ_D;
41031.101Skamil
41041.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41051.101Skamil			errno = 0;
41061.101Skamil			vector = ptrace(op, child, buffer + i, 0);
41071.101Skamil			ATF_REQUIRE_EQ(errno, 0);
41081.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
41091.101Skamil		}
41101.101Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
41111.101Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
41121.101Skamil		if (strcmp(operation, "PT_WRITE_I"))
41131.101Skamil			op = PT_WRITE_I;
41141.101Skamil		else
41151.101Skamil			op = PT_WRITE_D;
41161.101Skamil
41171.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41181.101Skamil			memcpy(&vector, buffer + i, sizeof(int));
41191.101Skamil			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
41201.101Skamil			    != -1);
41211.101Skamil		}
41221.101Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
41231.101Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
41241.101Skamil		if (strcmp(operation, "PIOD_READ_I"))
41251.101Skamil			op = PIOD_READ_I;
41261.101Skamil		else
41271.101Skamil			op = PIOD_READ_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			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
41391.101Skamil		}
41401.101Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
41411.101Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
41421.101Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
41431.101Skamil			op = PIOD_WRITE_I;
41441.101Skamil		else
41451.101Skamil			op = PIOD_WRITE_D;
41461.101Skamil
41471.101Skamil		io.piod_op = op;
41481.101Skamil		io.piod_addr = &vector;
41491.101Skamil		io.piod_len = sizeof(int);
41501.101Skamil
41511.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41521.101Skamil			io.piod_offs = buffer + i;
41531.101Skamil
41541.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
41551.101Skamil			                != -1);
41561.101Skamil		}
41571.101Skamil	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
41581.101Skamil		io.piod_op = PIOD_READ_AUXV;
41591.101Skamil		io.piod_addr = &vector;
41601.101Skamil		io.piod_len = sizeof(int);
41611.101Skamil
41621.101Skamil		errno = 0;
41631.101Skamil		i = 0;
41641.101Skamil		/* Read the whole AUXV vector, it has no clear length */
41651.120Skamil		while (io.piod_len > 0) {
41661.101Skamil			io.piod_offs = (void *)(intptr_t)i;
41671.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
41681.120Skamil			                != -1 || (io.piod_len == 0 && i > 0));
41691.101Skamil			++i;
41701.101Skamil		}
41711.101Skamil	}
41721.101Skamil
41731.101Skamil	DPRINTF("Before resuming the child process where it left off "
41741.101Skamil	    "and without signal to be sent\n");
41751.101Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41761.101Skamil
41771.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41781.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
41791.101Skamil	    child);
41801.101Skamil
41811.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41821.101Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41831.101Skamil}
41841.101Skamil
41851.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
41861.101SkamilATF_TC(test);								\
41871.101SkamilATF_TC_HEAD(test, tc)							\
41881.101Skamil{									\
41891.101Skamil	atf_tc_set_md_var(tc, "descr",					\
41901.101Skamil	    "Verify bytes transfer for potentially misaligned "		\
41911.101Skamil	    "operation " operation);					\
41921.101Skamil}									\
41931.101Skamil									\
41941.101SkamilATF_TC_BODY(test, tc)							\
41951.101Skamil{									\
41961.101Skamil									\
41971.101Skamil	bytes_transfer_alignment(operation);				\
41981.101Skamil}
41991.101Skamil
42001.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
42011.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
42021.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
42031.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
42041.101Skamil
42051.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
42061.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
42071.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
42081.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
42091.101Skamil
42101.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
42111.101Skamil
42121.101Skamil/// ----------------------------------------------------------------------------
42131.101Skamil
42141.115Skamilstatic void
42151.115Skamilbytes_transfer_eof(const char *operation)
42161.115Skamil{
42171.115Skamil	const int exitval = 5;
42181.115Skamil	const int sigval = SIGSTOP;
42191.115Skamil	pid_t child, wpid;
42201.115Skamil#if defined(TWAIT_HAVE_STATUS)
42211.115Skamil	int status;
42221.115Skamil#endif
42231.115Skamil	FILE *fp;
42241.115Skamil	char *p;
42251.115Skamil	int vector;
42261.115Skamil	int op;
42271.115Skamil
42281.115Skamil	struct ptrace_io_desc io;
42291.115Skamil	struct ptrace_siginfo info;
42301.115Skamil
42311.115Skamil	memset(&io, 0, sizeof(io));
42321.115Skamil	memset(&info, 0, sizeof(info));
42331.115Skamil
42341.115Skamil	vector = 0;
42351.115Skamil
42361.115Skamil	fp = tmpfile();
42371.115Skamil	ATF_REQUIRE(fp != NULL);
42381.115Skamil
42391.115Skamil	p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
42401.115Skamil	ATF_REQUIRE(p != MAP_FAILED);
42411.115Skamil
42421.115Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
42431.115Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
42441.115Skamil	if (child == 0) {
42451.115Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42461.115Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42471.115Skamil
42481.115Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42491.115Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42501.115Skamil
42511.115Skamil		DPRINTF("Before exiting of the child process\n");
42521.115Skamil		_exit(exitval);
42531.115Skamil	}
42541.115Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42551.115Skamil
42561.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42571.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42581.115Skamil
42591.115Skamil	validate_status_stopped(status, sigval);
42601.115Skamil
42611.115Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
42621.115Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
42631.115Skamil		!= -1);
42641.115Skamil
42651.115Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
42661.115Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
42671.115Skamil		"si_errno=%#x\n",
42681.115Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
42691.115Skamil		info.psi_siginfo.si_errno);
42701.115Skamil
42711.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
42721.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
42731.115Skamil
42741.115Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
42751.115Skamil	    strcmp(operation, "PT_READ_D") == 0) {
42761.115Skamil		if (strcmp(operation, "PT_READ_I"))
42771.115Skamil			op = PT_READ_I;
42781.115Skamil		else
42791.115Skamil			op = PT_READ_D;
42801.115Skamil
42811.115Skamil		errno = 0;
42821.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1);
42831.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42841.115Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
42851.115Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
42861.115Skamil		if (strcmp(operation, "PT_WRITE_I"))
42871.115Skamil			op = PT_WRITE_I;
42881.115Skamil		else
42891.115Skamil			op = PT_WRITE_D;
42901.115Skamil
42911.115Skamil		errno = 0;
42921.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1);
42931.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42941.115Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
42951.115Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
42961.115Skamil		if (strcmp(operation, "PIOD_READ_I"))
42971.115Skamil			op = PIOD_READ_I;
42981.115Skamil		else
42991.115Skamil			op = PIOD_READ_D;
43001.115Skamil
43011.115Skamil		io.piod_op = op;
43021.115Skamil		io.piod_addr = &vector;
43031.115Skamil		io.piod_len = sizeof(int);
43041.115Skamil		io.piod_offs = p;
43051.115Skamil
43061.115Skamil		errno = 0;
43071.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
43081.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
43091.115Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
43101.115Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
43111.115Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
43121.115Skamil			op = PIOD_WRITE_I;
43131.115Skamil		else
43141.115Skamil			op = PIOD_WRITE_D;
43151.115Skamil
43161.115Skamil		io.piod_op = op;
43171.115Skamil		io.piod_addr = &vector;
43181.115Skamil		io.piod_len = sizeof(int);
43191.115Skamil		io.piod_offs = p;
43201.115Skamil
43211.115Skamil		errno = 0;
43221.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
43231.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
43241.115Skamil	}
43251.115Skamil
43261.115Skamil	DPRINTF("Before resuming the child process where it left off "
43271.115Skamil	    "and without signal to be sent\n");
43281.115Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43291.115Skamil
43301.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43311.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
43321.115Skamil	    child);
43331.115Skamil
43341.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43351.115Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43361.115Skamil}
43371.115Skamil
43381.115Skamil#define BYTES_TRANSFER_EOF(test, operation)				\
43391.115SkamilATF_TC(test);								\
43401.115SkamilATF_TC_HEAD(test, tc)							\
43411.115Skamil{									\
43421.115Skamil	atf_tc_set_md_var(tc, "descr",					\
43431.115Skamil	    "Verify bytes EOF byte transfer for the " operation		\
43441.115Skamil	    " operation");						\
43451.115Skamil}									\
43461.115Skamil									\
43471.115SkamilATF_TC_BODY(test, tc)							\
43481.115Skamil{									\
43491.115Skamil									\
43501.115Skamil	bytes_transfer_eof(operation);					\
43511.115Skamil}
43521.115Skamil
43531.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I")
43541.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D")
43551.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I")
43561.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D")
43571.115Skamil
43581.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I")
43591.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D")
43601.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I")
43611.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D")
43621.115Skamil
43631.115Skamil/// ----------------------------------------------------------------------------
43641.115Skamil
43651.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
43661.72Skamilstatic void
43671.72Skamilaccess_regs(const char *regset, const char *aux)
43681.1Skamil{
43691.1Skamil	const int exitval = 5;
43701.1Skamil	const int sigval = SIGSTOP;
43711.1Skamil	pid_t child, wpid;
43721.1Skamil#if defined(TWAIT_HAVE_STATUS)
43731.1Skamil	int status;
43741.1Skamil#endif
43751.72Skamil#if defined(HAVE_GPREGS)
43761.72Skamil	struct reg gpr;
43771.76Sscole	register_t rgstr;
43781.1Skamil#endif
43791.72Skamil#if defined(HAVE_FPREGS)
43801.72Skamil	struct fpreg fpr;
43811.1Skamil#endif
43821.76Sscole
43831.72Skamil#if !defined(HAVE_GPREGS)
43841.72Skamil	if (strcmp(regset, "regs") == 0)
43851.72Skamil		atf_tc_fail("Impossible test scenario!");
43861.1Skamil#endif
43871.1Skamil
43881.72Skamil#if !defined(HAVE_FPREGS)
43891.72Skamil	if (strcmp(regset, "fpregs") == 0)
43901.72Skamil		atf_tc_fail("Impossible test scenario!");
43911.1Skamil#endif
43921.1Skamil
43931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43951.1Skamil	if (child == 0) {
43961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43981.1Skamil
43991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44011.1Skamil
44021.13Schristos		DPRINTF("Before exiting of the child process\n");
44031.1Skamil		_exit(exitval);
44041.1Skamil	}
44051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44061.1Skamil
44071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44091.1Skamil
44101.1Skamil	validate_status_stopped(status, sigval);
44111.1Skamil
44121.1Skamil#if defined(HAVE_GPREGS)
44131.72Skamil	if (strcmp(regset, "regs") == 0) {
44141.72Skamil		DPRINTF("Call GETREGS for the child process\n");
44151.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
44161.72Skamil
44171.72Skamil		if (strcmp(aux, "none") == 0) {
44181.72Skamil			DPRINTF("Retrieved registers\n");
44191.72Skamil		} else if (strcmp(aux, "pc") == 0) {
44201.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
44211.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44221.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
44231.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
44241.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
44251.72Skamil		} else if (strcmp(aux, "sp") == 0) {
44261.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
44271.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44281.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
44291.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
44301.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44311.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
44321.72Skamil			DPRINTF("Call SETREGS for the child process\n");
44331.72Skamil			SYSCALL_REQUIRE(
44341.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
44351.72Skamil		}
44361.72Skamil	}
44371.1Skamil#endif
44381.1Skamil
44391.72Skamil#if defined(HAVE_FPREGS)
44401.72Skamil	if (strcmp(regset, "fpregs") == 0) {
44411.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
44421.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
44431.72Skamil
44441.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
44451.72Skamil			DPRINTF("Retrieved FP registers\n");
44461.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
44471.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
44481.72Skamil			SYSCALL_REQUIRE(
44491.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
44501.72Skamil		}
44511.1Skamil	}
44521.1Skamil#endif
44531.1Skamil
44541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44551.1Skamil	    "without signal to be sent\n");
44561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44571.1Skamil
44581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44601.1Skamil
44611.1Skamil	validate_status_exited(status, exitval);
44621.1Skamil
44631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44651.1Skamil}
44661.1Skamil
44671.72Skamil#define ACCESS_REGS(test, regset, aux)					\
44681.72SkamilATF_TC(test);								\
44691.72SkamilATF_TC_HEAD(test, tc)							\
44701.72Skamil{									\
44711.72Skamil        atf_tc_set_md_var(tc, "descr",					\
44721.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
44731.72Skamil}									\
44741.72Skamil									\
44751.72SkamilATF_TC_BODY(test, tc)							\
44761.72Skamil{									\
44771.72Skamil									\
44781.72Skamil        access_regs(regset, aux);					\
44791.1Skamil}
44801.1Skamil#endif
44811.1Skamil
44821.72Skamil#if defined(HAVE_GPREGS)
44831.72SkamilACCESS_REGS(access_regs1, "regs", "none")
44841.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
44851.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
44861.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
44871.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
44881.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
44891.1Skamil#endif
44901.1Skamil#if defined(HAVE_FPREGS)
44911.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
44921.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
44931.1Skamil#endif
44941.1Skamil
44951.72Skamil/// ----------------------------------------------------------------------------
44961.1Skamil
44971.1Skamil#if defined(PT_STEP)
44981.1Skamilstatic void
44991.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
45001.1Skamil{
45011.1Skamil	const int exitval = 5;
45021.1Skamil	const int sigval = SIGSTOP;
45031.1Skamil	pid_t child, wpid;
45041.1Skamil#if defined(TWAIT_HAVE_STATUS)
45051.1Skamil	int status;
45061.1Skamil#endif
45071.1Skamil	int happy;
45081.95Skamil	struct sigaction sa;
45091.81Skamil	struct ptrace_siginfo info;
45101.95Skamil	sigset_t intmask;
45111.95Skamil	struct kinfo_proc2 kp;
45121.95Skamil	size_t len = sizeof(kp);
45131.95Skamil
45141.95Skamil	int name[6];
45151.95Skamil	const size_t namelen = __arraycount(name);
45161.95Skamil	ki_sigset_t kp_sigmask;
45171.95Skamil	ki_sigset_t kp_sigignore;
45181.1Skamil
45191.1Skamil#if defined(__arm__)
45201.1Skamil	/* PT_STEP not supported on arm 32-bit */
45211.1Skamil	atf_tc_expect_fail("PR kern/52119");
45221.1Skamil#endif
45231.1Skamil
45241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45261.1Skamil	if (child == 0) {
45271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45291.1Skamil
45301.95Skamil		if (masked) {
45311.95Skamil			sigemptyset(&intmask);
45321.95Skamil			sigaddset(&intmask, SIGTRAP);
45331.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
45341.95Skamil		}
45351.95Skamil
45361.95Skamil		if (ignored) {
45371.95Skamil			memset(&sa, 0, sizeof(sa));
45381.95Skamil			sa.sa_handler = SIG_IGN;
45391.95Skamil			sigemptyset(&sa.sa_mask);
45401.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
45411.95Skamil		}
45421.95Skamil
45431.1Skamil		happy = check_happy(999);
45441.1Skamil
45451.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45461.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45471.1Skamil
45481.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
45491.1Skamil
45501.13Schristos		DPRINTF("Before exiting of the child process\n");
45511.1Skamil		_exit(exitval);
45521.1Skamil	}
45531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45541.1Skamil
45551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45571.1Skamil
45581.1Skamil	validate_status_stopped(status, sigval);
45591.1Skamil
45601.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45611.81Skamil	SYSCALL_REQUIRE(
45621.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45631.81Skamil
45641.81Skamil	DPRINTF("Before checking siginfo_t\n");
45651.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
45661.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
45671.81Skamil
45681.95Skamil	name[0] = CTL_KERN,
45691.95Skamil	name[1] = KERN_PROC2,
45701.95Skamil	name[2] = KERN_PROC_PID;
45711.95Skamil	name[3] = child;
45721.95Skamil	name[4] = sizeof(kp);
45731.95Skamil	name[5] = 1;
45741.95Skamil
45751.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
45761.95Skamil
45771.95Skamil	if (masked)
45781.95Skamil		kp_sigmask = kp.p_sigmask;
45791.95Skamil
45801.95Skamil	if (ignored)
45811.95Skamil		kp_sigignore = kp.p_sigignore;
45821.95Skamil
45831.1Skamil	while (N --> 0) {
45841.2Skamil		if (setstep) {
45851.13Schristos			DPRINTF("Before resuming the child process where it "
45861.2Skamil			    "left off and without signal to be sent (use "
45871.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
45881.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
45891.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
45901.2Skamil			    != -1);
45911.2Skamil		} else {
45921.13Schristos			DPRINTF("Before resuming the child process where it "
45931.2Skamil			    "left off and without signal to be sent (use "
45941.2Skamil			    "PT_STEP)\n");
45951.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
45961.2Skamil			    != -1);
45971.2Skamil		}
45981.1Skamil
45991.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46001.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
46011.1Skamil		    child);
46021.1Skamil
46031.1Skamil		validate_status_stopped(status, SIGTRAP);
46041.2Skamil
46051.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
46061.81Skamil		SYSCALL_REQUIRE(
46071.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
46081.81Skamil
46091.81Skamil		DPRINTF("Before checking siginfo_t\n");
46101.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
46111.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
46121.81Skamil
46131.2Skamil		if (setstep) {
46141.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
46151.2Skamil		}
46161.95Skamil
46171.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
46181.95Skamil
46191.95Skamil		if (masked) {
46201.95Skamil			DPRINTF("kp_sigmask="
46211.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46221.95Skamil			    PRIx32 "\n",
46231.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
46241.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
46251.95Skamil
46261.95Skamil			DPRINTF("kp.p_sigmask="
46271.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46281.95Skamil			    PRIx32 "\n",
46291.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
46301.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
46311.95Skamil
46321.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
46331.95Skamil			    sizeof(kp_sigmask)));
46341.95Skamil		}
46351.95Skamil
46361.95Skamil		if (ignored) {
46371.95Skamil			DPRINTF("kp_sigignore="
46381.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46391.95Skamil			    PRIx32 "\n",
46401.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
46411.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
46421.95Skamil
46431.95Skamil			DPRINTF("kp.p_sigignore="
46441.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46451.95Skamil			    PRIx32 "\n",
46461.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
46471.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
46481.95Skamil
46491.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
46501.95Skamil			    sizeof(kp_sigignore)));
46511.95Skamil		}
46521.1Skamil	}
46531.1Skamil
46541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46551.1Skamil	    "without signal to be sent\n");
46561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46571.1Skamil
46581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46601.1Skamil
46611.1Skamil	validate_status_exited(status, exitval);
46621.1Skamil
46631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46651.1Skamil}
46661.1Skamil
46671.73Skamil#define PTRACE_STEP(test, N, setstep)					\
46681.73SkamilATF_TC(test);								\
46691.73SkamilATF_TC_HEAD(test, tc)							\
46701.73Skamil{									\
46711.73Skamil        atf_tc_set_md_var(tc, "descr",					\
46721.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
46731.73Skamil}									\
46741.73Skamil									\
46751.73SkamilATF_TC_BODY(test, tc)							\
46761.73Skamil{									\
46771.73Skamil									\
46781.95Skamil        ptrace_step(N, setstep, false, false);				\
46791.1Skamil}
46801.1Skamil
46811.73SkamilPTRACE_STEP(step1, 1, 0)
46821.73SkamilPTRACE_STEP(step2, 2, 0)
46831.73SkamilPTRACE_STEP(step3, 3, 0)
46841.73SkamilPTRACE_STEP(step4, 4, 0)
46851.73SkamilPTRACE_STEP(setstep1, 1, 1)
46861.73SkamilPTRACE_STEP(setstep2, 2, 1)
46871.73SkamilPTRACE_STEP(setstep3, 3, 1)
46881.73SkamilPTRACE_STEP(setstep4, 4, 1)
46891.95Skamil
46901.95SkamilATF_TC(step_signalmasked);
46911.95SkamilATF_TC_HEAD(step_signalmasked, tc)
46921.95Skamil{
46931.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
46941.95Skamil}
46951.95Skamil
46961.95SkamilATF_TC_BODY(step_signalmasked, tc)
46971.95Skamil{
46981.95Skamil
46991.95Skamil	ptrace_step(1, 0, true, false);
47001.95Skamil}
47011.95Skamil
47021.95SkamilATF_TC(step_signalignored);
47031.95SkamilATF_TC_HEAD(step_signalignored, tc)
47041.95Skamil{
47051.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
47061.95Skamil}
47071.95Skamil
47081.95SkamilATF_TC_BODY(step_signalignored, tc)
47091.95Skamil{
47101.95Skamil
47111.95Skamil	ptrace_step(1, 0, false, true);
47121.95Skamil}
47131.1Skamil#endif
47141.1Skamil
47151.73Skamil/// ----------------------------------------------------------------------------
47161.1Skamil
47171.75Skamilstatic void
47181.75Skamilptrace_kill(const char *type)
47191.1Skamil{
47201.75Skamil	const int sigval = SIGSTOP;
47211.1Skamil	pid_t child, wpid;
47221.1Skamil#if defined(TWAIT_HAVE_STATUS)
47231.1Skamil	int status;
47241.1Skamil#endif
47251.1Skamil
47261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47281.1Skamil	if (child == 0) {
47291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47311.1Skamil
47321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47341.1Skamil
47351.1Skamil		/* NOTREACHED */
47361.1Skamil		FORKEE_ASSERTX(0 &&
47371.1Skamil		    "Child should be terminated by a signal from its parent");
47381.1Skamil	}
47391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47401.1Skamil
47411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47431.1Skamil
47441.1Skamil	validate_status_stopped(status, sigval);
47451.1Skamil
47461.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
47471.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
47481.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
47491.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
47501.75Skamil		kill(child, SIGKILL);
47511.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
47521.75Skamil		setpgid(child, 0);
47531.75Skamil		killpg(getpgid(child), SIGKILL);
47541.75Skamil	}
47551.1Skamil
47561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47581.1Skamil
47591.75Skamil	validate_status_signaled(status, SIGKILL, 0);
47601.1Skamil
47611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47631.1Skamil}
47641.1Skamil
47651.75Skamil#define PTRACE_KILL(test, type)						\
47661.75SkamilATF_TC(test);								\
47671.75SkamilATF_TC_HEAD(test, tc)							\
47681.75Skamil{									\
47691.75Skamil        atf_tc_set_md_var(tc, "descr",					\
47701.75Skamil            "Verify killing the child with " type);			\
47711.75Skamil}									\
47721.75Skamil									\
47731.75SkamilATF_TC_BODY(test, tc)							\
47741.75Skamil{									\
47751.75Skamil									\
47761.75Skamil        ptrace_kill(type);						\
47771.1Skamil}
47781.1Skamil
47791.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
47801.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
47811.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
47821.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
47831.1Skamil
47841.75Skamil/// ----------------------------------------------------------------------------
47851.1Skamil
47861.77Skamilstatic void
47871.77Skamiltraceme_lwpinfo(const int threads)
47881.1Skamil{
47891.1Skamil	const int sigval = SIGSTOP;
47901.77Skamil	const int sigval2 = SIGINT;
47911.1Skamil	pid_t child, wpid;
47921.1Skamil#if defined(TWAIT_HAVE_STATUS)
47931.1Skamil	int status;
47941.1Skamil#endif
47951.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
47961.77Skamil	struct ptrace_siginfo info;
47971.77Skamil
47981.77Skamil	/* Maximum number of supported threads in this test */
47991.77Skamil	pthread_t t[3];
48001.77Skamil	int n, rv;
48011.77Skamil
48021.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
48031.1Skamil
48041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48061.1Skamil	if (child == 0) {
48071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48091.1Skamil
48101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48121.1Skamil
48131.77Skamil		for (n = 0; n < threads; n++) {
48141.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
48151.77Skamil			FORKEE_ASSERT(rv == 0);
48161.77Skamil		}
48171.77Skamil
48181.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
48191.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
48201.77Skamil
48211.77Skamil		/* NOTREACHED */
48221.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
48231.1Skamil	}
48241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48251.1Skamil
48261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48281.1Skamil
48291.1Skamil	validate_status_stopped(status, sigval);
48301.1Skamil
48311.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
48321.77Skamil	SYSCALL_REQUIRE(
48331.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48341.77Skamil
48351.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48361.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48371.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48381.77Skamil	    info.psi_siginfo.si_errno);
48391.77Skamil
48401.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
48411.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
48421.77Skamil
48431.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48441.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48451.1Skamil
48461.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
48471.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
48481.1Skamil
48491.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
48501.77Skamil	    lwp.pl_lwpid);
48511.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
48521.1Skamil
48531.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48541.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48551.1Skamil
48561.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
48571.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
48581.1Skamil
48591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48601.1Skamil	    "without signal to be sent\n");
48611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48621.1Skamil
48631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48651.1Skamil
48661.77Skamil	validate_status_stopped(status, sigval2);
48671.77Skamil
48681.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
48691.77Skamil	SYSCALL_REQUIRE(
48701.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48711.77Skamil
48721.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48731.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48741.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48751.77Skamil	    info.psi_siginfo.si_errno);
48761.77Skamil
48771.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
48781.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
48791.77Skamil
48801.77Skamil	memset(&lwp, 0, sizeof(lwp));
48811.77Skamil
48821.77Skamil	for (n = 0; n <= threads; n++) {
48831.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48841.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48851.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
48861.77Skamil
48871.77Skamil		DPRINTF("Assert that the thread exists\n");
48881.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
48891.77Skamil
48901.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
48911.77Skamil		    lwp.pl_lwpid);
48921.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
48931.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
48941.77Skamil	}
48951.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48961.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48971.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
48981.77Skamil
48991.77Skamil	DPRINTF("Assert that there are no more threads\n");
49001.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
49011.77Skamil
49021.77Skamil	DPRINTF("Before resuming the child process where it left off and "
49031.77Skamil	    "without signal to be sent\n");
49041.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
49051.77Skamil
49061.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49071.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49081.77Skamil
49091.77Skamil	validate_status_signaled(status, SIGKILL, 0);
49101.1Skamil
49111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49131.1Skamil}
49141.1Skamil
49151.77Skamil#define TRACEME_LWPINFO(test, threads)					\
49161.77SkamilATF_TC(test);								\
49171.77SkamilATF_TC_HEAD(test, tc)							\
49181.77Skamil{									\
49191.77Skamil	atf_tc_set_md_var(tc, "descr",					\
49201.77Skamil	    "Verify LWPINFO with the child with " #threads		\
49211.77Skamil	    " spawned extra threads");					\
49221.77Skamil}									\
49231.77Skamil									\
49241.77SkamilATF_TC_BODY(test, tc)							\
49251.77Skamil{									\
49261.77Skamil									\
49271.77Skamil	traceme_lwpinfo(threads);					\
49281.1Skamil}
49291.1Skamil
49301.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
49311.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
49321.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
49331.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
49341.77Skamil
49351.77Skamil/// ----------------------------------------------------------------------------
49361.77Skamil
49371.77Skamil#if defined(TWAIT_HAVE_PID)
49381.77Skamilstatic void
49391.77Skamilattach_lwpinfo(const int threads)
49401.1Skamil{
49411.77Skamil	const int sigval = SIGINT;
49421.1Skamil	struct msg_fds parent_tracee, parent_tracer;
49431.1Skamil	const int exitval_tracer = 10;
49441.1Skamil	pid_t tracee, tracer, wpid;
49451.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
49461.1Skamil#if defined(TWAIT_HAVE_STATUS)
49471.1Skamil	int status;
49481.1Skamil#endif
49491.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
49501.77Skamil	struct ptrace_siginfo info;
49511.77Skamil
49521.77Skamil	/* Maximum number of supported threads in this test */
49531.77Skamil	pthread_t t[3];
49541.77Skamil	int n, rv;
49551.1Skamil
49561.13Schristos	DPRINTF("Spawn tracee\n");
49571.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
49581.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
49591.1Skamil	tracee = atf_utils_fork();
49601.1Skamil	if (tracee == 0) {
49611.1Skamil		/* Wait for message from the parent */
49621.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
49631.1Skamil
49641.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
49651.77Skamil
49661.77Skamil		for (n = 0; n < threads; n++) {
49671.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
49681.77Skamil			FORKEE_ASSERT(rv == 0);
49691.77Skamil		}
49701.77Skamil
49711.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
49721.77Skamil
49731.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49741.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49751.77Skamil
49761.77Skamil		/* NOTREACHED */
49771.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
49781.1Skamil	}
49791.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
49801.1Skamil
49811.13Schristos	DPRINTF("Spawn debugger\n");
49821.1Skamil	tracer = atf_utils_fork();
49831.1Skamil	if (tracer == 0) {
49841.1Skamil		/* No IPC to communicate with the child */
49851.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
49861.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
49871.1Skamil
49881.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
49891.1Skamil		FORKEE_REQUIRE_SUCCESS(
49901.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
49911.1Skamil
49921.1Skamil		forkee_status_stopped(status, SIGSTOP);
49931.1Skamil
49941.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
49951.77Skamil		    "tracee");
49961.77Skamil		FORKEE_ASSERT(
49971.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
49981.77Skamil
49991.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50001.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50011.77Skamil		    "si_errno=%#x\n",
50021.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50031.77Skamil		    info.psi_siginfo.si_errno);
50041.77Skamil
50051.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
50061.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
50071.77Skamil
50081.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
50091.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
50101.1Skamil		    != -1);
50111.1Skamil
50121.13Schristos		DPRINTF("Assert that there exists a thread\n");
50131.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
50141.1Skamil
50151.13Schristos		DPRINTF("Assert that lwp thread %d received event "
50161.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
50171.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
50181.1Skamil
50191.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50201.77Skamil		    "tracee\n");
50211.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
50221.1Skamil		    != -1);
50231.1Skamil
50241.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
50251.77Skamil		    "tracee\n");
50261.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
50271.1Skamil
50281.1Skamil		/* Resume tracee with PT_CONTINUE */
50291.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
50301.1Skamil
50311.1Skamil		/* Inform parent that tracer has attached to tracee */
50321.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
50331.77Skamil
50341.1Skamil		/* Wait for parent */
50351.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
50361.1Skamil
50371.77Skamil		/* Wait for tracee and assert that it raised a signal */
50381.77Skamil		FORKEE_REQUIRE_SUCCESS(
50391.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
50401.77Skamil
50411.77Skamil		forkee_status_stopped(status, SIGINT);
50421.77Skamil
50431.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
50441.77Skamil		    "child");
50451.77Skamil		FORKEE_ASSERT(
50461.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
50471.77Skamil
50481.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50491.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50501.77Skamil		    "si_errno=%#x\n",
50511.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50521.77Skamil		    info.psi_siginfo.si_errno);
50531.77Skamil
50541.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
50551.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
50561.77Skamil
50571.77Skamil		memset(&lwp, 0, sizeof(lwp));
50581.77Skamil
50591.77Skamil		for (n = 0; n <= threads; n++) {
50601.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50611.77Skamil			    "child\n");
50621.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
50631.77Skamil			    sizeof(lwp)) != -1);
50641.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
50651.77Skamil
50661.77Skamil			DPRINTF("Assert that the thread exists\n");
50671.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
50681.77Skamil
50691.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
50701.77Skamil			    "event\n", lwp.pl_lwpid);
50711.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
50721.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
50731.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
50741.77Skamil		}
50751.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50761.77Skamil		    "tracee\n");
50771.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
50781.77Skamil		    != -1);
50791.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
50801.77Skamil
50811.77Skamil		DPRINTF("Assert that there are no more threads\n");
50821.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
50831.77Skamil
50841.77Skamil		DPRINTF("Before resuming the child process where it left off "
50851.77Skamil		    "and without signal to be sent\n");
50861.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
50871.77Skamil		    != -1);
50881.77Skamil
50891.1Skamil		/* Wait for tracee and assert that it exited */
50901.1Skamil		FORKEE_REQUIRE_SUCCESS(
50911.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
50921.1Skamil
50931.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
50941.1Skamil
50951.13Schristos		DPRINTF("Before exiting of the tracer process\n");
50961.1Skamil		_exit(exitval_tracer);
50971.1Skamil	}
50981.1Skamil
50991.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
51001.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
51011.1Skamil
51021.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
51031.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
51041.77Skamil
51051.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
51061.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
51071.1Skamil
51081.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
51091.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
51101.1Skamil
51111.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
51121.1Skamil	    TWAIT_FNAME);
51131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
51141.1Skamil	    tracer);
51151.1Skamil
51161.1Skamil	validate_status_exited(status, exitval_tracer);
51171.1Skamil
51181.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
51191.1Skamil	    TWAIT_FNAME);
51201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
51211.1Skamil	    tracee);
51221.1Skamil
51231.77Skamil	validate_status_signaled(status, SIGKILL, 0);
51241.1Skamil
51251.1Skamil	msg_close(&parent_tracer);
51261.1Skamil	msg_close(&parent_tracee);
51271.1Skamil}
51281.77Skamil
51291.77Skamil#define ATTACH_LWPINFO(test, threads)					\
51301.77SkamilATF_TC(test);								\
51311.77SkamilATF_TC_HEAD(test, tc)							\
51321.77Skamil{									\
51331.77Skamil	atf_tc_set_md_var(tc, "descr",					\
51341.77Skamil	    "Verify LWPINFO with the child with " #threads		\
51351.77Skamil	    " spawned extra threads (tracer is not the original "	\
51361.77Skamil	    "parent)");							\
51371.77Skamil}									\
51381.77Skamil									\
51391.77SkamilATF_TC_BODY(test, tc)							\
51401.77Skamil{									\
51411.77Skamil									\
51421.77Skamil	attach_lwpinfo(threads);					\
51431.77Skamil}
51441.77Skamil
51451.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
51461.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
51471.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
51481.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
51491.1Skamil#endif
51501.1Skamil
51511.77Skamil/// ----------------------------------------------------------------------------
51521.77Skamil
51531.1Skamilstatic void
51541.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
51551.1Skamil{
51561.1Skamil	const int exitval = 5;
51571.1Skamil	const int sigval = SIGINT;
51581.1Skamil	const int sigfaked = SIGTRAP;
51591.1Skamil	const int sicodefaked = TRAP_BRKPT;
51601.1Skamil	pid_t child, wpid;
51611.1Skamil	struct sigaction sa;
51621.1Skamil#if defined(TWAIT_HAVE_STATUS)
51631.1Skamil	int status;
51641.1Skamil#endif
51651.1Skamil	struct ptrace_siginfo info;
51661.1Skamil	memset(&info, 0, sizeof(info));
51671.1Skamil
51681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51701.1Skamil	if (child == 0) {
51711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51731.1Skamil
51741.79Skamil		sa.sa_sigaction = sah;
51751.1Skamil		sa.sa_flags = SA_SIGINFO;
51761.1Skamil		sigemptyset(&sa.sa_mask);
51771.1Skamil
51781.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
51791.79Skamil		    != -1);
51801.1Skamil
51811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51831.1Skamil
51841.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
51851.1Skamil
51861.13Schristos		DPRINTF("Before exiting of the child process\n");
51871.1Skamil		_exit(exitval);
51881.1Skamil	}
51891.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51901.1Skamil
51911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51931.1Skamil
51941.1Skamil	validate_status_stopped(status, sigval);
51951.1Skamil
51961.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51971.61Skre	SYSCALL_REQUIRE(
51981.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51991.1Skamil
52001.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
52011.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
52021.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
52031.1Skamil	    info.psi_siginfo.si_errno);
52041.1Skamil
52051.79Skamil	if (faked) {
52061.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
52071.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
52081.79Skamil		info.psi_siginfo.si_signo = sigfaked;
52091.79Skamil		info.psi_siginfo.si_code = sicodefaked;
52101.79Skamil	}
52111.1Skamil
52121.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
52131.61Skre	SYSCALL_REQUIRE(
52141.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
52151.1Skamil
52161.79Skamil	if (faked) {
52171.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
52181.79Skamil		    "child\n");
52191.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
52201.79Skamil		    sizeof(info)) != -1);
52211.1Skamil
52221.79Skamil		DPRINTF("Before checking siginfo_t\n");
52231.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
52241.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
52251.79Skamil	}
52261.1Skamil
52271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52281.1Skamil	    "without signal to be sent\n");
52291.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
52301.79Skamil	    faked ? sigfaked : sigval) != -1);
52311.1Skamil
52321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52341.1Skamil
52351.1Skamil	validate_status_exited(status, exitval);
52361.1Skamil
52371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52391.1Skamil}
52401.1Skamil
52411.79Skamil#define PTRACE_SIGINFO(test, faked)					\
52421.79SkamilATF_TC(test);								\
52431.79SkamilATF_TC_HEAD(test, tc)							\
52441.79Skamil{									\
52451.79Skamil	atf_tc_set_md_var(tc, "descr",					\
52461.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
52471.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
52481.79Skamil}									\
52491.79Skamil									\
52501.79Skamilstatic int test##_caught = 0;						\
52511.79Skamil									\
52521.79Skamilstatic void								\
52531.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
52541.79Skamil{									\
52551.79Skamil	if (faked) {							\
52561.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
52571.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
52581.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
52591.79Skamil	} else {							\
52601.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
52611.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
52621.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
52631.79Skamil	}								\
52641.79Skamil									\
52651.79Skamil	++ test##_caught;						\
52661.79Skamil}									\
52671.79Skamil									\
52681.79SkamilATF_TC_BODY(test, tc)							\
52691.79Skamil{									\
52701.79Skamil									\
52711.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
52721.79Skamil}
52731.79Skamil
52741.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
52751.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
52761.79Skamil
52771.79Skamil/// ----------------------------------------------------------------------------
52781.79Skamil
52791.97Skamilstatic void
52801.97Skamiltraceme_exec(bool masked, bool ignored)
52811.1Skamil{
52821.1Skamil	const int sigval = SIGTRAP;
52831.1Skamil	pid_t child, wpid;
52841.1Skamil#if defined(TWAIT_HAVE_STATUS)
52851.1Skamil	int status;
52861.1Skamil#endif
52871.97Skamil	struct sigaction sa;
52881.97Skamil	struct ptrace_siginfo info;
52891.97Skamil	sigset_t intmask;
52901.97Skamil	struct kinfo_proc2 kp;
52911.97Skamil	size_t len = sizeof(kp);
52921.97Skamil
52931.97Skamil	int name[6];
52941.97Skamil	const size_t namelen = __arraycount(name);
52951.97Skamil	ki_sigset_t kp_sigmask;
52961.97Skamil	ki_sigset_t kp_sigignore;
52971.1Skamil
52981.1Skamil	memset(&info, 0, sizeof(info));
52991.1Skamil
53001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53021.1Skamil	if (child == 0) {
53031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53051.1Skamil
53061.97Skamil		if (masked) {
53071.97Skamil			sigemptyset(&intmask);
53081.97Skamil			sigaddset(&intmask, sigval);
53091.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
53101.97Skamil		}
53111.97Skamil
53121.97Skamil		if (ignored) {
53131.97Skamil			memset(&sa, 0, sizeof(sa));
53141.97Skamil			sa.sa_handler = SIG_IGN;
53151.97Skamil			sigemptyset(&sa.sa_mask);
53161.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
53171.97Skamil		}
53181.97Skamil
53191.13Schristos		DPRINTF("Before calling execve(2) from child\n");
53201.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
53211.1Skamil
53221.1Skamil		FORKEE_ASSERT(0 && "Not reached");
53231.1Skamil	}
53241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53251.1Skamil
53261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53281.1Skamil
53291.1Skamil	validate_status_stopped(status, sigval);
53301.1Skamil
53311.97Skamil	name[0] = CTL_KERN,
53321.97Skamil	name[1] = KERN_PROC2,
53331.97Skamil	name[2] = KERN_PROC_PID;
53341.97Skamil	name[3] = getpid();
53351.97Skamil	name[4] = sizeof(kp);
53361.97Skamil	name[5] = 1;
53371.97Skamil
53381.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53391.97Skamil
53401.97Skamil	if (masked)
53411.97Skamil		kp_sigmask = kp.p_sigmask;
53421.97Skamil
53431.97Skamil	if (ignored)
53441.97Skamil		kp_sigignore = kp.p_sigignore;
53451.97Skamil
53461.97Skamil	name[3] = getpid();
53471.97Skamil
53481.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53491.97Skamil
53501.97Skamil	if (masked) {
53511.97Skamil		DPRINTF("kp_sigmask="
53521.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53531.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
53541.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
53551.97Skamil
53561.97Skamil		DPRINTF("kp.p_sigmask="
53571.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53581.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
53591.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
53601.97Skamil
53611.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
53621.97Skamil		    sizeof(kp_sigmask)));
53631.97Skamil	}
53641.97Skamil
53651.97Skamil	if (ignored) {
53661.97Skamil		DPRINTF("kp_sigignore="
53671.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53681.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
53691.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
53701.97Skamil
53711.97Skamil		DPRINTF("kp.p_sigignore="
53721.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53731.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
53741.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
53751.97Skamil
53761.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
53771.97Skamil		    sizeof(kp_sigignore)));
53781.97Skamil	}
53791.97Skamil
53801.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53811.61Skre	SYSCALL_REQUIRE(
53821.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53831.1Skamil
53841.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
53851.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
53861.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
53871.1Skamil	    info.psi_siginfo.si_errno);
53881.1Skamil
53891.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
53901.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
53911.1Skamil
53921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53931.1Skamil	    "without signal to be sent\n");
53941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53951.1Skamil
53961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53981.1Skamil
53991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54001.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54011.1Skamil}
54021.1Skamil
54031.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
54041.97SkamilATF_TC(test);								\
54051.97SkamilATF_TC_HEAD(test, tc)							\
54061.97Skamil{									\
54071.97Skamil       atf_tc_set_md_var(tc, "descr",					\
54081.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
54091.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
54101.97Skamil           masked ? " with ignored signal" : "");			\
54111.97Skamil}									\
54121.97Skamil									\
54131.97SkamilATF_TC_BODY(test, tc)							\
54141.97Skamil{									\
54151.97Skamil									\
54161.97Skamil       traceme_exec(masked, ignored);					\
54171.97Skamil}
54181.97Skamil
54191.97SkamilTRACEME_EXEC(traceme_exec, false, false)
54201.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
54211.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
54221.97Skamil
54231.82Skamil/// ----------------------------------------------------------------------------
54241.82Skamil
54251.83Skamilstatic volatile int done;
54261.1Skamil
54271.83Skamilstatic void *
54281.83Skamiltrace_threads_cb(void *arg __unused)
54291.1Skamil{
54301.1Skamil
54311.83Skamil	done++;
54321.83Skamil
54331.83Skamil	while (done < 3)
54341.83Skamil		continue;
54351.83Skamil
54361.83Skamil	return NULL;
54371.1Skamil}
54381.1Skamil
54391.83Skamilstatic void
54401.83Skamiltrace_threads(bool trace_create, bool trace_exit)
54411.1Skamil{
54421.1Skamil	const int sigval = SIGSTOP;
54431.1Skamil	pid_t child, wpid;
54441.1Skamil#if defined(TWAIT_HAVE_STATUS)
54451.1Skamil	int status;
54461.1Skamil#endif
54471.1Skamil	ptrace_state_t state;
54481.1Skamil	const int slen = sizeof(state);
54491.1Skamil	ptrace_event_t event;
54501.1Skamil	const int elen = sizeof(event);
54511.83Skamil	struct ptrace_siginfo info;
54521.83Skamil
54531.83Skamil	pthread_t t[3];
54541.83Skamil	int rv;
54551.83Skamil	size_t n;
54561.1Skamil	lwpid_t lid;
54571.83Skamil
54581.83Skamil	/* Track created and exited threads */
54591.83Skamil	bool traced_lwps[__arraycount(t)];
54601.83Skamil
54611.128Skamil#if !TEST_LWP_ENABLED
54621.120Skamil	if (trace_create || trace_exit)
54631.119Skamil		atf_tc_skip("PR kern/51995");
54641.128Skamil#endif
54651.1Skamil
54661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54681.1Skamil	if (child == 0) {
54691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54711.1Skamil
54721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54741.1Skamil
54751.83Skamil		for (n = 0; n < __arraycount(t); n++) {
54761.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
54771.83Skamil			    NULL);
54781.83Skamil			FORKEE_ASSERT(rv == 0);
54791.83Skamil		}
54801.1Skamil
54811.83Skamil		for (n = 0; n < __arraycount(t); n++) {
54821.83Skamil			rv = pthread_join(t[n], NULL);
54831.83Skamil			FORKEE_ASSERT(rv == 0);
54841.83Skamil		}
54851.1Skamil
54861.83Skamil		/*
54871.83Skamil		 * There is race between _exit() and pthread_join() detaching
54881.83Skamil		 * a thread. For simplicity kill the process after detecting
54891.83Skamil		 * LWP events.
54901.83Skamil		 */
54911.83Skamil		while (true)
54921.83Skamil			continue;
54931.1Skamil
54941.83Skamil		FORKEE_ASSERT(0 && "Not reached");
54951.1Skamil	}
54961.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54971.1Skamil
54981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55001.1Skamil
55011.1Skamil	validate_status_stopped(status, sigval);
55021.1Skamil
55031.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55041.83Skamil	SYSCALL_REQUIRE(
55051.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55061.1Skamil
55071.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
55081.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
55091.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
55101.83Skamil	    info.psi_siginfo.si_errno);
55111.1Skamil
55121.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
55131.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
55141.1Skamil
55151.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
55161.83Skamil	memset(&event, 0, sizeof(event));
55171.83Skamil	if (trace_create)
55181.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
55191.83Skamil	if (trace_exit)
55201.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
55211.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
55221.1Skamil
55231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55241.1Skamil	    "without signal to be sent\n");
55251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55261.1Skamil
55271.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
55281.1Skamil
55291.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
55301.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
55311.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
55321.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
55331.83Skamil		    child);
55341.1Skamil
55351.83Skamil		validate_status_stopped(status, SIGTRAP);
55361.1Skamil
55371.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
55381.83Skamil		    "child\n");
55391.83Skamil		SYSCALL_REQUIRE(
55401.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55411.1Skamil
55421.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
55431.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
55441.83Skamil		    "si_errno=%#x\n",
55451.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
55461.83Skamil		    info.psi_siginfo.si_errno);
55471.1Skamil
55481.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55491.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
55501.1Skamil
55511.83Skamil		SYSCALL_REQUIRE(
55521.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55531.1Skamil
55541.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
55551.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
55561.1Skamil
55571.83Skamil		lid = state.pe_lwp;
55581.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
55591.1Skamil
55601.83Skamil		traced_lwps[lid - 1] = true;
55611.1Skamil
55621.83Skamil		DPRINTF("Before resuming the child process where it left off "
55631.83Skamil		    "and without signal to be sent\n");
55641.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55651.83Skamil	}
55661.1Skamil
55671.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
55681.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
55691.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
55701.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
55711.83Skamil		    child);
55721.1Skamil
55731.83Skamil		validate_status_stopped(status, SIGTRAP);
55741.1Skamil
55751.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
55761.83Skamil		    "child\n");
55771.83Skamil		SYSCALL_REQUIRE(
55781.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55791.1Skamil
55801.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
55811.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
55821.83Skamil		    "si_errno=%#x\n",
55831.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
55841.83Skamil		    info.psi_siginfo.si_errno);
55851.1Skamil
55861.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55871.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
55881.1Skamil
55891.83Skamil		SYSCALL_REQUIRE(
55901.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55911.1Skamil
55921.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
55931.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
55941.1Skamil
55951.83Skamil		lid = state.pe_lwp;
55961.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
55971.1Skamil
55981.83Skamil		if (trace_create) {
55991.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
56001.83Skamil			traced_lwps[lid - 1] = false;
56011.83Skamil		}
56021.1Skamil
56031.83Skamil		DPRINTF("Before resuming the child process where it left off "
56041.83Skamil		    "and without signal to be sent\n");
56051.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56061.83Skamil	}
56071.1Skamil
56081.83Skamil	kill(child, SIGKILL);
56091.1Skamil
56101.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
56111.1Skamil	    TWAIT_FNAME);
56121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56131.1Skamil
56141.83Skamil	validate_status_signaled(status, SIGKILL, 0);
56151.1Skamil
56161.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
56171.1Skamil	    TWAIT_FNAME);
56181.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56191.1Skamil}
56201.1Skamil
56211.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
56221.83SkamilATF_TC(test);								\
56231.83SkamilATF_TC_HEAD(test, tc)							\
56241.83Skamil{									\
56251.83Skamil        atf_tc_set_md_var(tc, "descr",					\
56261.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
56271.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
56281.83Skamil	    trace_exit ? "" : "out");					\
56291.83Skamil}									\
56301.83Skamil									\
56311.83SkamilATF_TC_BODY(test, tc)							\
56321.83Skamil{									\
56331.83Skamil									\
56341.83Skamil        trace_threads(trace_create, trace_exit);			\
56351.83Skamil}
56361.83Skamil
56371.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false)
56381.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true)
56391.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false)
56401.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true)
56411.83Skamil
56421.83Skamil/// ----------------------------------------------------------------------------
56431.83Skamil
56441.84SkamilATF_TC(signal_mask_unrelated);
56451.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
56461.1Skamil{
56471.1Skamil	atf_tc_set_md_var(tc, "descr",
56481.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
56491.1Skamil	    "from catching other signals");
56501.1Skamil}
56511.1Skamil
56521.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
56531.1Skamil{
56541.1Skamil	const int exitval = 5;
56551.1Skamil	const int sigval = SIGSTOP;
56561.1Skamil	const int sigmasked = SIGTRAP;
56571.1Skamil	const int signotmasked = SIGINT;
56581.1Skamil	pid_t child, wpid;
56591.1Skamil#if defined(TWAIT_HAVE_STATUS)
56601.1Skamil	int status;
56611.1Skamil#endif
56621.1Skamil	sigset_t intmask;
56631.1Skamil
56641.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56651.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56661.1Skamil	if (child == 0) {
56671.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56681.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56691.1Skamil
56701.1Skamil		sigemptyset(&intmask);
56711.1Skamil		sigaddset(&intmask, sigmasked);
56721.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56731.1Skamil
56741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56761.1Skamil
56771.13Schristos		DPRINTF("Before raising %s from child\n",
56781.1Skamil		    strsignal(signotmasked));
56791.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
56801.1Skamil
56811.13Schristos		DPRINTF("Before exiting of the child process\n");
56821.1Skamil		_exit(exitval);
56831.1Skamil	}
56841.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56851.1Skamil
56861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56881.1Skamil
56891.1Skamil	validate_status_stopped(status, sigval);
56901.1Skamil
56911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56921.1Skamil	    "without signal to be sent\n");
56931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56941.1Skamil
56951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56971.1Skamil
56981.1Skamil	validate_status_stopped(status, signotmasked);
56991.1Skamil
57001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57011.1Skamil	    "without signal to be sent\n");
57021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57031.1Skamil
57041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57061.1Skamil
57071.1Skamil	validate_status_exited(status, exitval);
57081.1Skamil
57091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57111.1Skamil}
57121.1Skamil
57131.84Skamil/// ----------------------------------------------------------------------------
57141.84Skamil
57151.1Skamil#if defined(TWAIT_HAVE_PID)
57161.99Skamilstatic void
57171.126Skamilfork2_body(const char *fn, bool masked, bool ignored)
57181.1Skamil{
57191.1Skamil	const int exitval = 5;
57201.126Skamil	const int exitval2 = 0; /* Match exit status from /bin/echo */
57211.1Skamil	const int sigval = SIGSTOP;
57221.99Skamil	pid_t child, child2 = 0, wpid;
57231.1Skamil#if defined(TWAIT_HAVE_STATUS)
57241.1Skamil	int status;
57251.1Skamil#endif
57261.1Skamil	ptrace_state_t state;
57271.1Skamil	const int slen = sizeof(state);
57281.1Skamil	ptrace_event_t event;
57291.1Skamil	const int elen = sizeof(event);
57301.99Skamil	struct sigaction sa;
57311.99Skamil	struct ptrace_siginfo info;
57321.99Skamil	sigset_t intmask;
57331.99Skamil	struct kinfo_proc2 kp;
57341.99Skamil	size_t len = sizeof(kp);
57351.99Skamil
57361.99Skamil	int name[6];
57371.99Skamil	const size_t namelen = __arraycount(name);
57381.99Skamil	ki_sigset_t kp_sigmask;
57391.99Skamil	ki_sigset_t kp_sigignore;
57401.1Skamil
57411.126Skamil	char * const arg[] = { __UNCONST("/bin/echo"), NULL };
57421.14Schristos
57431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57451.1Skamil	if (child == 0) {
57461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57481.1Skamil
57491.99Skamil		if (masked) {
57501.99Skamil			sigemptyset(&intmask);
57511.99Skamil			sigaddset(&intmask, SIGTRAP);
57521.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
57531.99Skamil		}
57541.99Skamil
57551.99Skamil		if (ignored) {
57561.99Skamil			memset(&sa, 0, sizeof(sa));
57571.99Skamil			sa.sa_handler = SIG_IGN;
57581.99Skamil			sigemptyset(&sa.sa_mask);
57591.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
57601.99Skamil		}
57611.1Skamil
57621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57641.1Skamil
57651.126Skamil		if (strcmp(fn, "spawn") == 0) {
57661.126Skamil			FORKEE_ASSERT_EQ(posix_spawn(&child2,
57671.126Skamil			    arg[0], NULL, NULL, arg, NULL), 0);
57681.126Skamil		} else  {
57691.126Skamil			if (strcmp(fn, "fork") == 0) {
57701.126Skamil				FORKEE_ASSERT((child2 = fork()) != -1);
57711.126Skamil			} else {
57721.126Skamil				FORKEE_ASSERT((child2 = vfork()) != -1);
57731.126Skamil			}
57741.126Skamil			if (child2 == 0)
57751.126Skamil				_exit(exitval2);
57761.126Skamil		}
57771.1Skamil
57781.1Skamil		FORKEE_REQUIRE_SUCCESS
57791.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
57801.1Skamil
57811.1Skamil		forkee_status_exited(status, exitval2);
57821.1Skamil
57831.13Schristos		DPRINTF("Before exiting of the child process\n");
57841.1Skamil		_exit(exitval);
57851.1Skamil	}
57861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57871.1Skamil
57881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57901.1Skamil
57911.1Skamil	validate_status_stopped(status, sigval);
57921.1Skamil
57931.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
57941.99Skamil	SYSCALL_REQUIRE(
57951.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
57961.99Skamil
57971.99Skamil	DPRINTF("Before checking siginfo_t\n");
57981.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
57991.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
58001.1Skamil
58011.99Skamil	name[0] = CTL_KERN,
58021.99Skamil	name[1] = KERN_PROC2,
58031.99Skamil	name[2] = KERN_PROC_PID;
58041.99Skamil	name[3] = child;
58051.99Skamil	name[4] = sizeof(kp);
58061.99Skamil	name[5] = 1;
58071.1Skamil
58081.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
58091.1Skamil
58101.99Skamil	if (masked)
58111.99Skamil		kp_sigmask = kp.p_sigmask;
58121.1Skamil
58131.99Skamil	if (ignored)
58141.99Skamil		kp_sigignore = kp.p_sigignore;
58151.1Skamil
58161.126Skamil	DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n",
58171.126Skamil	    strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "",
58181.126Skamil	    strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "",
58191.126Skamil	    strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "",
58201.126Skamil	    strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child);
58211.99Skamil	event.pe_set_event = 0;
58221.126Skamil	if (strcmp(fn, "spawn") == 0)
58231.126Skamil		event.pe_set_event |= PTRACE_POSIX_SPAWN;
58241.126Skamil	if (strcmp(fn, "fork") == 0)
58251.99Skamil		event.pe_set_event |= PTRACE_FORK;
58261.126Skamil	if (strcmp(fn, "vfork") == 0)
58271.99Skamil		event.pe_set_event |= PTRACE_VFORK;
58281.126Skamil	if (strcmp(fn, "vforkdone") == 0)
58291.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
58301.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
58311.1Skamil
58321.99Skamil	DPRINTF("Before resuming the child process where it left off and "
58331.99Skamil	    "without signal to be sent\n");
58341.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58351.1Skamil
58361.126Skamil	if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 ||
58371.126Skamil	    strcmp(fn, "vfork") == 0) {
58381.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
58391.99Skamil		    child);
58401.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
58411.99Skamil		    child);
58421.1Skamil
58431.99Skamil		validate_status_stopped(status, SIGTRAP);
58441.1Skamil
58451.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
58461.1Skamil
58471.99Skamil		if (masked) {
58481.99Skamil			DPRINTF("kp_sigmask="
58491.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58501.99Skamil			    PRIx32 "\n",
58511.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
58521.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
58531.1Skamil
58541.99Skamil			DPRINTF("kp.p_sigmask="
58551.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58561.99Skamil			    PRIx32 "\n",
58571.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
58581.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
58591.1Skamil
58601.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
58611.99Skamil			    sizeof(kp_sigmask)));
58621.99Skamil		}
58631.1Skamil
58641.99Skamil		if (ignored) {
58651.99Skamil			DPRINTF("kp_sigignore="
58661.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58671.99Skamil			    PRIx32 "\n",
58681.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
58691.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
58701.1Skamil
58711.99Skamil			DPRINTF("kp.p_sigignore="
58721.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58731.99Skamil			    PRIx32 "\n",
58741.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
58751.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
58761.1Skamil
58771.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
58781.99Skamil			    sizeof(kp_sigignore)));
58791.99Skamil		}
58801.1Skamil
58811.99Skamil		SYSCALL_REQUIRE(
58821.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
58831.126Skamil		if (strcmp(fn, "spawn") == 0) {
58841.126Skamil			ATF_REQUIRE_EQ(
58851.126Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
58861.126Skamil			       PTRACE_POSIX_SPAWN);
58871.126Skamil		}
58881.126Skamil		if (strcmp(fn, "fork") == 0) {
58891.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
58901.99Skamil			       PTRACE_FORK);
58911.99Skamil		}
58921.126Skamil		if (strcmp(fn, "vfork") == 0) {
58931.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
58941.99Skamil			       PTRACE_VFORK);
58951.99Skamil		}
58961.1Skamil
58971.99Skamil		child2 = state.pe_other_pid;
58981.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
58991.1Skamil
59001.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
59011.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
59021.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59031.99Skamil		    child2);
59041.1Skamil
59051.99Skamil		validate_status_stopped(status, SIGTRAP);
59061.1Skamil
59071.99Skamil		name[3] = child2;
59081.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
59091.1Skamil
59101.99Skamil		if (masked) {
59111.99Skamil			DPRINTF("kp_sigmask="
59121.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59131.99Skamil			    PRIx32 "\n",
59141.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
59151.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
59161.1Skamil
59171.99Skamil			DPRINTF("kp.p_sigmask="
59181.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59191.99Skamil			    PRIx32 "\n",
59201.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
59211.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
59221.14Schristos
59231.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
59241.99Skamil			    sizeof(kp_sigmask)));
59251.99Skamil		}
59261.1Skamil
59271.99Skamil		if (ignored) {
59281.99Skamil			DPRINTF("kp_sigignore="
59291.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59301.99Skamil			    PRIx32 "\n",
59311.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
59321.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
59331.1Skamil
59341.99Skamil			DPRINTF("kp.p_sigignore="
59351.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59361.99Skamil			    PRIx32 "\n",
59371.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
59381.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
59391.1Skamil
59401.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
59411.99Skamil			    sizeof(kp_sigignore)));
59421.99Skamil		}
59431.1Skamil
59441.99Skamil		SYSCALL_REQUIRE(
59451.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
59461.126Skamil		if (strcmp(fn, "spawn") == 0) {
59471.126Skamil			ATF_REQUIRE_EQ(
59481.126Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
59491.126Skamil			       PTRACE_POSIX_SPAWN);
59501.126Skamil		}
59511.126Skamil		if (strcmp(fn, "fork") == 0) {
59521.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
59531.99Skamil			       PTRACE_FORK);
59541.99Skamil		}
59551.126Skamil		if (strcmp(fn, "vfork") == 0) {
59561.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
59571.99Skamil			       PTRACE_VFORK);
59581.99Skamil		}
59591.1Skamil
59601.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
59611.1Skamil
59621.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
59631.99Skamil		    "and without signal to be sent\n");
59641.99Skamil		SYSCALL_REQUIRE(
59651.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
59661.1Skamil
59671.99Skamil		DPRINTF("Before resuming the child process where it left off "
59681.99Skamil		    "and without signal to be sent\n");
59691.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59701.1Skamil	}
59711.1Skamil
59721.126Skamil	if (strcmp(fn, "vforkdone") == 0) {
59731.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
59741.99Skamil		    child);
59751.99Skamil		TWAIT_REQUIRE_SUCCESS(
59761.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
59771.1Skamil
59781.99Skamil		validate_status_stopped(status, SIGTRAP);
59791.1Skamil
59801.99Skamil		name[3] = child;
59811.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
59821.1Skamil
59831.102Skamil		/*
59841.102Skamil		 * SIGCHLD is now pending in the signal queue and
59851.102Skamil		 * the kernel presents it to userland as a masked signal.
59861.102Skamil		 */
59871.102Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
59881.102Skamil
59891.99Skamil		if (masked) {
59901.99Skamil			DPRINTF("kp_sigmask="
59911.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59921.99Skamil			    PRIx32 "\n",
59931.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
59941.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
59951.1Skamil
59961.99Skamil			DPRINTF("kp.p_sigmask="
59971.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59981.99Skamil			    PRIx32 "\n",
59991.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
60001.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
60011.1Skamil
60021.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
60031.99Skamil			    sizeof(kp_sigmask)));
60041.99Skamil		}
60051.1Skamil
60061.99Skamil		if (ignored) {
60071.99Skamil			DPRINTF("kp_sigignore="
60081.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
60091.99Skamil			    PRIx32 "\n",
60101.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
60111.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
60121.1Skamil
60131.99Skamil			DPRINTF("kp.p_sigignore="
60141.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
60151.99Skamil			    PRIx32 "\n",
60161.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
60171.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
60181.1Skamil
60191.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
60201.99Skamil			    sizeof(kp_sigignore)));
60211.99Skamil		}
60221.1Skamil
60231.99Skamil		SYSCALL_REQUIRE(
60241.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
60251.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
60261.1Skamil
60271.99Skamil		child2 = state.pe_other_pid;
60281.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
60291.99Skamil		    child2);
60301.1Skamil
60311.99Skamil		DPRINTF("Before resuming the child process where it left off "
60321.99Skamil		    "and without signal to be sent\n");
60331.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60341.99Skamil	}
60351.1Skamil
60361.126Skamil	if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 ||
60371.126Skamil	    strcmp(fn, "vfork") == 0) {
60381.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
60391.99Skamil		    "\n", TWAIT_FNAME);
60401.99Skamil		TWAIT_REQUIRE_SUCCESS(
60411.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
60421.1Skamil
60431.99Skamil		validate_status_exited(status, exitval2);
60441.1Skamil
60451.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
60461.99Skamil		    "process\n", TWAIT_FNAME);
60471.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
60481.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
60491.99Skamil	}
60501.1Skamil
60511.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60521.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
60531.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60541.1Skamil
60551.1Skamil	validate_status_stopped(status, SIGCHLD);
60561.1Skamil
60571.57Skamil	DPRINTF("Before resuming the child process where it left off and "
60581.1Skamil	    "without signal to be sent\n");
60591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60601.1Skamil
60611.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60621.1Skamil	    TWAIT_FNAME);
60631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60641.1Skamil
60651.1Skamil	validate_status_exited(status, exitval);
60661.1Skamil
60671.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60681.57Skamil	    TWAIT_FNAME);
60691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60701.1Skamil}
60711.1Skamil
60721.126Skamil#define FORK2_TEST(name,fn,masked,ignored)				\
60731.99SkamilATF_TC(name);								\
60741.99SkamilATF_TC_HEAD(name, tc)							\
60751.99Skamil{									\
60761.126Skamil	atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught "	\
60771.99Skamil	    "regardless of signal %s%s", 				\
60781.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
60791.99Skamil}									\
60801.99Skamil									\
60811.99SkamilATF_TC_BODY(name, tc)							\
60821.99Skamil{									\
60831.99Skamil									\
60841.126Skamil	fork2_body(fn, masked, ignored);				\
60851.1Skamil}
60861.1Skamil
60871.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false)
60881.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true)
60891.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false)
60901.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true)
60911.110Skamil#if TEST_VFORK_ENABLED
60921.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false)
60931.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true)
60941.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false)
60951.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true)
60961.1Skamil#endif
60971.110Skamil#endif
60981.1Skamil
60991.99Skamil/// ----------------------------------------------------------------------------
61001.1Skamil
61011.83Skamilvolatile lwpid_t the_lwp_id = 0;
61021.83Skamil
61031.83Skamilstatic void
61041.83Skamillwp_main_func(void *arg)
61051.83Skamil{
61061.83Skamil	the_lwp_id = _lwp_self();
61071.83Skamil	_lwp_exit();
61081.83Skamil}
61091.83Skamil
61101.1SkamilATF_TC(signal9);
61111.1SkamilATF_TC_HEAD(signal9, tc)
61121.1Skamil{
61131.1Skamil	atf_tc_set_md_var(tc, "descr",
61141.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61151.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
61161.1Skamil}
61171.1Skamil
61181.1SkamilATF_TC_BODY(signal9, tc)
61191.1Skamil{
61201.1Skamil	const int exitval = 5;
61211.1Skamil	const int sigval = SIGSTOP;
61221.1Skamil	const int sigmasked = SIGTRAP;
61231.1Skamil	pid_t child, wpid;
61241.1Skamil#if defined(TWAIT_HAVE_STATUS)
61251.1Skamil	int status;
61261.1Skamil#endif
61271.1Skamil	sigset_t intmask;
61281.1Skamil	ptrace_state_t state;
61291.1Skamil	const int slen = sizeof(state);
61301.1Skamil	ptrace_event_t event;
61311.1Skamil	const int elen = sizeof(event);
61321.1Skamil	ucontext_t uc;
61331.1Skamil	lwpid_t lid;
61341.1Skamil	static const size_t ssize = 16*1024;
61351.1Skamil	void *stack;
61361.1Skamil
61371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61391.1Skamil	if (child == 0) {
61401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61421.1Skamil
61431.1Skamil		sigemptyset(&intmask);
61441.1Skamil		sigaddset(&intmask, sigmasked);
61451.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61461.1Skamil
61471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61491.1Skamil
61501.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
61511.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
61521.1Skamil
61531.13Schristos		DPRINTF("Before making context for new lwp in child\n");
61541.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
61551.1Skamil
61561.13Schristos		DPRINTF("Before creating new in child\n");
61571.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
61581.1Skamil
61591.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
61601.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
61611.1Skamil
61621.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
61631.1Skamil		    "are the same\n", lid, the_lwp_id);
61641.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
61651.1Skamil
61661.13Schristos		DPRINTF("Before exiting of the child process\n");
61671.1Skamil		_exit(exitval);
61681.1Skamil	}
61691.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61701.1Skamil
61711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61731.1Skamil
61741.1Skamil	validate_status_stopped(status, sigval);
61751.1Skamil
61761.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
61771.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
61781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
61791.1Skamil
61801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61811.1Skamil	    "without signal to be sent\n");
61821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61831.1Skamil
61841.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61851.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
61861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61871.1Skamil
61881.1Skamil	validate_status_stopped(status, sigmasked);
61891.1Skamil
61901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
61911.1Skamil
61921.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
61931.1Skamil
61941.1Skamil	lid = state.pe_lwp;
61951.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
61961.1Skamil
61971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61981.1Skamil	    "without signal to be sent\n");
61991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62001.1Skamil
62011.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62021.1Skamil	    TWAIT_FNAME);
62031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62041.1Skamil
62051.1Skamil	validate_status_exited(status, exitval);
62061.1Skamil
62071.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62081.1Skamil	    TWAIT_FNAME);
62091.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62101.1Skamil}
62111.1Skamil
62121.1SkamilATF_TC(signal10);
62131.1SkamilATF_TC_HEAD(signal10, tc)
62141.1Skamil{
62151.1Skamil	atf_tc_set_md_var(tc, "descr",
62161.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
62171.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
62181.1Skamil}
62191.1Skamil
62201.1SkamilATF_TC_BODY(signal10, tc)
62211.1Skamil{
62221.1Skamil	const int exitval = 5;
62231.1Skamil	const int sigval = SIGSTOP;
62241.1Skamil	const int sigmasked = SIGTRAP;
62251.1Skamil	pid_t child, wpid;
62261.1Skamil#if defined(TWAIT_HAVE_STATUS)
62271.1Skamil	int status;
62281.1Skamil#endif
62291.1Skamil	sigset_t intmask;
62301.1Skamil	ptrace_state_t state;
62311.1Skamil	const int slen = sizeof(state);
62321.1Skamil	ptrace_event_t event;
62331.1Skamil	const int elen = sizeof(event);
62341.1Skamil	ucontext_t uc;
62351.1Skamil	lwpid_t lid;
62361.1Skamil	static const size_t ssize = 16*1024;
62371.1Skamil	void *stack;
62381.1Skamil
62391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62411.1Skamil	if (child == 0) {
62421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62441.1Skamil
62451.1Skamil		sigemptyset(&intmask);
62461.1Skamil		sigaddset(&intmask, sigmasked);
62471.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
62481.1Skamil
62491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62511.1Skamil
62521.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62531.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62541.1Skamil
62551.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62561.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
62571.1Skamil
62581.13Schristos		DPRINTF("Before creating new in child\n");
62591.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62601.1Skamil
62611.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62621.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62631.1Skamil
62641.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62651.1Skamil		    "are the same\n", lid, the_lwp_id);
62661.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
62671.1Skamil
62681.13Schristos		DPRINTF("Before exiting of the child process\n");
62691.1Skamil		_exit(exitval);
62701.1Skamil	}
62711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62721.1Skamil
62731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62751.1Skamil
62761.1Skamil	validate_status_stopped(status, sigval);
62771.1Skamil
62781.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
62791.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
62801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62811.1Skamil
62821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62831.1Skamil	    "without signal to be sent\n");
62841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62851.1Skamil
62861.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62871.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
62881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62891.1Skamil
62901.1Skamil	validate_status_stopped(status, sigmasked);
62911.1Skamil
62921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
62931.1Skamil
62941.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
62951.1Skamil
62961.1Skamil	lid = state.pe_lwp;
62971.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
62981.1Skamil
62991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63001.1Skamil	    "without signal to be sent\n");
63011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63021.1Skamil
63031.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63041.1Skamil	    TWAIT_FNAME);
63051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63061.1Skamil
63071.1Skamil	validate_status_exited(status, exitval);
63081.1Skamil
63091.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63101.1Skamil	    TWAIT_FNAME);
63111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63121.1Skamil}
63131.1Skamil
63141.1Skamilstatic void
63151.1Skamillwp_main_stop(void *arg)
63161.1Skamil{
63171.1Skamil	the_lwp_id = _lwp_self();
63181.1Skamil
63191.1Skamil	raise(SIGTRAP);
63201.1Skamil
63211.1Skamil	_lwp_exit();
63221.1Skamil}
63231.1Skamil
63241.1SkamilATF_TC(suspend1);
63251.1SkamilATF_TC_HEAD(suspend1, tc)
63261.1Skamil{
63271.1Skamil	atf_tc_set_md_var(tc, "descr",
63281.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
63291.1Skamil	    "resumed by a tracee");
63301.1Skamil}
63311.1Skamil
63321.1SkamilATF_TC_BODY(suspend1, tc)
63331.1Skamil{
63341.1Skamil	const int exitval = 5;
63351.1Skamil	const int sigval = SIGSTOP;
63361.1Skamil	pid_t child, wpid;
63371.1Skamil#if defined(TWAIT_HAVE_STATUS)
63381.1Skamil	int status;
63391.1Skamil#endif
63401.1Skamil	ucontext_t uc;
63411.1Skamil	lwpid_t lid;
63421.1Skamil	static const size_t ssize = 16*1024;
63431.1Skamil	void *stack;
63441.1Skamil	struct ptrace_lwpinfo pl;
63451.1Skamil	struct ptrace_siginfo psi;
63461.1Skamil	volatile int go = 0;
63471.1Skamil
63481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63501.1Skamil	if (child == 0) {
63511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63531.1Skamil
63541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63561.1Skamil
63571.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63581.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63591.1Skamil
63601.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63611.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
63621.1Skamil
63631.13Schristos		DPRINTF("Before creating new in child\n");
63641.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63651.1Skamil
63661.1Skamil		while (go == 0)
63671.1Skamil			continue;
63681.1Skamil
63691.1Skamil		raise(SIGINT);
63701.1Skamil
63711.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
63721.1Skamil
63731.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
63741.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
63751.1Skamil
63761.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
63771.1Skamil		    "are the same\n", lid, the_lwp_id);
63781.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63791.1Skamil
63801.13Schristos		DPRINTF("Before exiting of the child process\n");
63811.1Skamil		_exit(exitval);
63821.1Skamil	}
63831.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63841.1Skamil
63851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63871.1Skamil
63881.1Skamil	validate_status_stopped(status, sigval);
63891.1Skamil
63901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63911.1Skamil	    "without signal to be sent\n");
63921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63931.1Skamil
63941.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63951.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63971.1Skamil
63981.1Skamil	validate_status_stopped(status, SIGTRAP);
63991.1Skamil
64001.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
64011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
64021.1Skamil
64031.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
64041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
64051.1Skamil
64061.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
64071.1Skamil	    child, getpid());
64081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
64091.1Skamil
64101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64111.1Skamil	    "without signal to be sent\n");
64121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64131.1Skamil
64141.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64151.1Skamil	    "SIGINT\n", TWAIT_FNAME);
64161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64171.1Skamil
64181.1Skamil	validate_status_stopped(status, SIGINT);
64191.1Skamil
64201.1Skamil	pl.pl_lwpid = 0;
64211.1Skamil
64221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
64231.1Skamil	while (pl.pl_lwpid != 0) {
64241.1Skamil
64251.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
64261.1Skamil		switch (pl.pl_lwpid) {
64271.1Skamil		case 1:
64281.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
64291.1Skamil			break;
64301.1Skamil		case 2:
64311.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
64321.1Skamil			break;
64331.1Skamil		}
64341.1Skamil	}
64351.1Skamil
64361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64371.1Skamil	    "without signal to be sent\n");
64381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64391.1Skamil
64401.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
64411.1Skamil	    TWAIT_FNAME);
64421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64431.1Skamil
64441.1Skamil	validate_status_exited(status, exitval);
64451.1Skamil
64461.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64471.1Skamil	    TWAIT_FNAME);
64481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64491.1Skamil}
64501.1Skamil
64511.1SkamilATF_TC(suspend2);
64521.1SkamilATF_TC_HEAD(suspend2, tc)
64531.1Skamil{
64541.1Skamil	atf_tc_set_md_var(tc, "descr",
64551.1Skamil	    "Verify that the while the only thread within a process is "
64561.1Skamil	    "suspended, the whole process cannot be unstopped");
64571.1Skamil}
64581.1Skamil
64591.1SkamilATF_TC_BODY(suspend2, tc)
64601.1Skamil{
64611.1Skamil	const int exitval = 5;
64621.1Skamil	const int sigval = SIGSTOP;
64631.1Skamil	pid_t child, wpid;
64641.1Skamil#if defined(TWAIT_HAVE_STATUS)
64651.1Skamil	int status;
64661.1Skamil#endif
64671.1Skamil	struct ptrace_siginfo psi;
64681.1Skamil
64691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64711.1Skamil	if (child == 0) {
64721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64741.1Skamil
64751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64771.1Skamil
64781.13Schristos		DPRINTF("Before exiting of the child process\n");
64791.1Skamil		_exit(exitval);
64801.1Skamil	}
64811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64821.1Skamil
64831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64851.1Skamil
64861.1Skamil	validate_status_stopped(status, sigval);
64871.1Skamil
64881.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
64891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
64901.1Skamil
64911.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
64921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
64931.1Skamil
64941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64951.1Skamil	    "without signal to be sent\n");
64961.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
64971.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
64981.1Skamil
64991.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
65001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
65011.1Skamil
65021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65031.1Skamil	    "without signal to be sent\n");
65041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65051.1Skamil
65061.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65071.1Skamil	    TWAIT_FNAME);
65081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65091.1Skamil
65101.1Skamil	validate_status_exited(status, exitval);
65111.1Skamil
65121.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
65131.1Skamil	    TWAIT_FNAME);
65141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65151.1Skamil}
65161.1Skamil
65171.1SkamilATF_TC(resume1);
65181.1SkamilATF_TC_HEAD(resume1, tc)
65191.1Skamil{
65201.1Skamil	atf_tc_set_md_var(tc, "descr",
65211.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
65221.1Skamil	    "resumed by the debugger");
65231.1Skamil}
65241.1Skamil
65251.1SkamilATF_TC_BODY(resume1, tc)
65261.1Skamil{
65271.1Skamil	struct msg_fds fds;
65281.1Skamil	const int exitval = 5;
65291.1Skamil	const int sigval = SIGSTOP;
65301.1Skamil	pid_t child, wpid;
65311.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
65321.1Skamil#if defined(TWAIT_HAVE_STATUS)
65331.1Skamil	int status;
65341.1Skamil#endif
65351.1Skamil	ucontext_t uc;
65361.1Skamil	lwpid_t lid;
65371.1Skamil	static const size_t ssize = 16*1024;
65381.1Skamil	void *stack;
65391.1Skamil	struct ptrace_lwpinfo pl;
65401.1Skamil	struct ptrace_siginfo psi;
65411.1Skamil
65421.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
65431.1Skamil
65441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
65451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
65461.1Skamil	if (child == 0) {
65471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65491.1Skamil
65501.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65511.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65521.1Skamil
65531.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
65541.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
65551.1Skamil
65561.13Schristos		DPRINTF("Before making context for new lwp in child\n");
65571.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
65581.1Skamil
65591.13Schristos		DPRINTF("Before creating new in child\n");
65601.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
65611.1Skamil
65621.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
65631.1Skamil
65641.1Skamil		raise(SIGINT);
65651.1Skamil
65661.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
65671.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
65681.1Skamil
65691.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
65701.1Skamil		    "are the same\n", lid, the_lwp_id);
65711.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
65721.1Skamil
65731.13Schristos		DPRINTF("Before exiting of the child process\n");
65741.1Skamil		_exit(exitval);
65751.1Skamil	}
65761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65771.1Skamil
65781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65801.1Skamil
65811.1Skamil	validate_status_stopped(status, sigval);
65821.1Skamil
65831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65841.1Skamil	    "without signal to be sent\n");
65851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65861.1Skamil
65871.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65881.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
65891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65901.1Skamil
65911.1Skamil	validate_status_stopped(status, SIGTRAP);
65921.1Skamil
65931.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
65941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
65951.1Skamil
65961.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
65971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65981.1Skamil
65991.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
66001.1Skamil
66011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66021.1Skamil	    "without signal to be sent\n");
66031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66041.1Skamil
66051.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
66061.1Skamil	    "SIGINT\n", TWAIT_FNAME);
66071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66081.1Skamil
66091.1Skamil	validate_status_stopped(status, SIGINT);
66101.1Skamil
66111.1Skamil	pl.pl_lwpid = 0;
66121.1Skamil
66131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
66141.1Skamil	while (pl.pl_lwpid != 0) {
66151.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
66161.1Skamil		switch (pl.pl_lwpid) {
66171.1Skamil		case 1:
66181.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
66191.1Skamil			break;
66201.1Skamil		case 2:
66211.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
66221.1Skamil			break;
66231.1Skamil		}
66241.1Skamil	}
66251.1Skamil
66261.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
66271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
66281.1Skamil
66291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66301.1Skamil	    "without signal to be sent\n");
66311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66321.1Skamil
66331.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
66341.1Skamil	    TWAIT_FNAME);
66351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66361.1Skamil
66371.1Skamil	validate_status_exited(status, exitval);
66381.1Skamil
66391.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66401.1Skamil	    TWAIT_FNAME);
66411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66421.1Skamil
66431.1Skamil	msg_close(&fds);
66441.1Skamil}
66451.1Skamil
66461.1SkamilATF_TC(syscall1);
66471.1SkamilATF_TC_HEAD(syscall1, tc)
66481.1Skamil{
66491.1Skamil	atf_tc_set_md_var(tc, "descr",
66501.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
66511.1Skamil}
66521.1Skamil
66531.1SkamilATF_TC_BODY(syscall1, tc)
66541.1Skamil{
66551.1Skamil	const int exitval = 5;
66561.1Skamil	const int sigval = SIGSTOP;
66571.1Skamil	pid_t child, wpid;
66581.1Skamil#if defined(TWAIT_HAVE_STATUS)
66591.1Skamil	int status;
66601.1Skamil#endif
66611.1Skamil	struct ptrace_siginfo info;
66621.1Skamil	memset(&info, 0, sizeof(info));
66631.1Skamil
66641.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66651.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66661.1Skamil	if (child == 0) {
66671.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66681.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66691.1Skamil
66701.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66711.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66721.1Skamil
66731.1Skamil		syscall(SYS_getpid);
66741.1Skamil
66751.13Schristos		DPRINTF("Before exiting of the child process\n");
66761.1Skamil		_exit(exitval);
66771.1Skamil	}
66781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66791.1Skamil
66801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66821.1Skamil
66831.1Skamil	validate_status_stopped(status, sigval);
66841.1Skamil
66851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66861.1Skamil	    "without signal to be sent\n");
66871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
66881.1Skamil
66891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66911.1Skamil
66921.1Skamil	validate_status_stopped(status, SIGTRAP);
66931.1Skamil
66941.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
66951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
66961.1Skamil
66971.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
66981.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
66991.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
67001.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
67011.1Skamil
67021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67031.1Skamil	    "without signal to be sent\n");
67041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67051.1Skamil
67061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67081.1Skamil
67091.1Skamil	validate_status_stopped(status, SIGTRAP);
67101.1Skamil
67111.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
67121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
67131.1Skamil
67141.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
67151.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
67161.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
67171.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
67181.1Skamil
67191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67201.1Skamil	    "without signal to be sent\n");
67211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67221.1Skamil
67231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67251.1Skamil
67261.1Skamil	validate_status_exited(status, exitval);
67271.1Skamil
67281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67301.1Skamil}
67311.1Skamil
67321.1SkamilATF_TC(syscallemu1);
67331.1SkamilATF_TC_HEAD(syscallemu1, tc)
67341.1Skamil{
67351.1Skamil	atf_tc_set_md_var(tc, "descr",
67361.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
67371.1Skamil}
67381.1Skamil
67391.1SkamilATF_TC_BODY(syscallemu1, tc)
67401.1Skamil{
67411.1Skamil	const int exitval = 5;
67421.1Skamil	const int sigval = SIGSTOP;
67431.1Skamil	pid_t child, wpid;
67441.1Skamil#if defined(TWAIT_HAVE_STATUS)
67451.1Skamil	int status;
67461.1Skamil#endif
67471.1Skamil
67481.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
67491.6Skamil	/* syscallemu does not work on sparc (32-bit) */
67501.6Skamil	atf_tc_expect_fail("PR kern/52166");
67511.6Skamil#endif
67521.6Skamil
67531.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67541.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67551.1Skamil	if (child == 0) {
67561.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67571.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67581.1Skamil
67591.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67601.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67611.1Skamil
67621.1Skamil		syscall(SYS_exit, 100);
67631.1Skamil
67641.13Schristos		DPRINTF("Before exiting of the child process\n");
67651.1Skamil		_exit(exitval);
67661.1Skamil	}
67671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67681.1Skamil
67691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67711.1Skamil
67721.1Skamil	validate_status_stopped(status, sigval);
67731.1Skamil
67741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67751.1Skamil	    "without signal to be sent\n");
67761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67771.1Skamil
67781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67801.1Skamil
67811.1Skamil	validate_status_stopped(status, SIGTRAP);
67821.1Skamil
67831.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
67841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
67851.1Skamil
67861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67871.1Skamil	    "without signal to be sent\n");
67881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67891.1Skamil
67901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67921.1Skamil
67931.1Skamil	validate_status_stopped(status, SIGTRAP);
67941.1Skamil
67951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67961.1Skamil	    "without signal to be sent\n");
67971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67981.1Skamil
67991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68011.1Skamil
68021.1Skamil	validate_status_exited(status, exitval);
68031.1Skamil
68041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68051.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68061.1Skamil}
68071.1Skamil
68081.103Skamil/// ----------------------------------------------------------------------------
68091.103Skamil
68101.106Skamilstatic void
68111.106Skamilclone_body(int flags, bool trackfork, bool trackvfork,
68121.106Skamil    bool trackvforkdone)
68131.106Skamil{
68141.106Skamil	const int exitval = 5;
68151.106Skamil	const int exitval2 = 15;
68161.106Skamil	const int sigval = SIGSTOP;
68171.106Skamil	pid_t child, child2 = 0, wpid;
68181.106Skamil#if defined(TWAIT_HAVE_STATUS)
68191.106Skamil	int status;
68201.106Skamil#endif
68211.106Skamil	ptrace_state_t state;
68221.106Skamil	const int slen = sizeof(state);
68231.106Skamil	ptrace_event_t event;
68241.106Skamil	const int elen = sizeof(event);
68251.106Skamil
68261.106Skamil	const size_t stack_size = 1024 * 1024;
68271.106Skamil	void *stack, *stack_base;
68281.106Skamil
68291.106Skamil	stack = malloc(stack_size);
68301.106Skamil	ATF_REQUIRE(stack != NULL);
68311.106Skamil
68321.106Skamil#ifdef __MACHINE_STACK_GROWS_UP
68331.106Skamil	stack_base = stack;
68341.106Skamil#else
68351.106Skamil	stack_base = (char *)stack + stack_size;
68361.106Skamil#endif
68371.106Skamil
68381.106Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
68391.106Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
68401.106Skamil	if (child == 0) {
68411.106Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68421.106Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68431.106Skamil
68441.106Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68451.106Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68461.106Skamil
68471.106Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
68481.106Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
68491.106Skamil
68501.106Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
68511.106Skamil		    child2);
68521.106Skamil
68531.106Skamil		// XXX WALLSIG?
68541.106Skamil		FORKEE_REQUIRE_SUCCESS
68551.106Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
68561.106Skamil
68571.106Skamil		forkee_status_exited(status, exitval2);
68581.106Skamil
68591.106Skamil		DPRINTF("Before exiting of the child process\n");
68601.106Skamil		_exit(exitval);
68611.106Skamil	}
68621.106Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
68631.106Skamil
68641.106Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68651.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68661.106Skamil
68671.106Skamil	validate_status_stopped(status, sigval);
68681.106Skamil
68691.106Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
68701.106Skamil	    trackfork ? "|PTRACE_FORK" : "",
68711.106Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
68721.106Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
68731.106Skamil	event.pe_set_event = 0;
68741.106Skamil	if (trackfork)
68751.106Skamil		event.pe_set_event |= PTRACE_FORK;
68761.106Skamil	if (trackvfork)
68771.106Skamil		event.pe_set_event |= PTRACE_VFORK;
68781.106Skamil	if (trackvforkdone)
68791.106Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
68801.106Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
68811.106Skamil
68821.106Skamil	DPRINTF("Before resuming the child process where it left off and "
68831.106Skamil	    "without signal to be sent\n");
68841.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68851.106Skamil
68861.106Skamil#if defined(TWAIT_HAVE_PID)
68871.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
68881.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
68891.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
68901.106Skamil		    child);
68911.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
68921.106Skamil		    child);
68931.106Skamil
68941.106Skamil		validate_status_stopped(status, SIGTRAP);
68951.106Skamil
68961.106Skamil		SYSCALL_REQUIRE(
68971.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
68981.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
68991.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
69001.106Skamil			       PTRACE_FORK);
69011.106Skamil		}
69021.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
69031.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
69041.106Skamil			       PTRACE_VFORK);
69051.106Skamil		}
69061.106Skamil
69071.106Skamil		child2 = state.pe_other_pid;
69081.106Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
69091.106Skamil
69101.106Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
69111.106Skamil		    "%d\n", TWAIT_FNAME, child2, child);
69121.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
69131.106Skamil		    child2);
69141.106Skamil
69151.106Skamil		validate_status_stopped(status, SIGTRAP);
69161.106Skamil
69171.106Skamil		SYSCALL_REQUIRE(
69181.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
69191.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
69201.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
69211.106Skamil			       PTRACE_FORK);
69221.106Skamil		}
69231.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
69241.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
69251.106Skamil			       PTRACE_VFORK);
69261.106Skamil		}
69271.106Skamil
69281.106Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
69291.106Skamil
69301.106Skamil		DPRINTF("Before resuming the forkee process where it left off "
69311.106Skamil		    "and without signal to be sent\n");
69321.106Skamil		SYSCALL_REQUIRE(
69331.106Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
69341.106Skamil
69351.106Skamil		DPRINTF("Before resuming the child process where it left off "
69361.106Skamil		    "and without signal to be sent\n");
69371.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69381.106Skamil	}
69391.106Skamil#endif
69401.106Skamil
69411.106Skamil	if (trackvforkdone && (flags & CLONE_VFORK)) {
69421.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
69431.106Skamil		    child);
69441.106Skamil		TWAIT_REQUIRE_SUCCESS(
69451.106Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
69461.106Skamil
69471.106Skamil		validate_status_stopped(status, SIGTRAP);
69481.106Skamil
69491.106Skamil		SYSCALL_REQUIRE(
69501.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
69511.106Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
69521.106Skamil
69531.106Skamil		child2 = state.pe_other_pid;
69541.106Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
69551.106Skamil		    child2);
69561.106Skamil
69571.106Skamil		DPRINTF("Before resuming the child process where it left off "
69581.106Skamil		    "and without signal to be sent\n");
69591.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69601.106Skamil	}
69611.106Skamil
69621.103Skamil#if defined(TWAIT_HAVE_PID)
69631.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
69641.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
69651.106Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
69661.106Skamil		    "\n", TWAIT_FNAME);
69671.106Skamil		TWAIT_REQUIRE_SUCCESS(
69681.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
69691.106Skamil
69701.106Skamil		validate_status_exited(status, exitval2);
69711.106Skamil
69721.106Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
69731.106Skamil		    "process\n", TWAIT_FNAME);
69741.106Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
69751.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
69761.106Skamil	}
69771.106Skamil#endif
69781.106Skamil
69791.106Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
69801.106Skamil	    "SIGCHLD\n", TWAIT_FNAME);
69811.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69821.106Skamil
69831.106Skamil	validate_status_stopped(status, SIGCHLD);
69841.106Skamil
69851.106Skamil	DPRINTF("Before resuming the child process where it left off and "
69861.106Skamil	    "without signal to be sent\n");
69871.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69881.106Skamil
69891.106Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
69901.106Skamil	    TWAIT_FNAME);
69911.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69921.106Skamil
69931.106Skamil	validate_status_exited(status, exitval);
69941.103Skamil
69951.106Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
69961.106Skamil	    TWAIT_FNAME);
69971.106Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69981.106Skamil}
69991.103Skamil
70001.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone)			\
70011.106SkamilATF_TC(name);								\
70021.106SkamilATF_TC_HEAD(name, tc)							\
70031.106Skamil{									\
70041.106Skamil	atf_tc_set_md_var(tc, "descr", "Verify clone(%s) "		\
70051.106Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
70061.106Skamil	    #flags,							\
70071.106Skamil	    tfork ? "|PTRACE_FORK" : "",				\
70081.106Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
70091.106Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
70101.106Skamil}									\
70111.106Skamil									\
70121.106SkamilATF_TC_BODY(name, tc)							\
70131.106Skamil{									\
70141.106Skamil									\
70151.106Skamil	clone_body(flags, tfork, tvfork, tvforkdone);			\
70161.103Skamil}
70171.103Skamil
70181.106SkamilCLONE_TEST(clone1, 0, false, false, false)
70191.106Skamil#if defined(TWAIT_HAVE_PID)
70201.106SkamilCLONE_TEST(clone2, 0, true, false, false)
70211.106SkamilCLONE_TEST(clone3, 0, false, true, false)
70221.106SkamilCLONE_TEST(clone4, 0, true, true, false)
70231.106Skamil#endif
70241.106SkamilCLONE_TEST(clone5, 0, false, false, true)
70251.106Skamil#if defined(TWAIT_HAVE_PID)
70261.106SkamilCLONE_TEST(clone6, 0, true, false, true)
70271.106SkamilCLONE_TEST(clone7, 0, false, true, true)
70281.106SkamilCLONE_TEST(clone8, 0, true, true, true)
70291.106Skamil#endif
70301.106Skamil
70311.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false)
70321.106Skamil#if defined(TWAIT_HAVE_PID)
70331.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false)
70341.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false)
70351.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false)
70361.106Skamil#endif
70371.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true)
70381.106Skamil#if defined(TWAIT_HAVE_PID)
70391.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true)
70401.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true)
70411.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true)
70421.106Skamil#endif
70431.106Skamil
70441.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false)
70451.106Skamil#if defined(TWAIT_HAVE_PID)
70461.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false)
70471.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false)
70481.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false)
70491.106Skamil#endif
70501.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true)
70511.106Skamil#if defined(TWAIT_HAVE_PID)
70521.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true)
70531.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true)
70541.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true)
70551.106Skamil#endif
70561.106Skamil
70571.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false)
70581.106Skamil#if defined(TWAIT_HAVE_PID)
70591.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false)
70601.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false)
70611.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false)
70621.106Skamil#endif
70631.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true)
70641.106Skamil#if defined(TWAIT_HAVE_PID)
70651.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true)
70661.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true)
70671.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true)
70681.106Skamil#endif
70691.106Skamil
70701.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false)
70711.106Skamil#if defined(TWAIT_HAVE_PID)
70721.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false)
70731.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false)
70741.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false)
70751.106Skamil#endif
70761.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true)
70771.106Skamil#if defined(TWAIT_HAVE_PID)
70781.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true)
70791.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true)
70801.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true)
70811.106Skamil#endif
70821.106Skamil
70831.110Skamil#if TEST_VFORK_ENABLED
70841.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false)
70851.106Skamil#if defined(TWAIT_HAVE_PID)
70861.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false)
70871.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false)
70881.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false)
70891.106Skamil#endif
70901.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true)
70911.106Skamil#if defined(TWAIT_HAVE_PID)
70921.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true)
70931.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true)
70941.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true)
70951.106Skamil#endif
70961.110Skamil#endif
70971.106Skamil
70981.106Skamil/// ----------------------------------------------------------------------------
70991.106Skamil
71001.106Skamil#if defined(TWAIT_HAVE_PID)
71011.103Skamilstatic void
71021.106Skamilclone_body2(int flags, bool masked, bool ignored)
71031.103Skamil{
71041.103Skamil	const int exitval = 5;
71051.103Skamil	const int exitval2 = 15;
71061.103Skamil	const int sigval = SIGSTOP;
71071.103Skamil	pid_t child, child2 = 0, wpid;
71081.103Skamil#if defined(TWAIT_HAVE_STATUS)
71091.103Skamil	int status;
71101.103Skamil#endif
71111.103Skamil	ptrace_state_t state;
71121.103Skamil	const int slen = sizeof(state);
71131.103Skamil	ptrace_event_t event;
71141.103Skamil	const int elen = sizeof(event);
71151.103Skamil	struct sigaction sa;
71161.103Skamil	struct ptrace_siginfo info;
71171.103Skamil	sigset_t intmask;
71181.103Skamil	struct kinfo_proc2 kp;
71191.103Skamil	size_t len = sizeof(kp);
71201.103Skamil
71211.103Skamil	int name[6];
71221.103Skamil	const size_t namelen = __arraycount(name);
71231.103Skamil	ki_sigset_t kp_sigmask;
71241.103Skamil	ki_sigset_t kp_sigignore;
71251.103Skamil
71261.103Skamil	const size_t stack_size = 1024 * 1024;
71271.103Skamil	void *stack, *stack_base;
71281.103Skamil
71291.103Skamil	stack = malloc(stack_size);
71301.103Skamil	ATF_REQUIRE(stack != NULL);
71311.103Skamil
71321.103Skamil#ifdef __MACHINE_STACK_GROWS_UP
71331.103Skamil	stack_base = stack;
71341.103Skamil#else
71351.103Skamil	stack_base = (char *)stack + stack_size;
71361.103Skamil#endif
71371.103Skamil
71381.103Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
71391.103Skamil	if (child == 0) {
71401.103Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
71411.103Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
71421.103Skamil
71431.103Skamil		if (masked) {
71441.103Skamil			sigemptyset(&intmask);
71451.103Skamil			sigaddset(&intmask, SIGTRAP);
71461.103Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
71471.103Skamil		}
71481.103Skamil
71491.103Skamil		if (ignored) {
71501.103Skamil			memset(&sa, 0, sizeof(sa));
71511.103Skamil			sa.sa_handler = SIG_IGN;
71521.103Skamil			sigemptyset(&sa.sa_mask);
71531.103Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
71541.103Skamil		}
71551.103Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
71561.103Skamil		FORKEE_ASSERT(raise(sigval) == 0);
71571.103Skamil
71581.103Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
71591.103Skamil		    flags);
71601.103Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
71611.103Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
71621.103Skamil
71631.103Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
71641.103Skamil		    child2);
71651.103Skamil
71661.103Skamil		// XXX WALLSIG?
71671.103Skamil		FORKEE_REQUIRE_SUCCESS
71681.103Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
71691.103Skamil
71701.103Skamil		forkee_status_exited(status, exitval2);
71711.103Skamil
71721.103Skamil		DPRINTF("Before exiting of the child process\n");
71731.103Skamil		_exit(exitval);
71741.103Skamil	}
71751.103Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
71761.103Skamil
71771.103Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
71781.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
71791.103Skamil
71801.103Skamil	validate_status_stopped(status, sigval);
71811.103Skamil
71821.103Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
71831.103Skamil	SYSCALL_REQUIRE(
71841.103Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
71851.103Skamil
71861.103Skamil	DPRINTF("Before checking siginfo_t\n");
71871.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
71881.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
71891.103Skamil
71901.103Skamil	name[0] = CTL_KERN,
71911.103Skamil	name[1] = KERN_PROC2,
71921.103Skamil	name[2] = KERN_PROC_PID;
71931.103Skamil	name[3] = child;
71941.103Skamil	name[4] = sizeof(kp);
71951.103Skamil	name[5] = 1;
71961.103Skamil
71971.103Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
71981.103Skamil
71991.103Skamil	if (masked)
72001.103Skamil		kp_sigmask = kp.p_sigmask;
72011.103Skamil
72021.103Skamil	if (ignored)
72031.103Skamil		kp_sigignore = kp.p_sigignore;
72041.103Skamil
72051.103Skamil	DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in "
72061.103Skamil	    "EVENT_MASK for the child %d\n", child);
72071.103Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
72081.103Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
72091.103Skamil
72101.103Skamil	DPRINTF("Before resuming the child process where it left off and "
72111.103Skamil	    "without signal to be sent\n");
72121.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
72131.103Skamil
72141.103Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
72151.103Skamil	    child);
72161.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
72171.103Skamil	    child);
72181.103Skamil
72191.103Skamil	validate_status_stopped(status, SIGTRAP);
72201.103Skamil
72211.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
72221.103Skamil
72231.103Skamil	if (masked) {
72241.103Skamil		DPRINTF("kp_sigmask="
72251.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72261.103Skamil		    PRIx32 "\n",
72271.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
72281.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
72291.103Skamil
72301.103Skamil		DPRINTF("kp.p_sigmask="
72311.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72321.103Skamil		    PRIx32 "\n",
72331.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
72341.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
72351.103Skamil
72361.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
72371.103Skamil		    sizeof(kp_sigmask)));
72381.103Skamil	}
72391.103Skamil
72401.103Skamil	if (ignored) {
72411.103Skamil		DPRINTF("kp_sigignore="
72421.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72431.103Skamil		    PRIx32 "\n",
72441.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
72451.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
72461.103Skamil
72471.103Skamil		DPRINTF("kp.p_sigignore="
72481.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72491.103Skamil		    PRIx32 "\n",
72501.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
72511.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
72521.103Skamil
72531.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
72541.103Skamil		    sizeof(kp_sigignore)));
72551.103Skamil	}
72561.103Skamil
72571.103Skamil	SYSCALL_REQUIRE(
72581.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
72591.103Skamil	DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event,
72601.103Skamil	    child2);
72611.103Skamil	if (!(flags & CLONE_VFORK)) {
72621.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
72631.103Skamil		       PTRACE_FORK);
72641.103Skamil	} else {
72651.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
72661.103Skamil		       PTRACE_VFORK);
72671.103Skamil	}
72681.103Skamil
72691.103Skamil	child2 = state.pe_other_pid;
72701.103Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
72711.103Skamil
72721.103Skamil	DPRINTF("Before calling %s() for the forkee %d of the child "
72731.103Skamil	    "%d\n", TWAIT_FNAME, child2, child);
72741.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
72751.103Skamil	    child2);
72761.103Skamil
72771.103Skamil	validate_status_stopped(status, SIGTRAP);
72781.103Skamil
72791.103Skamil	name[3] = child2;
72801.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
72811.103Skamil
72821.103Skamil	if (masked) {
72831.103Skamil		DPRINTF("kp_sigmask="
72841.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72851.103Skamil		    PRIx32 "\n",
72861.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
72871.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
72881.103Skamil
72891.103Skamil		DPRINTF("kp.p_sigmask="
72901.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72911.103Skamil		    PRIx32 "\n",
72921.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
72931.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
72941.103Skamil
72951.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
72961.103Skamil		    sizeof(kp_sigmask)));
72971.103Skamil	}
72981.103Skamil
72991.103Skamil	if (ignored) {
73001.103Skamil		DPRINTF("kp_sigignore="
73011.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73021.103Skamil		    PRIx32 "\n",
73031.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
73041.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
73051.103Skamil
73061.103Skamil		DPRINTF("kp.p_sigignore="
73071.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73081.103Skamil		    PRIx32 "\n",
73091.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
73101.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
73111.103Skamil
73121.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
73131.103Skamil		    sizeof(kp_sigignore)));
73141.103Skamil	}
73151.103Skamil
73161.103Skamil	SYSCALL_REQUIRE(
73171.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
73181.103Skamil	if (!(flags & CLONE_VFORK)) {
73191.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
73201.103Skamil		       PTRACE_FORK);
73211.103Skamil	} else {
73221.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
73231.103Skamil		       PTRACE_VFORK);
73241.103Skamil	}
73251.103Skamil
73261.103Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
73271.103Skamil
73281.103Skamil	DPRINTF("Before resuming the forkee process where it left off "
73291.103Skamil	    "and without signal to be sent\n");
73301.103Skamil	SYSCALL_REQUIRE(
73311.103Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
73321.103Skamil
73331.103Skamil	DPRINTF("Before resuming the child process where it left off "
73341.103Skamil	    "and without signal to be sent\n");
73351.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
73361.103Skamil
73371.103Skamil	if (flags & CLONE_VFORK) {
73381.103Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
73391.103Skamil		    child);
73401.103Skamil		TWAIT_REQUIRE_SUCCESS(
73411.103Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
73421.103Skamil
73431.103Skamil		validate_status_stopped(status, SIGTRAP);
73441.103Skamil
73451.103Skamil		name[3] = child;
73461.103Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
73471.103Skamil
73481.103Skamil		/*
73491.103Skamil		 * SIGCHLD is now pending in the signal queue and
73501.103Skamil		 * the kernel presents it to userland as a masked signal.
73511.103Skamil		 */
73521.103Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
73531.103Skamil
73541.103Skamil		if (masked) {
73551.103Skamil			DPRINTF("kp_sigmask="
73561.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73571.103Skamil			    PRIx32 "\n",
73581.103Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
73591.103Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
73601.103Skamil
73611.103Skamil			DPRINTF("kp.p_sigmask="
73621.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73631.103Skamil			    PRIx32 "\n",
73641.103Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
73651.103Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
73661.103Skamil
73671.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
73681.103Skamil			    sizeof(kp_sigmask)));
73691.103Skamil		}
73701.103Skamil
73711.103Skamil		if (ignored) {
73721.103Skamil			DPRINTF("kp_sigignore="
73731.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73741.103Skamil			    PRIx32 "\n",
73751.103Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
73761.103Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
73771.103Skamil
73781.103Skamil			DPRINTF("kp.p_sigignore="
73791.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73801.103Skamil			    PRIx32 "\n",
73811.103Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
73821.103Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
73831.103Skamil
73841.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
73851.103Skamil			    sizeof(kp_sigignore)));
73861.103Skamil		}
73871.103Skamil
73881.103Skamil		SYSCALL_REQUIRE(
73891.103Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
73901.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
73911.103Skamil
73921.103Skamil		child2 = state.pe_other_pid;
73931.103Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
73941.103Skamil		    child2);
73951.103Skamil
73961.103Skamil		DPRINTF("Before resuming the child process where it left off "
73971.103Skamil		    "and without signal to be sent\n");
73981.103Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
73991.103Skamil	}
74001.103Skamil
74011.103Skamil	DPRINTF("Before calling %s() for the forkee - expected exited"
74021.103Skamil	    "\n", TWAIT_FNAME);
74031.103Skamil	TWAIT_REQUIRE_SUCCESS(
74041.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
74051.103Skamil
74061.103Skamil	validate_status_exited(status, exitval2);
74071.103Skamil
74081.103Skamil	DPRINTF("Before calling %s() for the forkee - expected no "
74091.103Skamil	    "process\n", TWAIT_FNAME);
74101.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
74111.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
74121.103Skamil
74131.103Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
74141.103Skamil	    "SIGCHLD\n", TWAIT_FNAME);
74151.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
74161.103Skamil
74171.103Skamil	validate_status_stopped(status, SIGCHLD);
74181.103Skamil
74191.103Skamil	DPRINTF("Before resuming the child process where it left off and "
74201.103Skamil	    "without signal to be sent\n");
74211.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
74221.103Skamil
74231.103Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
74241.103Skamil	    TWAIT_FNAME);
74251.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
74261.103Skamil
74271.103Skamil	validate_status_exited(status, exitval);
74281.103Skamil
74291.103Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
74301.103Skamil	    TWAIT_FNAME);
74311.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
74321.103Skamil}
74331.103Skamil
74341.106Skamil#define CLONE_TEST2(name,flags,masked,ignored)				\
74351.103SkamilATF_TC(name);								\
74361.103SkamilATF_TC_HEAD(name, tc)							\
74371.103Skamil{									\
74381.103Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\
74391.103Skamil	    " regardless of signal %s%s", 				\
74401.103Skamil	    #flags, masked ? "masked" : "", ignored ? "ignored" : "");	\
74411.103Skamil}									\
74421.103Skamil									\
74431.103SkamilATF_TC_BODY(name, tc)							\
74441.103Skamil{									\
74451.103Skamil									\
74461.106Skamil	clone_body2(flags, masked, ignored);				\
74471.103Skamil}
74481.103Skamil
74491.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false)
74501.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true)
74511.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false)
74521.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true)
74531.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false)
74541.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true)
74551.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false)
74561.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true)
74571.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX
74581.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true)  // XXX
74591.110Skamil#if TEST_VFORK_ENABLED
74601.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false)
74611.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true)
74621.103Skamil#endif
74631.110Skamil#endif
74641.103Skamil
74651.103Skamil/// ----------------------------------------------------------------------------
74661.103Skamil
74671.111Skamil#if TEST_VFORK_ENABLED
74681.107Skamil#if defined(TWAIT_HAVE_PID)
74691.107Skamilstatic void
74701.107Skamiltraceme_vfork_clone_body(int flags)
74711.107Skamil{
74721.107Skamil	const int exitval = 5;
74731.107Skamil	const int exitval2 = 15;
74741.107Skamil	pid_t child, child2 = 0, wpid;
74751.107Skamil#if defined(TWAIT_HAVE_STATUS)
74761.107Skamil	int status;
74771.107Skamil#endif
74781.107Skamil
74791.107Skamil	const size_t stack_size = 1024 * 1024;
74801.107Skamil	void *stack, *stack_base;
74811.107Skamil
74821.107Skamil	stack = malloc(stack_size);
74831.107Skamil	ATF_REQUIRE(stack != NULL);
74841.107Skamil
74851.107Skamil#ifdef __MACHINE_STACK_GROWS_UP
74861.107Skamil	stack_base = stack;
74871.107Skamil#else
74881.107Skamil	stack_base = (char *)stack + stack_size;
74891.107Skamil#endif
74901.107Skamil
74911.107Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
74921.107Skamil	if (child == 0) {
74931.107Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
74941.107Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
74951.107Skamil
74961.107Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
74971.107Skamil		    flags);
74981.107Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
74991.107Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
75001.107Skamil
75011.107Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
75021.107Skamil		    child2);
75031.107Skamil
75041.107Skamil		// XXX WALLSIG?
75051.107Skamil		FORKEE_REQUIRE_SUCCESS
75061.107Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
75071.107Skamil
75081.107Skamil		forkee_status_exited(status, exitval2);
75091.107Skamil
75101.107Skamil		DPRINTF("Before exiting of the child process\n");
75111.107Skamil		_exit(exitval);
75121.107Skamil	}
75131.107Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
75141.107Skamil
75151.107Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
75161.107Skamil	    TWAIT_FNAME);
75171.107Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
75181.107Skamil
75191.107Skamil	validate_status_exited(status, exitval);
75201.107Skamil
75211.107Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
75221.107Skamil	    TWAIT_FNAME);
75231.107Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
75241.107Skamil}
75251.107Skamil
75261.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags)				\
75271.107SkamilATF_TC(name);								\
75281.107SkamilATF_TC_HEAD(name, tc)							\
75291.107Skamil{									\
75301.107Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is "	\
75311.107Skamil	    "handled correctly with vfork(2)ed tracer", 		\
75321.107Skamil	    #flags);							\
75331.107Skamil}									\
75341.107Skamil									\
75351.107SkamilATF_TC_BODY(name, tc)							\
75361.107Skamil{									\
75371.107Skamil									\
75381.107Skamil	traceme_vfork_clone_body(flags);				\
75391.107Skamil}
75401.107Skamil
75411.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0)
75421.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM)
75431.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS)
75441.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES)
75451.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND)  // XXX
75461.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK)
75471.107Skamil#endif
75481.110Skamil#endif
75491.107Skamil
75501.107Skamil/// ----------------------------------------------------------------------------
75511.107Skamil
75521.122Skamilstatic void
75531.122Skamiluser_va0_disable(int operation)
75541.122Skamil{
75551.122Skamil	pid_t child, wpid;
75561.122Skamil#if defined(TWAIT_HAVE_STATUS)
75571.122Skamil	int status;
75581.122Skamil#endif
75591.122Skamil	const int sigval = SIGSTOP;
75601.122Skamil	int rv;
75611.122Skamil
75621.122Skamil	struct ptrace_siginfo info;
75631.122Skamil
75641.122Skamil	if (get_user_va0_disable() == 0)
75651.122Skamil		atf_tc_skip("vm.user_va0_disable is set to 0");
75661.122Skamil
75671.122Skamil	memset(&info, 0, sizeof(info));
75681.122Skamil
75691.122Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
75701.122Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
75711.122Skamil	if (child == 0) {
75721.122Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
75731.122Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
75741.122Skamil
75751.122Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
75761.122Skamil		FORKEE_ASSERT(raise(sigval) == 0);
75771.122Skamil
75781.122Skamil		/* NOTREACHED */
75791.122Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
75801.122Skamil		__unreachable();
75811.122Skamil	}
75821.122Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
75831.122Skamil
75841.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
75851.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
75861.122Skamil
75871.122Skamil	validate_status_stopped(status, sigval);
75881.122Skamil
75891.122Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
75901.122Skamil		"child\n");
75911.122Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
75921.122Skamil		sizeof(info)) != -1);
75931.122Skamil
75941.122Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
75951.122Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
75961.122Skamil		"si_errno=%#x\n",
75971.122Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
75981.122Skamil		info.psi_siginfo.si_errno);
75991.122Skamil
76001.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
76011.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
76021.122Skamil
76031.122Skamil	DPRINTF("Before resuming the child process in PC=0x0 "
76041.122Skamil	    "and without signal to be sent\n");
76051.122Skamil	errno = 0;
76061.122Skamil	rv = ptrace(operation, child, (void *)0, 0);
76071.122Skamil	ATF_REQUIRE_EQ(errno, EINVAL);
76081.122Skamil	ATF_REQUIRE_EQ(rv, -1);
76091.122Skamil
76101.122Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
76111.122Skamil
76121.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
76131.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
76141.122Skamil	validate_status_signaled(status, SIGKILL, 0);
76151.122Skamil
76161.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
76171.122Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
76181.122Skamil}
76191.122Skamil
76201.122Skamil#define USER_VA0_DISABLE(test, operation)				\
76211.122SkamilATF_TC(test);								\
76221.122SkamilATF_TC_HEAD(test, tc)							\
76231.122Skamil{									\
76241.122Skamil	atf_tc_set_md_var(tc, "descr",					\
76251.122Skamil	    "Verify behavior of " #operation " with PC set to 0x0");	\
76261.122Skamil}									\
76271.122Skamil									\
76281.122SkamilATF_TC_BODY(test, tc)							\
76291.122Skamil{									\
76301.122Skamil									\
76311.122Skamil	user_va0_disable(operation);					\
76321.122Skamil}
76331.122Skamil
76341.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE)
76351.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL)
76361.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH)
76371.122Skamil
76381.122Skamil/// ----------------------------------------------------------------------------
76391.122Skamil
76401.1Skamil#include "t_ptrace_amd64_wait.h"
76411.1Skamil#include "t_ptrace_i386_wait.h"
76421.1Skamil#include "t_ptrace_x86_wait.h"
76431.1Skamil
76441.1SkamilATF_TP_ADD_TCS(tp)
76451.1Skamil{
76461.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
76471.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
76481.33Skamil
76491.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
76501.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
76511.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
76521.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
76531.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
76541.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
76551.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
76561.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
76571.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
76581.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
76591.33Skamil
76601.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
76611.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
76621.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
76631.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
76641.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
76651.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
76661.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
76671.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
76681.87Skamil
76691.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
76701.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
76711.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
76721.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
76731.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
76741.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
76751.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
76761.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
76771.86Skamil
76781.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
76791.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
76801.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
76811.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
76821.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
76831.59Skamil
76841.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
76851.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
76861.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
76871.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
76881.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
76891.88Skamil
76901.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
76911.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
76921.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
76931.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
76941.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
76951.88Skamil
76961.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
76971.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
76981.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
76991.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
77001.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
77011.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
77021.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
77031.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
77041.50Skamil
77051.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
77061.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
77071.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
77081.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
77091.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
77101.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
77111.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
77121.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
77131.50Skamil
77141.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
77151.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
77161.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
77171.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
77181.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
77191.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
77201.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
77211.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
77221.50Skamil
77231.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
77241.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
77251.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
77261.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
77271.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
77281.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
77291.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
77301.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
77311.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
77321.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
77331.1Skamil
77341.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
77351.37Skamil
77361.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
77371.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
77381.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
77391.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
77401.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
77411.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
77421.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
77431.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
77441.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
77451.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
77461.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
77471.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
77481.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
77491.40Skamil
77501.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
77511.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
77521.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
77531.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
77541.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
77551.41Skamil
77561.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
77571.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
77581.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
77591.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
77601.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
77611.92Skamil
77621.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
77631.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
77641.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
77651.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
77661.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
77671.92Skamil
77681.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
77691.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
77701.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
77711.43Skamil
77721.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
77731.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
77741.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
77751.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
77761.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
77771.59Skamil
77781.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77791.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
77801.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77811.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
77821.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77831.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
77841.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77851.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
77861.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77871.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
77881.94Skamil
77891.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77901.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
77911.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77921.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
77931.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77941.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
77951.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77961.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
77971.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
77981.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
77991.94Skamil
78001.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
78011.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
78021.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
78031.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
78041.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
78051.51Skamil
78061.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
78071.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
78081.51Skamil
78091.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
78101.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
78111.51Skamil
78121.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
78131.51Skamil		tracee_sees_its_original_parent_getppid);
78141.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
78151.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
78161.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
78171.51Skamil		tracee_sees_its_original_parent_procfs_status);
78181.1Skamil
78191.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
78201.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
78211.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
78221.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
78231.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
78241.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
78251.125Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn);
78261.1Skamil
78271.31Skamil	ATF_TP_ADD_TC(tp, fork1);
78281.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
78291.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
78301.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
78311.31Skamil	ATF_TP_ADD_TC(tp, fork5);
78321.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
78331.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
78341.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
78351.125Skamil	ATF_TP_ADD_TC(tp, fork9);
78361.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork10);
78371.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork11);
78381.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork12);
78391.125Skamil	ATF_TP_ADD_TC(tp, fork13);
78401.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork14);
78411.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork15);
78421.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork16);
78431.31Skamil
78441.109Skamil#if TEST_VFORK_ENABLED
78451.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
78461.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
78471.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
78481.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
78491.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
78501.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
78511.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
78521.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
78531.125Skamil	ATF_TP_ADD_TC(tp, vfork9);
78541.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork10);
78551.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork11);
78561.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork12);
78571.125Skamil	ATF_TP_ADD_TC(tp, vfork13);
78581.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork14);
78591.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork15);
78601.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork16);
78611.116Skamil#endif
78621.1Skamil
78631.124Skamil	ATF_TP_ADD_TC(tp, posix_spawn1);
78641.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn2);
78651.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn3);
78661.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn4);
78671.124Skamil	ATF_TP_ADD_TC(tp, posix_spawn5);
78681.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn6);
78691.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn7);
78701.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn8);
78711.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9);
78721.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10);
78731.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11);
78741.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12);
78751.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13);
78761.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14);
78771.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15);
78781.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16);
78791.124Skamil
78801.126Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner);
78811.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker);
78821.116Skamil#if TEST_VFORK_ENABLED
78831.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker);
78841.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone);
78851.116Skamil#endif
78861.126Skamil
78871.126Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner);
78881.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker);
78891.116Skamil#if TEST_VFORK_ENABLED
78901.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker);
78911.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone);
78921.116Skamil#endif
78931.116Skamil
78941.116Skamil#if TEST_VFORK_ENABLED
78951.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_fork);
78961.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_vfork);
78971.109Skamil#endif
78981.108Skamil
78991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
79001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
79011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
79021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
79031.54Skamil
79041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
79051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
79061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
79071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
79081.54Skamil
79091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
79101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
79111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
79121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
79131.54Skamil
79141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
79151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
79161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
79171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
79181.54Skamil
79191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
79201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
79211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
79221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
79231.54Skamil
79241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
79251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
79261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
79271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
79281.54Skamil
79291.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
79301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
79311.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
79321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
79331.54Skamil
79341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
79351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
79361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
79371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
79381.54Skamil
79391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
79401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
79411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
79421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
79431.54Skamil
79441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
79451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
79461.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
79471.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
79481.1Skamil
79491.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
79501.1Skamil
79511.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i);
79521.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d);
79531.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i);
79541.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d);
79551.101Skamil
79561.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i);
79571.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d);
79581.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i);
79591.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d);
79601.101Skamil
79611.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv);
79621.101Skamil
79631.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i);
79641.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d);
79651.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i);
79661.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d);
79671.115Skamil
79681.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i);
79691.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d);
79701.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i);
79711.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d);
79721.115Skamil
79731.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
79741.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
79751.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
79761.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
79771.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
79781.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
79791.1Skamil
79801.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
79811.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
79821.1Skamil
79831.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
79841.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
79851.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
79861.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
79871.1Skamil
79881.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
79891.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
79901.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
79911.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
79921.2Skamil
79931.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
79941.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
79951.95Skamil
79961.1Skamil	ATF_TP_ADD_TC(tp, kill1);
79971.1Skamil	ATF_TP_ADD_TC(tp, kill2);
79981.75Skamil	ATF_TP_ADD_TC(tp, kill3);
79991.1Skamil
80001.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
80011.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
80021.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
80031.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
80041.77Skamil
80051.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
80061.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
80071.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
80081.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
80091.1Skamil
80101.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
80111.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
80121.79Skamil
80131.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
80141.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
80151.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
80161.1Skamil
80171.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_nolwpevents);
80181.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpexit);
80191.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate);
80201.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit);
80211.1Skamil
80221.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
80231.84Skamil
80241.126Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked);
80251.126Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored);
80261.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
80271.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
80281.109Skamil#if TEST_VFORK_ENABLED
80291.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
80301.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
80311.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
80321.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
80331.109Skamil#endif
80341.99Skamil
80351.1Skamil	ATF_TP_ADD_TC(tp, signal9);
80361.1Skamil	ATF_TP_ADD_TC(tp, signal10);
80371.1Skamil
80381.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
80391.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
80401.1Skamil
80411.1Skamil	ATF_TP_ADD_TC(tp, resume1);
80421.1Skamil
80431.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
80441.1Skamil
80451.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
80461.1Skamil
80471.106Skamil	ATF_TP_ADD_TC(tp, clone1);
80481.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone2);
80491.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone3);
80501.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone4);
80511.106Skamil	ATF_TP_ADD_TC(tp, clone5);
80521.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone6);
80531.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone7);
80541.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone8);
80551.106Skamil
80561.106Skamil	ATF_TP_ADD_TC(tp, clone_vm1);
80571.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2);
80581.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3);
80591.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4);
80601.106Skamil	ATF_TP_ADD_TC(tp, clone_vm5);
80611.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6);
80621.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7);
80631.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8);
80641.106Skamil
80651.106Skamil	ATF_TP_ADD_TC(tp, clone_fs1);
80661.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2);
80671.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3);
80681.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4);
80691.106Skamil	ATF_TP_ADD_TC(tp, clone_fs5);
80701.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6);
80711.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7);
80721.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8);
80731.106Skamil
80741.106Skamil	ATF_TP_ADD_TC(tp, clone_files1);
80751.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2);
80761.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3);
80771.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4);
80781.106Skamil	ATF_TP_ADD_TC(tp, clone_files5);
80791.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6);
80801.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7);
80811.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8);
80821.106Skamil
80831.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand1); // XXX
80841.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX
80851.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX
80861.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX
80871.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand5); // XXX
80881.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX
80891.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX
80901.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX
80911.106Skamil
80921.109Skamil#if TEST_VFORK_ENABLED
80931.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork1);
80941.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2);
80951.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3);
80961.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4);
80971.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork5);
80981.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6);
80991.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7);
81001.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8);
81011.109Skamil#endif
81021.106Skamil
81031.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored);
81041.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked);
81051.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored);
81061.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked);
81071.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored);
81081.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked);
81091.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored);
81101.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked);
81111.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX
81121.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX
81131.109Skamil#if TEST_VFORK_ENABLED
81141.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored);
81151.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked);
81161.109Skamil#endif
81171.103Skamil
81181.109Skamil#if TEST_VFORK_ENABLED
81191.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone);
81201.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm);
81211.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs);
81221.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files);
81231.107Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX
81241.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork);
81251.109Skamil#endif
81261.107Skamil
81271.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue);
81281.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall);
81291.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach);
81301.122Skamil
81311.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
81321.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
81331.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
81341.1Skamil
81351.1Skamil	return atf_no_error();
81361.1Skamil}
8137