t_ptrace_wait.c revision 1.115
11.115Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.115 2019/04/30 22:39:31 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.115Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.115 2019/04/30 22:39:31 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.1Skamil#include <stdint.h>
501.1Skamil#include <stdio.h>
511.1Skamil#include <stdlib.h>
521.1Skamil#include <strings.h>
531.26Skamil#include <time.h>
541.1Skamil#include <unistd.h>
551.1Skamil
561.114Skamil#include <fenv.h>
571.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__
581.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
591.114Skamil#endif
601.114Skamil
611.1Skamil#include <atf-c.h>
621.1Skamil
631.1Skamil#include "h_macros.h"
641.1Skamil
651.1Skamil#include "t_ptrace_wait.h"
661.1Skamil#include "msg.h"
671.1Skamil
681.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
691.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
701.61Skre	sizeof(msg)) == 0)
711.1Skamil
721.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
731.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
741.61Skre	sizeof(msg)) == 0)
751.1Skamil
761.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
771.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
781.61Skre	sizeof(msg)) == 0)
791.1Skamil
801.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
811.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
821.61Skre	sizeof(msg)) == 0)
831.13Schristos
841.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
851.13Schristos    strerror(errno))
861.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
871.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
881.13Schristos
891.13Schristosstatic int debug = 0;
901.13Schristos
911.13Schristos#define DPRINTF(a, ...)	do  \
921.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
931.13Schristos    while (/*CONSTCOND*/0)
941.1Skamil
951.110Skamil#ifndef TEST_VFORK_ENABLED
961.109Skamil#define TEST_VFORK_ENABLED 0
971.110Skamil#endif
981.109Skamil
991.34Skamil/// ----------------------------------------------------------------------------
1001.34Skamil
1011.33Skamilstatic void
1021.33Skamiltraceme_raise(int sigval)
1031.1Skamil{
1041.1Skamil	const int exitval = 5;
1051.1Skamil	pid_t child, wpid;
1061.1Skamil#if defined(TWAIT_HAVE_STATUS)
1071.1Skamil	int status;
1081.1Skamil#endif
1091.1Skamil
1101.45Skamil	struct ptrace_siginfo info;
1111.45Skamil	memset(&info, 0, sizeof(info));
1121.45Skamil
1131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1151.1Skamil	if (child == 0) {
1161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1181.1Skamil
1191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1211.1Skamil
1221.36Skamil		switch (sigval) {
1231.36Skamil		case SIGKILL:
1241.36Skamil			/* NOTREACHED */
1251.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1261.70Smrg			__unreachable();
1271.36Skamil		default:
1281.36Skamil			DPRINTF("Before exiting of the child process\n");
1291.36Skamil			_exit(exitval);
1301.36Skamil		}
1311.1Skamil	}
1321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1331.1Skamil
1341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1361.1Skamil
1371.36Skamil	switch (sigval) {
1381.36Skamil	case SIGKILL:
1391.36Skamil		validate_status_signaled(status, sigval, 0);
1401.36Skamil		break;
1411.36Skamil	default:
1421.36Skamil		validate_status_stopped(status, sigval);
1431.1Skamil
1441.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1451.61Skre			"child\n");
1461.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1471.61Skre			sizeof(info)) != -1);
1481.45Skamil
1491.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1501.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1511.61Skre			"si_errno=%#x\n",
1521.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1531.61Skre			info.psi_siginfo.si_errno);
1541.45Skamil
1551.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1561.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1571.45Skamil
1581.36Skamil		DPRINTF("Before resuming the child process where it left off "
1591.36Skamil		    "and without signal to be sent\n");
1601.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1611.1Skamil
1621.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1631.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1641.61Skre		    child);
1651.36Skamil		break;
1661.36Skamil	}
1671.1Skamil
1681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1701.1Skamil}
1711.1Skamil
1721.61Skre#define TRACEME_RAISE(test, sig)					\
1731.61SkreATF_TC(test);								\
1741.61SkreATF_TC_HEAD(test, tc)							\
1751.61Skre{									\
1761.61Skre	atf_tc_set_md_var(tc, "descr",					\
1771.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1781.61Skre}									\
1791.61Skre									\
1801.61SkreATF_TC_BODY(test, tc)							\
1811.61Skre{									\
1821.61Skre									\
1831.61Skre	traceme_raise(sig);						\
1841.33Skamil}
1851.33Skamil
1861.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1871.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1881.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1891.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1901.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1911.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1921.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1931.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1941.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
1951.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
1961.33Skamil
1971.34Skamil/// ----------------------------------------------------------------------------
1981.1Skamil
1991.1Skamilstatic void
2001.87Skamiltraceme_raisesignal_ignored(int sigignored)
2011.87Skamil{
2021.87Skamil	const int exitval = 5;
2031.87Skamil	const int sigval = SIGSTOP;
2041.87Skamil	pid_t child, wpid;
2051.87Skamil	struct sigaction sa;
2061.87Skamil#if defined(TWAIT_HAVE_STATUS)
2071.87Skamil	int status;
2081.87Skamil#endif
2091.87Skamil	struct ptrace_siginfo info;
2101.87Skamil
2111.87Skamil	memset(&info, 0, sizeof(info));
2121.87Skamil
2131.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2141.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2151.87Skamil	if (child == 0) {
2161.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2171.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2181.87Skamil
2191.87Skamil		memset(&sa, 0, sizeof(sa));
2201.87Skamil		sa.sa_handler = SIG_IGN;
2211.87Skamil		sigemptyset(&sa.sa_mask);
2221.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2231.87Skamil
2241.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2251.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2261.87Skamil
2271.87Skamil		DPRINTF("Before raising %s from child\n",
2281.87Skamil		    strsignal(sigignored));
2291.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2301.87Skamil
2311.87Skamil		DPRINTF("Before exiting of the child process\n");
2321.87Skamil		_exit(exitval);
2331.87Skamil	}
2341.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2351.87Skamil
2361.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2371.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2381.87Skamil
2391.87Skamil	validate_status_stopped(status, sigval);
2401.87Skamil
2411.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2421.87Skamil	SYSCALL_REQUIRE(
2431.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2441.87Skamil
2451.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2461.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2471.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2481.87Skamil	    info.psi_siginfo.si_errno);
2491.87Skamil
2501.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2511.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2521.87Skamil
2531.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2541.87Skamil	    "without signal to be sent\n");
2551.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2561.87Skamil
2571.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2581.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2591.87Skamil
2601.87Skamil	validate_status_stopped(status, sigignored);
2611.87Skamil
2621.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2631.87Skamil	SYSCALL_REQUIRE(
2641.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2651.87Skamil
2661.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2671.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2681.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2691.87Skamil	    info.psi_siginfo.si_errno);
2701.87Skamil
2711.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2721.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2731.87Skamil
2741.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2751.87Skamil	    "without signal to be sent\n");
2761.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2771.87Skamil
2781.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2791.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2801.87Skamil
2811.87Skamil	validate_status_exited(status, exitval);
2821.87Skamil
2831.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2841.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2851.87Skamil}
2861.87Skamil
2871.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2881.87SkamilATF_TC(test);								\
2891.87SkamilATF_TC_HEAD(test, tc)							\
2901.87Skamil{									\
2911.87Skamil	atf_tc_set_md_var(tc, "descr",					\
2921.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
2931.87Skamil	    "does not stop tracer from catching this raised signal");	\
2941.87Skamil}									\
2951.87Skamil									\
2961.87SkamilATF_TC_BODY(test, tc)							\
2971.87Skamil{									\
2981.87Skamil									\
2991.87Skamil	traceme_raisesignal_ignored(sig);				\
3001.87Skamil}
3011.87Skamil
3021.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
3031.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
3041.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
3051.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
3061.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
3071.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
3081.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3091.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3101.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3111.87Skamil
3121.87Skamil/// ----------------------------------------------------------------------------
3131.87Skamil
3141.87Skamilstatic void
3151.86Skamiltraceme_raisesignal_masked(int sigmasked)
3161.86Skamil{
3171.86Skamil	const int exitval = 5;
3181.86Skamil	const int sigval = SIGSTOP;
3191.86Skamil	pid_t child, wpid;
3201.86Skamil#if defined(TWAIT_HAVE_STATUS)
3211.86Skamil	int status;
3221.86Skamil#endif
3231.86Skamil	sigset_t intmask;
3241.86Skamil	struct ptrace_siginfo info;
3251.86Skamil
3261.86Skamil	memset(&info, 0, sizeof(info));
3271.86Skamil
3281.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3291.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3301.86Skamil	if (child == 0) {
3311.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3321.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3331.86Skamil
3341.86Skamil		sigemptyset(&intmask);
3351.86Skamil		sigaddset(&intmask, sigmasked);
3361.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3371.86Skamil
3381.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3391.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3401.86Skamil
3411.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3421.86Skamil		    strsignal(sigmasked));
3431.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3441.86Skamil
3451.86Skamil		DPRINTF("Before exiting of the child process\n");
3461.86Skamil		_exit(exitval);
3471.86Skamil	}
3481.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3491.86Skamil
3501.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3511.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3521.86Skamil
3531.86Skamil	validate_status_stopped(status, sigval);
3541.86Skamil
3551.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3561.86Skamil	SYSCALL_REQUIRE(
3571.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3581.86Skamil
3591.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3601.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3611.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3621.86Skamil	    info.psi_siginfo.si_errno);
3631.86Skamil
3641.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3651.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3661.86Skamil
3671.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3681.86Skamil	    "without signal to be sent\n");
3691.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3701.86Skamil
3711.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3721.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3731.86Skamil
3741.86Skamil	validate_status_exited(status, exitval);
3751.86Skamil
3761.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3771.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3781.86Skamil}
3791.86Skamil
3801.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3811.86SkamilATF_TC(test);								\
3821.86SkamilATF_TC_HEAD(test, tc)							\
3831.86Skamil{									\
3841.86Skamil	atf_tc_set_md_var(tc, "descr",					\
3851.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3861.86Skamil	    "stops tracer from catching this raised signal");		\
3871.86Skamil}									\
3881.86Skamil									\
3891.86SkamilATF_TC_BODY(test, tc)							\
3901.86Skamil{									\
3911.86Skamil									\
3921.86Skamil	traceme_raisesignal_masked(sig);				\
3931.86Skamil}
3941.86Skamil
3951.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
3961.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
3971.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
3981.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
3991.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
4001.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
4011.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
4021.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
4031.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
4041.86Skamil
4051.86Skamil/// ----------------------------------------------------------------------------
4061.86Skamil
4071.86Skamilstatic void
4081.59Skamiltraceme_crash(int sig)
4091.59Skamil{
4101.59Skamil	pid_t child, wpid;
4111.59Skamil#if defined(TWAIT_HAVE_STATUS)
4121.59Skamil	int status;
4131.59Skamil#endif
4141.59Skamil	struct ptrace_siginfo info;
4151.61Skre
4161.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4171.71Skamil	if (sig == SIGILL)
4181.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4191.71Skamil#endif
4201.71Skamil
4211.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
4221.114Skamil		atf_tc_skip("FP exceptions are not supported");
4231.114Skamil
4241.59Skamil	memset(&info, 0, sizeof(info));
4251.59Skamil
4261.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4271.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4281.59Skamil	if (child == 0) {
4291.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4301.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4311.59Skamil
4321.59Skamil		DPRINTF("Before executing a trap\n");
4331.59Skamil		switch (sig) {
4341.59Skamil		case SIGTRAP:
4351.59Skamil			trigger_trap();
4361.59Skamil			break;
4371.59Skamil		case SIGSEGV:
4381.59Skamil			trigger_segv();
4391.59Skamil			break;
4401.59Skamil		case SIGILL:
4411.59Skamil			trigger_ill();
4421.59Skamil			break;
4431.59Skamil		case SIGFPE:
4441.59Skamil			trigger_fpe();
4451.59Skamil			break;
4461.59Skamil		case SIGBUS:
4471.59Skamil			trigger_bus();
4481.59Skamil			break;
4491.59Skamil		default:
4501.59Skamil			/* NOTREACHED */
4511.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4521.59Skamil		}
4531.59Skamil
4541.59Skamil		/* NOTREACHED */
4551.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4561.59Skamil	}
4571.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4581.59Skamil
4591.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4601.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4611.59Skamil
4621.59Skamil	validate_status_stopped(status, sig);
4631.59Skamil
4641.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4651.61Skre	SYSCALL_REQUIRE(
4661.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4671.59Skamil
4681.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4691.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4701.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4711.61Skre	    info.psi_siginfo.si_errno);
4721.59Skamil
4731.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4741.59Skamil	switch (sig) {
4751.59Skamil	case SIGTRAP:
4761.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4771.59Skamil		break;
4781.59Skamil	case SIGSEGV:
4791.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4801.59Skamil		break;
4811.71Skamil	case SIGILL:
4821.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
4831.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
4841.71Skamil		break;
4851.59Skamil	case SIGFPE:
4861.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4871.59Skamil		break;
4881.59Skamil	case SIGBUS:
4891.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
4901.59Skamil		break;
4911.59Skamil	}
4921.59Skamil
4931.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
4941.59Skamil
4951.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4961.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4971.59Skamil
4981.59Skamil	validate_status_signaled(status, SIGKILL, 0);
4991.59Skamil
5001.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5011.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5021.59Skamil}
5031.59Skamil
5041.61Skre#define TRACEME_CRASH(test, sig)					\
5051.61SkreATF_TC(test);								\
5061.61SkreATF_TC_HEAD(test, tc)							\
5071.61Skre{									\
5081.61Skre	atf_tc_set_md_var(tc, "descr",					\
5091.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
5101.61Skre}									\
5111.61Skre									\
5121.61SkreATF_TC_BODY(test, tc)							\
5131.61Skre{									\
5141.61Skre									\
5151.61Skre	traceme_crash(sig);						\
5161.59Skamil}
5171.59Skamil
5181.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5191.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5201.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5211.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5221.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5231.59Skamil
5241.59Skamil/// ----------------------------------------------------------------------------
5251.59Skamil
5261.59Skamilstatic void
5271.88Skamiltraceme_signalmasked_crash(int sig)
5281.88Skamil{
5291.89Skamil	const int sigval = SIGSTOP;
5301.88Skamil	pid_t child, wpid;
5311.88Skamil#if defined(TWAIT_HAVE_STATUS)
5321.88Skamil	int status;
5331.88Skamil#endif
5341.88Skamil	struct ptrace_siginfo info;
5351.88Skamil	sigset_t intmask;
5361.89Skamil	struct kinfo_proc2 kp;
5371.89Skamil	size_t len = sizeof(kp);
5381.89Skamil
5391.89Skamil	int name[6];
5401.89Skamil	const size_t namelen = __arraycount(name);
5411.89Skamil	ki_sigset_t kp_sigmask;
5421.88Skamil
5431.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5441.88Skamil	if (sig == SIGILL)
5451.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5461.88Skamil#endif
5471.88Skamil
5481.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
5491.114Skamil		atf_tc_skip("FP exceptions are not supported");
5501.114Skamil
5511.88Skamil	memset(&info, 0, sizeof(info));
5521.88Skamil
5531.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5541.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5551.88Skamil	if (child == 0) {
5561.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5571.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5581.88Skamil
5591.88Skamil		sigemptyset(&intmask);
5601.88Skamil		sigaddset(&intmask, sig);
5611.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5621.88Skamil
5631.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5641.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5651.89Skamil
5661.88Skamil		DPRINTF("Before executing a trap\n");
5671.88Skamil		switch (sig) {
5681.88Skamil		case SIGTRAP:
5691.88Skamil			trigger_trap();
5701.88Skamil			break;
5711.88Skamil		case SIGSEGV:
5721.88Skamil			trigger_segv();
5731.88Skamil			break;
5741.88Skamil		case SIGILL:
5751.88Skamil			trigger_ill();
5761.88Skamil			break;
5771.88Skamil		case SIGFPE:
5781.88Skamil			trigger_fpe();
5791.88Skamil			break;
5801.88Skamil		case SIGBUS:
5811.88Skamil			trigger_bus();
5821.88Skamil			break;
5831.88Skamil		default:
5841.88Skamil			/* NOTREACHED */
5851.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5861.88Skamil		}
5871.88Skamil
5881.88Skamil		/* NOTREACHED */
5891.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5901.88Skamil	}
5911.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5921.88Skamil
5931.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5941.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5951.88Skamil
5961.89Skamil	validate_status_stopped(status, sigval);
5971.89Skamil
5981.89Skamil	name[0] = CTL_KERN,
5991.89Skamil	name[1] = KERN_PROC2,
6001.89Skamil	name[2] = KERN_PROC_PID;
6011.89Skamil	name[3] = child;
6021.89Skamil	name[4] = sizeof(kp);
6031.89Skamil	name[5] = 1;
6041.89Skamil
6051.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6061.89Skamil
6071.89Skamil	kp_sigmask = kp.p_sigmask;
6081.89Skamil
6091.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6101.89Skamil	SYSCALL_REQUIRE(
6111.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6121.89Skamil
6131.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6141.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6151.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6161.89Skamil	    info.psi_siginfo.si_errno);
6171.89Skamil
6181.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6191.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6201.89Skamil
6211.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6221.89Skamil	    "without signal to be sent\n");
6231.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6241.89Skamil
6251.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6261.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6271.89Skamil
6281.88Skamil	validate_status_stopped(status, sig);
6291.88Skamil
6301.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6311.88Skamil	SYSCALL_REQUIRE(
6321.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6331.88Skamil
6341.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6351.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6361.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6371.88Skamil	    info.psi_siginfo.si_errno);
6381.88Skamil
6391.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6401.89Skamil
6411.89Skamil	DPRINTF("kp_sigmask="
6421.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6431.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6441.89Skamil	    kp_sigmask.__bits[3]);
6451.89Skamil
6461.89Skamil	DPRINTF("kp.p_sigmask="
6471.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6481.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6491.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6501.89Skamil
6511.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6521.89Skamil
6531.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6541.88Skamil	switch (sig) {
6551.88Skamil	case SIGTRAP:
6561.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6571.88Skamil		break;
6581.88Skamil	case SIGSEGV:
6591.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6601.88Skamil		break;
6611.88Skamil	case SIGILL:
6621.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
6631.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
6641.88Skamil		break;
6651.88Skamil	case SIGFPE:
6661.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6671.88Skamil		break;
6681.88Skamil	case SIGBUS:
6691.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6701.88Skamil		break;
6711.88Skamil	}
6721.88Skamil
6731.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6741.88Skamil
6751.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6761.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6771.88Skamil
6781.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6791.88Skamil
6801.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6811.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6821.88Skamil}
6831.88Skamil
6841.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6851.88SkamilATF_TC(test);								\
6861.88SkamilATF_TC_HEAD(test, tc)							\
6871.88Skamil{									\
6881.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6891.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6901.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6911.88Skamil}									\
6921.88Skamil									\
6931.88SkamilATF_TC_BODY(test, tc)							\
6941.88Skamil{									\
6951.88Skamil									\
6961.88Skamil	traceme_signalmasked_crash(sig);				\
6971.88Skamil}
6981.88Skamil
6991.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
7001.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
7011.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
7021.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
7031.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
7041.88Skamil
7051.88Skamil/// ----------------------------------------------------------------------------
7061.88Skamil
7071.88Skamilstatic void
7081.88Skamiltraceme_signalignored_crash(int sig)
7091.88Skamil{
7101.90Skamil	const int sigval = SIGSTOP;
7111.88Skamil	pid_t child, wpid;
7121.88Skamil#if defined(TWAIT_HAVE_STATUS)
7131.88Skamil	int status;
7141.88Skamil#endif
7151.88Skamil	struct sigaction sa;
7161.88Skamil	struct ptrace_siginfo info;
7171.90Skamil	struct kinfo_proc2 kp;
7181.90Skamil	size_t len = sizeof(kp);
7191.90Skamil
7201.90Skamil	int name[6];
7211.90Skamil	const size_t namelen = __arraycount(name);
7221.90Skamil	ki_sigset_t kp_sigignore;
7231.88Skamil
7241.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7251.88Skamil	if (sig == SIGILL)
7261.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7271.88Skamil#endif
7281.88Skamil
7291.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
7301.114Skamil		atf_tc_skip("FP exceptions are not supported");
7311.114Skamil
7321.88Skamil	memset(&info, 0, sizeof(info));
7331.88Skamil
7341.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7351.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7361.88Skamil	if (child == 0) {
7371.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7381.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7391.88Skamil
7401.88Skamil		memset(&sa, 0, sizeof(sa));
7411.88Skamil		sa.sa_handler = SIG_IGN;
7421.88Skamil		sigemptyset(&sa.sa_mask);
7431.88Skamil
7441.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7451.88Skamil
7461.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7471.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7481.90Skamil
7491.88Skamil		DPRINTF("Before executing a trap\n");
7501.88Skamil		switch (sig) {
7511.88Skamil		case SIGTRAP:
7521.88Skamil			trigger_trap();
7531.88Skamil			break;
7541.88Skamil		case SIGSEGV:
7551.88Skamil			trigger_segv();
7561.88Skamil			break;
7571.88Skamil		case SIGILL:
7581.88Skamil			trigger_ill();
7591.88Skamil			break;
7601.88Skamil		case SIGFPE:
7611.88Skamil			trigger_fpe();
7621.88Skamil			break;
7631.88Skamil		case SIGBUS:
7641.88Skamil			trigger_bus();
7651.88Skamil			break;
7661.88Skamil		default:
7671.88Skamil			/* NOTREACHED */
7681.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7691.88Skamil		}
7701.88Skamil
7711.88Skamil		/* NOTREACHED */
7721.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7731.88Skamil	}
7741.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7751.88Skamil
7761.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7771.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7781.88Skamil
7791.90Skamil	validate_status_stopped(status, sigval);
7801.90Skamil
7811.90Skamil	name[0] = CTL_KERN,
7821.90Skamil	name[1] = KERN_PROC2,
7831.90Skamil	name[2] = KERN_PROC_PID;
7841.90Skamil	name[3] = child;
7851.90Skamil	name[4] = sizeof(kp);
7861.90Skamil	name[5] = 1;
7871.90Skamil
7881.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
7891.90Skamil
7901.90Skamil	kp_sigignore = kp.p_sigignore;
7911.90Skamil
7921.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7931.90Skamil	SYSCALL_REQUIRE(
7941.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7951.90Skamil
7961.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7971.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7981.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7991.90Skamil	    info.psi_siginfo.si_errno);
8001.90Skamil
8011.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8021.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
8031.90Skamil
8041.90Skamil	DPRINTF("Before resuming the child process where it left off and "
8051.90Skamil	    "without signal to be sent\n");
8061.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8071.90Skamil
8081.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8091.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8101.90Skamil
8111.88Skamil	validate_status_stopped(status, sig);
8121.88Skamil
8131.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
8141.88Skamil	SYSCALL_REQUIRE(
8151.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8161.88Skamil
8171.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8181.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8191.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8201.88Skamil	    info.psi_siginfo.si_errno);
8211.88Skamil
8221.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8231.90Skamil
8241.90Skamil	DPRINTF("kp_sigignore="
8251.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8261.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8271.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8281.90Skamil
8291.90Skamil	DPRINTF("kp.p_sigignore="
8301.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8311.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8321.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8331.90Skamil
8341.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8351.90Skamil
8361.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8371.88Skamil	switch (sig) {
8381.88Skamil	case SIGTRAP:
8391.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8401.88Skamil		break;
8411.88Skamil	case SIGSEGV:
8421.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8431.88Skamil		break;
8441.88Skamil	case SIGILL:
8451.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
8461.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
8471.88Skamil		break;
8481.88Skamil	case SIGFPE:
8491.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8501.88Skamil		break;
8511.88Skamil	case SIGBUS:
8521.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8531.88Skamil		break;
8541.88Skamil	}
8551.88Skamil
8561.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8571.88Skamil
8581.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8591.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8601.88Skamil
8611.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8621.88Skamil
8631.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8641.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8651.88Skamil}
8661.88Skamil
8671.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8681.88SkamilATF_TC(test);								\
8691.88SkamilATF_TC_HEAD(test, tc)							\
8701.88Skamil{									\
8711.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8721.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8731.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8741.88Skamil}									\
8751.88Skamil									\
8761.88SkamilATF_TC_BODY(test, tc)							\
8771.88Skamil{									\
8781.88Skamil									\
8791.88Skamil	traceme_signalignored_crash(sig);				\
8801.88Skamil}
8811.88Skamil
8821.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8831.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8841.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8851.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8861.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8871.88Skamil
8881.88Skamil/// ----------------------------------------------------------------------------
8891.88Skamil
8901.88Skamilstatic void
8911.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
8921.1Skamil{
8931.1Skamil	const int exitval = 5;
8941.34Skamil	const int sigval = SIGSTOP;
8951.1Skamil	pid_t child, wpid;
8961.1Skamil	struct sigaction sa;
8971.1Skamil#if defined(TWAIT_HAVE_STATUS)
8981.1Skamil	int status;
8991.1Skamil#endif
9001.61Skre	struct ptrace_siginfo info;
9011.1Skamil
9021.45Skamil	memset(&info, 0, sizeof(info));
9031.45Skamil
9041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
9051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
9061.1Skamil	if (child == 0) {
9071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9091.1Skamil
9101.34Skamil		sa.sa_handler = sah;
9111.1Skamil		sa.sa_flags = SA_SIGINFO;
9121.1Skamil		sigemptyset(&sa.sa_mask);
9131.1Skamil
9141.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
9151.1Skamil
9161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9181.1Skamil
9191.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9201.1Skamil
9211.13Schristos		DPRINTF("Before exiting of the child process\n");
9221.1Skamil		_exit(exitval);
9231.1Skamil	}
9241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9251.1Skamil
9261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9281.1Skamil
9291.1Skamil	validate_status_stopped(status, sigval);
9301.1Skamil
9311.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9321.61Skre	SYSCALL_REQUIRE(
9331.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9341.45Skamil
9351.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9361.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9371.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9381.45Skamil	    info.psi_siginfo.si_errno);
9391.45Skamil
9401.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9411.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9421.45Skamil
9431.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9441.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9461.1Skamil
9471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9491.1Skamil
9501.1Skamil	validate_status_exited(status, exitval);
9511.1Skamil
9521.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9531.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9541.1Skamil}
9551.1Skamil
9561.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9571.61SkreATF_TC(test);								\
9581.61SkreATF_TC_HEAD(test, tc)							\
9591.61Skre{									\
9601.61Skre	atf_tc_set_md_var(tc, "descr",					\
9611.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9621.61Skre	    "handled correctly and caught by a signal handler");	\
9631.61Skre}									\
9641.61Skre									\
9651.61Skrestatic int test##_caught = 0;						\
9661.61Skre									\
9671.61Skrestatic void								\
9681.61Skretest##_sighandler(int arg)						\
9691.61Skre{									\
9701.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9711.61Skre									\
9721.61Skre	++ test##_caught;						\
9731.61Skre}									\
9741.61Skre									\
9751.61SkreATF_TC_BODY(test, tc)							\
9761.61Skre{									\
9771.61Skre									\
9781.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9791.34Skamil}
9801.34Skamil
9811.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9821.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9831.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9841.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9851.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9861.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9871.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9881.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
9891.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
9901.34Skamil
9911.34Skamil/// ----------------------------------------------------------------------------
9921.34Skamil
9931.35Skamilstatic void
9941.50Skamiltraceme_sendsignal_masked(int sigsent)
9951.50Skamil{
9961.50Skamil	const int exitval = 5;
9971.50Skamil	const int sigval = SIGSTOP;
9981.50Skamil	pid_t child, wpid;
9991.50Skamil	sigset_t set;
10001.50Skamil#if defined(TWAIT_HAVE_STATUS)
10011.50Skamil	int status;
10021.50Skamil#endif
10031.61Skre	struct ptrace_siginfo info;
10041.50Skamil
10051.50Skamil	memset(&info, 0, sizeof(info));
10061.50Skamil
10071.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10081.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10091.50Skamil	if (child == 0) {
10101.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10111.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10121.50Skamil
10131.50Skamil		sigemptyset(&set);
10141.50Skamil		sigaddset(&set, sigsent);
10151.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
10161.50Skamil
10171.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10181.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10191.50Skamil
10201.50Skamil		_exit(exitval);
10211.50Skamil	}
10221.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10231.50Skamil
10241.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10251.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10261.50Skamil
10271.50Skamil	validate_status_stopped(status, sigval);
10281.50Skamil
10291.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10301.61Skre	SYSCALL_REQUIRE(
10311.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10321.50Skamil
10331.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10341.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10351.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10361.50Skamil	    info.psi_siginfo.si_errno);
10371.50Skamil
10381.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10391.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10401.50Skamil
10411.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10421.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10431.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10441.50Skamil
10451.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10461.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10471.50Skamil
10481.50Skamil	validate_status_exited(status, exitval);
10491.50Skamil
10501.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10511.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10521.50Skamil}
10531.50Skamil
10541.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10551.61SkreATF_TC(test);								\
10561.61SkreATF_TC_HEAD(test, tc)							\
10571.61Skre{									\
10581.61Skre	atf_tc_set_md_var(tc, "descr",					\
10591.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10601.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10611.61Skre}									\
10621.61Skre									\
10631.61SkreATF_TC_BODY(test, tc)							\
10641.61Skre{									\
10651.61Skre									\
10661.61Skre	traceme_sendsignal_masked(sig);					\
10671.50Skamil}
10681.50Skamil
10691.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10701.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10711.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10721.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10731.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10741.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10751.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10761.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10771.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10781.50Skamil
10791.50Skamil/// ----------------------------------------------------------------------------
10801.50Skamil
10811.50Skamilstatic void
10821.50Skamiltraceme_sendsignal_ignored(int sigsent)
10831.50Skamil{
10841.50Skamil	const int exitval = 5;
10851.50Skamil	const int sigval = SIGSTOP;
10861.50Skamil	pid_t child, wpid;
10871.50Skamil	struct sigaction sa;
10881.50Skamil#if defined(TWAIT_HAVE_STATUS)
10891.50Skamil	int status;
10901.50Skamil#endif
10911.61Skre	struct ptrace_siginfo info;
10921.50Skamil
10931.50Skamil	memset(&info, 0, sizeof(info));
10941.50Skamil
10951.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10961.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10971.50Skamil	if (child == 0) {
10981.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10991.61Skre
11001.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11011.50Skamil
11021.50Skamil		memset(&sa, 0, sizeof(sa));
11031.50Skamil		sa.sa_handler = SIG_IGN;
11041.50Skamil		sigemptyset(&sa.sa_mask);
11051.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
11061.50Skamil
11071.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11081.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11091.50Skamil
11101.50Skamil		_exit(exitval);
11111.50Skamil	}
11121.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11131.50Skamil
11141.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11151.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11161.50Skamil
11171.50Skamil	validate_status_stopped(status, sigval);
11181.50Skamil
11191.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11201.61Skre	SYSCALL_REQUIRE(
11211.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11221.50Skamil
11231.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11241.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11251.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11261.50Skamil	    info.psi_siginfo.si_errno);
11271.50Skamil
11281.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11291.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11301.50Skamil
11311.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11321.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11331.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11341.50Skamil
11351.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11361.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11371.50Skamil
11381.50Skamil	validate_status_exited(status, exitval);
11391.50Skamil
11401.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11411.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11421.50Skamil}
11431.50Skamil
11441.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11451.61SkreATF_TC(test);								\
11461.61SkreATF_TC_HEAD(test, tc)							\
11471.61Skre{									\
11481.61Skre	atf_tc_set_md_var(tc, "descr",					\
11491.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11501.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11511.61Skre}									\
11521.61Skre									\
11531.61SkreATF_TC_BODY(test, tc)							\
11541.61Skre{									\
11551.61Skre									\
11561.61Skre	traceme_sendsignal_ignored(sig);				\
11571.50Skamil}
11581.50Skamil
11591.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11601.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11611.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11621.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11631.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11641.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11651.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11661.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11671.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11681.50Skamil
11691.50Skamil/// ----------------------------------------------------------------------------
11701.50Skamil
11711.50Skamilstatic void
11721.50Skamiltraceme_sendsignal_simple(int sigsent)
11731.1Skamil{
11741.35Skamil	const int sigval = SIGSTOP;
11751.35Skamil	int exitval = 0;
11761.1Skamil	pid_t child, wpid;
11771.1Skamil#if defined(TWAIT_HAVE_STATUS)
11781.1Skamil	int status;
11791.85Skamil	int expect_core;
11801.85Skamil
11811.85Skamil	switch (sigsent) {
11821.85Skamil	case SIGABRT:
11831.85Skamil	case SIGTRAP:
11841.85Skamil	case SIGBUS:
11851.85Skamil	case SIGILL:
11861.85Skamil	case SIGFPE:
11871.85Skamil	case SIGSEGV:
11881.85Skamil		expect_core = 1;
11891.85Skamil		break;
11901.85Skamil	default:
11911.85Skamil		expect_core = 0;
11921.85Skamil		break;
11931.85Skamil	}
11941.1Skamil#endif
11951.61Skre	struct ptrace_siginfo info;
11961.1Skamil
11971.45Skamil	memset(&info, 0, sizeof(info));
11981.45Skamil
11991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12011.1Skamil	if (child == 0) {
12021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12041.1Skamil
12051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12071.1Skamil
12081.35Skamil		switch (sigsent) {
12091.35Skamil		case SIGCONT:
12101.48Skamil		case SIGSTOP:
12111.35Skamil			_exit(exitval);
12121.35Skamil		default:
12131.35Skamil			/* NOTREACHED */
12141.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
12151.35Skamil		}
12161.1Skamil	}
12171.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12181.1Skamil
12191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12211.1Skamil
12221.1Skamil	validate_status_stopped(status, sigval);
12231.1Skamil
12241.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12251.61Skre	SYSCALL_REQUIRE(
12261.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12271.45Skamil
12281.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12291.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12301.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12311.45Skamil	    info.psi_siginfo.si_errno);
12321.45Skamil
12331.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12341.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12351.45Skamil
12361.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12371.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12391.1Skamil
12401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12421.1Skamil
12431.35Skamil	switch (sigsent) {
12441.48Skamil	case SIGSTOP:
12451.48Skamil		validate_status_stopped(status, sigsent);
12461.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12471.61Skre		    "child\n");
12481.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12491.61Skre		    sizeof(info)) != -1);
12501.48Skamil
12511.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12521.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12531.61Skre		    "si_errno=%#x\n",
12541.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12551.61Skre		    info.psi_siginfo.si_errno);
12561.48Skamil
12571.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12581.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12591.48Skamil
12601.48Skamil		DPRINTF("Before resuming the child process where it left off "
12611.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12621.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12631.48Skamil
12641.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12651.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12661.61Skre		    child);
12671.48Skamil		/* FALLTHROUGH */
12681.35Skamil	case SIGCONT:
12691.35Skamil		validate_status_exited(status, exitval);
12701.35Skamil		break;
12711.35Skamil	default:
12721.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12731.35Skamil		break;
12741.35Skamil	}
12751.1Skamil
12761.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12781.1Skamil}
12791.1Skamil
12801.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12811.61SkreATF_TC(test);								\
12821.61SkreATF_TC_HEAD(test, tc)							\
12831.61Skre{									\
12841.61Skre	atf_tc_set_md_var(tc, "descr",					\
12851.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12861.61Skre	    "handled correctly in a child without a signal handler");	\
12871.61Skre}									\
12881.61Skre									\
12891.61SkreATF_TC_BODY(test, tc)							\
12901.61Skre{									\
12911.61Skre									\
12921.61Skre	traceme_sendsignal_simple(sig);					\
12931.35Skamil}
12941.35Skamil
12951.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
12961.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
12971.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
12981.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
12991.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
13001.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
13011.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
13021.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
13031.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
13041.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
13051.35Skamil
13061.35Skamil/// ----------------------------------------------------------------------------
13071.35Skamil
13081.37SkamilATF_TC(traceme_pid1_parent);
13091.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
13101.37Skamil{
13111.37Skamil	atf_tc_set_md_var(tc, "descr",
13121.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
13131.37Skamil}
13141.37Skamil
13151.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
13161.37Skamil{
13171.37Skamil	struct msg_fds parent_child;
13181.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13191.37Skamil	pid_t child1, child2, wpid;
13201.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13211.37Skamil#if defined(TWAIT_HAVE_STATUS)
13221.37Skamil	int status;
13231.37Skamil#endif
13241.37Skamil
13251.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13261.37Skamil
13271.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13281.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13291.37Skamil	if (child1 == 0) {
13301.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13311.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13321.37Skamil		if (child2 != 0) {
13331.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13341.61Skre			    getpid(), child2);
13351.37Skamil			_exit(exitval_child1);
13361.37Skamil		}
13371.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13381.37Skamil
13391.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13401.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13411.37Skamil
13421.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13431.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13441.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13451.37Skamil
13461.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13471.37Skamil
13481.37Skamil		_exit(exitval_child2);
13491.37Skamil	}
13501.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13511.37Skamil
13521.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13531.61Skre	TWAIT_REQUIRE_SUCCESS(
13541.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13551.37Skamil
13561.37Skamil	validate_status_exited(status, exitval_child1);
13571.37Skamil
13581.37Skamil	DPRINTF("Notify that child1 is dead\n");
13591.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13601.37Skamil
13611.37Skamil	DPRINTF("Wait for exiting of child2\n");
13621.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13631.37Skamil}
13641.37Skamil
13651.37Skamil/// ----------------------------------------------------------------------------
13661.37Skamil
13671.40Skamilstatic void
13681.40Skamiltraceme_vfork_raise(int sigval)
13691.40Skamil{
13701.46Skamil	const int exitval = 5, exitval_watcher = 10;
13711.46Skamil	pid_t child, parent, watcher, wpid;
13721.46Skamil	int rv;
13731.40Skamil#if defined(TWAIT_HAVE_STATUS)
13741.40Skamil	int status;
13751.85Skamil
13761.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13771.85Skamil	volatile int expect_core;
13781.85Skamil
13791.85Skamil	switch (sigval) {
13801.85Skamil	case SIGABRT:
13811.85Skamil	case SIGTRAP:
13821.85Skamil	case SIGBUS:
13831.85Skamil	case SIGILL:
13841.85Skamil	case SIGFPE:
13851.85Skamil	case SIGSEGV:
13861.85Skamil		expect_core = 1;
13871.85Skamil		break;
13881.85Skamil	default:
13891.85Skamil		expect_core = 0;
13901.85Skamil		break;
13911.85Skamil	}
13921.40Skamil#endif
13931.40Skamil
13941.46Skamil	/*
13951.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
13961.46Skamil	 * the SIGKILL signal to it.
13971.46Skamil	 *
13981.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
13991.46Skamil	 * simpler to reparent this process to initproc and forget about it.
14001.46Skamil	 */
14011.46Skamil	if (sigval == SIGSTOP) {
14021.46Skamil		parent = getpid();
14031.46Skamil
14041.46Skamil		watcher = fork();
14051.46Skamil		ATF_REQUIRE(watcher != 1);
14061.46Skamil		if (watcher == 0) {
14071.46Skamil			/* Double fork(2) trick to reparent to initproc */
14081.46Skamil			watcher = fork();
14091.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
14101.46Skamil			if (watcher != 0)
14111.46Skamil				_exit(exitval_watcher);
14121.46Skamil
14131.46Skamil			child = await_stopped_child(parent);
14141.46Skamil
14151.46Skamil			errno = 0;
14161.46Skamil			rv = kill(child, SIGKILL);
14171.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
14181.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14191.46Skamil
14201.46Skamil			/* This exit value will be collected by initproc */
14211.46Skamil			_exit(0);
14221.46Skamil		}
14231.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14241.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14251.61Skre		    watcher);
14261.46Skamil
14271.46Skamil		validate_status_exited(status, exitval_watcher);
14281.46Skamil
14291.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14301.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14311.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14321.46Skamil	}
14331.46Skamil
14341.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14351.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14361.40Skamil	if (child == 0) {
14371.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14381.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14391.40Skamil
14401.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14411.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14421.40Skamil
14431.40Skamil		switch (sigval) {
14441.46Skamil		case SIGSTOP:
14451.40Skamil		case SIGKILL:
14461.40Skamil		case SIGABRT:
14471.40Skamil		case SIGHUP:
14481.85Skamil		case SIGTRAP:
14491.85Skamil		case SIGBUS:
14501.85Skamil		case SIGILL:
14511.85Skamil		case SIGFPE:
14521.85Skamil		case SIGSEGV:
14531.40Skamil			/* NOTREACHED */
14541.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14551.70Smrg			__unreachable();
14561.40Skamil		default:
14571.40Skamil			DPRINTF("Before exiting of the child process\n");
14581.40Skamil			_exit(exitval);
14591.40Skamil		}
14601.40Skamil	}
14611.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14621.40Skamil
14631.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14641.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14651.40Skamil
14661.40Skamil	switch (sigval) {
14671.40Skamil	case SIGKILL:
14681.40Skamil	case SIGABRT:
14691.40Skamil	case SIGHUP:
14701.85Skamil	case SIGTRAP:
14711.85Skamil	case SIGBUS:
14721.85Skamil	case SIGILL:
14731.85Skamil	case SIGFPE:
14741.85Skamil	case SIGSEGV:
14751.40Skamil		validate_status_signaled(status, sigval, expect_core);
14761.40Skamil		break;
14771.40Skamil	case SIGSTOP:
14781.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14791.46Skamil		break;
14801.40Skamil	case SIGCONT:
14811.47Skamil	case SIGTSTP:
14821.47Skamil	case SIGTTIN:
14831.47Skamil	case SIGTTOU:
14841.40Skamil		validate_status_exited(status, exitval);
14851.40Skamil		break;
14861.40Skamil	default:
14871.40Skamil		/* NOTREACHED */
14881.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
14891.40Skamil		break;
14901.40Skamil	}
14911.40Skamil
14921.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14931.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14941.40Skamil}
14951.40Skamil
14961.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
14971.61SkreATF_TC(test);								\
14981.61SkreATF_TC_HEAD(test, tc)							\
14991.61Skre{									\
15001.61Skre	atf_tc_set_md_var(tc, "descr",					\
15011.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
15021.61Skre	    "vfork(2)ed child");					\
15031.61Skre}									\
15041.61Skre									\
15051.61SkreATF_TC_BODY(test, tc)							\
15061.61Skre{									\
15071.61Skre									\
15081.61Skre	traceme_vfork_raise(sig);					\
15091.40Skamil}
15101.40Skamil
15111.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
15121.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
15131.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
15141.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
15151.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
15161.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
15171.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
15181.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15191.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15201.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15211.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15221.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15231.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15241.40Skamil
15251.40Skamil/// ----------------------------------------------------------------------------
15261.40Skamil
15271.52Skamilstatic void
15281.52Skamiltraceme_vfork_crash(int sig)
15291.41Skamil{
15301.41Skamil	pid_t child, wpid;
15311.41Skamil#if defined(TWAIT_HAVE_STATUS)
15321.41Skamil	int status;
15331.41Skamil#endif
15341.41Skamil
15351.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15361.71Skamil	if (sig == SIGILL)
15371.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15381.71Skamil#endif
15391.71Skamil
15401.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
15411.114Skamil		atf_tc_skip("FP exceptions are not supported");
15421.114Skamil
15431.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15441.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15451.41Skamil	if (child == 0) {
15461.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15471.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15481.41Skamil
15491.52Skamil		DPRINTF("Before executing a trap\n");
15501.52Skamil		switch (sig) {
15511.52Skamil		case SIGTRAP:
15521.52Skamil			trigger_trap();
15531.52Skamil			break;
15541.52Skamil		case SIGSEGV:
15551.52Skamil			trigger_segv();
15561.52Skamil			break;
15571.52Skamil		case SIGILL:
15581.52Skamil			trigger_ill();
15591.52Skamil			break;
15601.52Skamil		case SIGFPE:
15611.52Skamil			trigger_fpe();
15621.52Skamil			break;
15631.52Skamil		case SIGBUS:
15641.52Skamil			trigger_bus();
15651.52Skamil			break;
15661.52Skamil		default:
15671.52Skamil			/* NOTREACHED */
15681.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15691.52Skamil		}
15701.41Skamil
15711.41Skamil		/* NOTREACHED */
15721.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15731.41Skamil	}
15741.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15751.41Skamil
15761.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15771.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15781.41Skamil
15791.52Skamil	validate_status_signaled(status, sig, 1);
15801.41Skamil
15811.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15821.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15831.41Skamil}
15841.41Skamil
15851.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15861.61SkreATF_TC(test);								\
15871.61SkreATF_TC_HEAD(test, tc)							\
15881.61Skre{									\
15891.61Skre	atf_tc_set_md_var(tc, "descr",					\
15901.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
15911.61Skre	    "vfork(2)ed child");					\
15921.61Skre}									\
15931.61Skre									\
15941.61SkreATF_TC_BODY(test, tc)							\
15951.61Skre{									\
15961.61Skre									\
15971.61Skre	traceme_vfork_crash(sig);					\
15981.52Skamil}
15991.52Skamil
16001.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
16011.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
16021.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
16031.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
16041.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
16051.52Skamil
16061.41Skamil/// ----------------------------------------------------------------------------
16071.41Skamil
16081.92Skamilstatic void
16091.92Skamiltraceme_vfork_signalmasked_crash(int sig)
16101.92Skamil{
16111.92Skamil	pid_t child, wpid;
16121.92Skamil#if defined(TWAIT_HAVE_STATUS)
16131.92Skamil	int status;
16141.92Skamil#endif
16151.92Skamil	sigset_t intmask;
16161.92Skamil
16171.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16181.92Skamil	if (sig == SIGILL)
16191.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16201.92Skamil#endif
16211.92Skamil
16221.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
16231.114Skamil		atf_tc_skip("FP exceptions are not supported");
16241.114Skamil
16251.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16261.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16271.92Skamil	if (child == 0) {
16281.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16291.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16301.92Skamil
16311.92Skamil		sigemptyset(&intmask);
16321.92Skamil		sigaddset(&intmask, sig);
16331.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16341.92Skamil
16351.92Skamil		DPRINTF("Before executing a trap\n");
16361.92Skamil		switch (sig) {
16371.92Skamil		case SIGTRAP:
16381.92Skamil			trigger_trap();
16391.92Skamil			break;
16401.92Skamil		case SIGSEGV:
16411.92Skamil			trigger_segv();
16421.92Skamil			break;
16431.92Skamil		case SIGILL:
16441.92Skamil			trigger_ill();
16451.92Skamil			break;
16461.92Skamil		case SIGFPE:
16471.92Skamil			trigger_fpe();
16481.92Skamil			break;
16491.92Skamil		case SIGBUS:
16501.92Skamil			trigger_bus();
16511.92Skamil			break;
16521.92Skamil		default:
16531.92Skamil			/* NOTREACHED */
16541.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16551.92Skamil		}
16561.92Skamil
16571.92Skamil		/* NOTREACHED */
16581.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16591.92Skamil	}
16601.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16611.92Skamil
16621.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16631.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16641.92Skamil
16651.92Skamil	validate_status_signaled(status, sig, 1);
16661.92Skamil
16671.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16681.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16691.92Skamil}
16701.92Skamil
16711.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16721.92SkamilATF_TC(test);								\
16731.92SkamilATF_TC_HEAD(test, tc)							\
16741.92Skamil{									\
16751.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16761.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16771.92Skamil	    "vfork(2)ed child with a masked signal");			\
16781.92Skamil}									\
16791.92Skamil									\
16801.92SkamilATF_TC_BODY(test, tc)							\
16811.92Skamil{									\
16821.92Skamil									\
16831.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16841.92Skamil}
16851.92Skamil
16861.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16871.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16881.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
16891.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
16901.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
16911.92Skamil
16921.92Skamil/// ----------------------------------------------------------------------------
16931.92Skamil
16941.92Skamilstatic void
16951.92Skamiltraceme_vfork_signalignored_crash(int sig)
16961.92Skamil{
16971.92Skamil	pid_t child, wpid;
16981.92Skamil#if defined(TWAIT_HAVE_STATUS)
16991.92Skamil	int status;
17001.92Skamil#endif
17011.92Skamil	struct sigaction sa;
17021.92Skamil
17031.92Skamil#ifndef PTRACE_ILLEGAL_ASM
17041.92Skamil	if (sig == SIGILL)
17051.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
17061.92Skamil#endif
17071.92Skamil
17081.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
17091.114Skamil		atf_tc_skip("FP exceptions are not supported");
17101.114Skamil
17111.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17121.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17131.92Skamil	if (child == 0) {
17141.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17151.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17161.92Skamil
17171.92Skamil		memset(&sa, 0, sizeof(sa));
17181.92Skamil		sa.sa_handler = SIG_IGN;
17191.92Skamil		sigemptyset(&sa.sa_mask);
17201.92Skamil
17211.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
17221.92Skamil
17231.92Skamil		DPRINTF("Before executing a trap\n");
17241.92Skamil		switch (sig) {
17251.92Skamil		case SIGTRAP:
17261.92Skamil			trigger_trap();
17271.92Skamil			break;
17281.92Skamil		case SIGSEGV:
17291.92Skamil			trigger_segv();
17301.92Skamil			break;
17311.92Skamil		case SIGILL:
17321.92Skamil			trigger_ill();
17331.92Skamil			break;
17341.92Skamil		case SIGFPE:
17351.92Skamil			trigger_fpe();
17361.92Skamil			break;
17371.92Skamil		case SIGBUS:
17381.92Skamil			trigger_bus();
17391.92Skamil			break;
17401.92Skamil		default:
17411.92Skamil			/* NOTREACHED */
17421.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17431.92Skamil		}
17441.92Skamil
17451.92Skamil		/* NOTREACHED */
17461.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17471.92Skamil	}
17481.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17491.92Skamil
17501.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17511.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17521.92Skamil
17531.92Skamil	validate_status_signaled(status, sig, 1);
17541.92Skamil
17551.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17561.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17571.92Skamil}
17581.92Skamil
17591.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17601.92SkamilATF_TC(test);								\
17611.92SkamilATF_TC_HEAD(test, tc)							\
17621.92Skamil{									\
17631.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17641.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17651.92Skamil	    "vfork(2)ed child with ignored signal");			\
17661.92Skamil}									\
17671.92Skamil									\
17681.92SkamilATF_TC_BODY(test, tc)							\
17691.92Skamil{									\
17701.92Skamil									\
17711.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17721.92Skamil}
17731.92Skamil
17741.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17751.92Skamil    SIGTRAP)
17761.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17771.92Skamil    SIGSEGV)
17781.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17791.92Skamil    SIGILL)
17801.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17811.92Skamil    SIGFPE)
17821.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17831.92Skamil    SIGBUS)
17841.92Skamil
17851.92Skamil/// ----------------------------------------------------------------------------
17861.92Skamil
17871.96Skamilstatic void
17881.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
17891.43Skamil{
17901.43Skamil	const int sigval = SIGTRAP;
17911.43Skamil	pid_t child, wpid;
17921.43Skamil#if defined(TWAIT_HAVE_STATUS)
17931.43Skamil	int status;
17941.43Skamil#endif
17951.96Skamil	struct sigaction sa;
17961.61Skre	struct ptrace_siginfo info;
17971.96Skamil	sigset_t intmask;
17981.96Skamil	struct kinfo_proc2 kp;
17991.96Skamil	size_t len = sizeof(kp);
18001.96Skamil
18011.96Skamil	int name[6];
18021.96Skamil	const size_t namelen = __arraycount(name);
18031.96Skamil	ki_sigset_t kp_sigmask;
18041.96Skamil	ki_sigset_t kp_sigignore;
18051.43Skamil
18061.43Skamil	memset(&info, 0, sizeof(info));
18071.43Skamil
18081.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
18091.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
18101.43Skamil	if (child == 0) {
18111.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18121.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18131.43Skamil
18141.96Skamil		if (masked) {
18151.96Skamil			sigemptyset(&intmask);
18161.96Skamil			sigaddset(&intmask, sigval);
18171.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
18181.96Skamil		}
18191.96Skamil
18201.96Skamil		if (ignored) {
18211.96Skamil			memset(&sa, 0, sizeof(sa));
18221.96Skamil			sa.sa_handler = SIG_IGN;
18231.96Skamil			sigemptyset(&sa.sa_mask);
18241.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
18251.96Skamil		}
18261.96Skamil
18271.43Skamil		DPRINTF("Before calling execve(2) from child\n");
18281.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
18291.43Skamil
18301.43Skamil		/* NOTREACHED */
18311.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18321.43Skamil	}
18331.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18341.43Skamil
18351.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18361.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18371.43Skamil
18381.43Skamil	validate_status_stopped(status, sigval);
18391.43Skamil
18401.96Skamil	name[0] = CTL_KERN,
18411.96Skamil	name[1] = KERN_PROC2,
18421.96Skamil	name[2] = KERN_PROC_PID;
18431.96Skamil	name[3] = getpid();
18441.96Skamil	name[4] = sizeof(kp);
18451.96Skamil	name[5] = 1;
18461.96Skamil
18471.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18481.96Skamil
18491.96Skamil	if (masked)
18501.96Skamil		kp_sigmask = kp.p_sigmask;
18511.96Skamil
18521.96Skamil	if (ignored)
18531.96Skamil		kp_sigignore = kp.p_sigignore;
18541.96Skamil
18551.96Skamil	name[3] = getpid();
18561.96Skamil
18571.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18581.96Skamil
18591.96Skamil	if (masked) {
18601.96Skamil		DPRINTF("kp_sigmask="
18611.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18621.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18631.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18641.96Skamil
18651.96Skamil	        DPRINTF("kp.p_sigmask="
18661.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18671.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18681.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18691.96Skamil
18701.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18711.96Skamil		    sizeof(kp_sigmask)));
18721.96Skamil	}
18731.96Skamil
18741.96Skamil	if (ignored) {
18751.96Skamil		DPRINTF("kp_sigignore="
18761.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18771.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18781.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18791.96Skamil
18801.96Skamil	        DPRINTF("kp.p_sigignore="
18811.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18821.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
18831.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
18841.96Skamil
18851.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
18861.96Skamil		    sizeof(kp_sigignore)));
18871.96Skamil	}
18881.96Skamil
18891.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
18901.61Skre	SYSCALL_REQUIRE(
18911.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
18921.43Skamil
18931.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
18941.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
18951.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
18961.43Skamil	    info.psi_siginfo.si_errno);
18971.43Skamil
18981.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
18991.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
19001.43Skamil
19011.43Skamil	DPRINTF("Before resuming the child process where it left off and "
19021.43Skamil	    "without signal to be sent\n");
19031.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19041.43Skamil
19051.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19061.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19071.43Skamil
19081.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19091.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19101.43Skamil}
19111.43Skamil
19121.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
19131.96SkamilATF_TC(test);								\
19141.96SkamilATF_TC_HEAD(test, tc)							\
19151.96Skamil{									\
19161.96Skamil	atf_tc_set_md_var(tc, "descr",					\
19171.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
19181.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
19191.96Skamil	    masked ? " with ignored signal" : "");			\
19201.96Skamil}									\
19211.96Skamil									\
19221.96SkamilATF_TC_BODY(test, tc)							\
19231.96Skamil{									\
19241.96Skamil									\
19251.96Skamil	traceme_vfork_exec(masked, ignored);				\
19261.96Skamil}
19271.96Skamil
19281.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
19291.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19301.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19311.96Skamil
19321.43Skamil/// ----------------------------------------------------------------------------
19331.43Skamil
19341.1Skamil#if defined(TWAIT_HAVE_PID)
19351.51Skamilstatic void
19361.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19371.59Skamil{
19381.94Skamil	const int sigval = SIGSTOP;
19391.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19401.59Skamil	const int exitval = 10;
19411.59Skamil	pid_t tracee, tracer, wpid;
19421.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19431.59Skamil#if defined(TWAIT_HAVE_STATUS)
19441.59Skamil	int status;
19451.59Skamil#endif
19461.94Skamil	struct sigaction sa;
19471.59Skamil	struct ptrace_siginfo info;
19481.94Skamil	sigset_t intmask;
19491.94Skamil	struct kinfo_proc2 kp;
19501.94Skamil	size_t len = sizeof(kp);
19511.94Skamil
19521.94Skamil	int name[6];
19531.94Skamil	const size_t namelen = __arraycount(name);
19541.94Skamil	ki_sigset_t kp_sigmask;
19551.94Skamil	ki_sigset_t kp_sigignore;
19561.61Skre
19571.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19581.71Skamil	if (sig == SIGILL)
19591.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19601.71Skamil#endif
19611.71Skamil
19621.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
19631.114Skamil		atf_tc_skip("FP exceptions are not supported");
19641.114Skamil
19651.59Skamil	memset(&info, 0, sizeof(info));
19661.59Skamil
19671.59Skamil	DPRINTF("Spawn tracee\n");
19681.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19691.59Skamil	tracee = atf_utils_fork();
19701.59Skamil	if (tracee == 0) {
19711.59Skamil		// Wait for parent to let us crash
19721.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19731.61Skre
19741.94Skamil		if (masked) {
19751.94Skamil			sigemptyset(&intmask);
19761.94Skamil			sigaddset(&intmask, sig);
19771.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19781.94Skamil		}
19791.94Skamil
19801.94Skamil		if (ignored) {
19811.94Skamil			memset(&sa, 0, sizeof(sa));
19821.94Skamil			sa.sa_handler = SIG_IGN;
19831.94Skamil			sigemptyset(&sa.sa_mask);
19841.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
19851.94Skamil		}
19861.94Skamil
19871.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19881.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19891.94Skamil
19901.59Skamil		DPRINTF("Before executing a trap\n");
19911.59Skamil		switch (sig) {
19921.59Skamil		case SIGTRAP:
19931.59Skamil			trigger_trap();
19941.59Skamil			break;
19951.59Skamil		case SIGSEGV:
19961.59Skamil			trigger_segv();
19971.59Skamil			break;
19981.59Skamil		case SIGILL:
19991.59Skamil			trigger_ill();
20001.59Skamil			break;
20011.59Skamil		case SIGFPE:
20021.59Skamil			trigger_fpe();
20031.59Skamil			break;
20041.59Skamil		case SIGBUS:
20051.59Skamil			trigger_bus();
20061.59Skamil			break;
20071.59Skamil		default:
20081.59Skamil			/* NOTREACHED */
20091.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
20101.59Skamil		}
20111.59Skamil
20121.59Skamil		/* NOTREACHED */
20131.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
20141.59Skamil	}
20151.59Skamil
20161.59Skamil	DPRINTF("Spawn debugger\n");
20171.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
20181.59Skamil	tracer = atf_utils_fork();
20191.59Skamil	if (tracer == 0) {
20201.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
20211.59Skamil		tracer = atf_utils_fork();
20221.59Skamil		if (tracer != 0)
20231.61Skre			_exit(exitval);
20241.59Skamil
20251.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
20261.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
20271.59Skamil
20281.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
20291.59Skamil		FORKEE_REQUIRE_SUCCESS(
20301.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20311.59Skamil
20321.59Skamil		forkee_status_stopped(status, SIGSTOP);
20331.59Skamil
20341.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20351.94Skamil		    "traced process\n");
20361.94Skamil		SYSCALL_REQUIRE(
20371.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20381.94Skamil
20391.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20401.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20411.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20421.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20431.94Skamil
20441.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20451.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20461.94Skamil
20471.59Skamil		/* Resume tracee with PT_CONTINUE */
20481.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20491.59Skamil
20501.59Skamil		/* Inform parent that tracer has attached to tracee */
20511.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20521.59Skamil
20531.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20541.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20551.59Skamil
20561.59Skamil		/* Wait for tracee and assert that it exited */
20571.59Skamil		FORKEE_REQUIRE_SUCCESS(
20581.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20591.59Skamil
20601.94Skamil		forkee_status_stopped(status, sigval);
20611.94Skamil
20621.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20631.94Skamil		    "traced process\n");
20641.94Skamil		SYSCALL_REQUIRE(
20651.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20661.94Skamil
20671.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20681.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20691.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20701.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20711.94Skamil
20721.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20731.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20741.94Skamil
20751.94Skamil		name[0] = CTL_KERN,
20761.94Skamil		name[1] = KERN_PROC2,
20771.94Skamil		name[2] = KERN_PROC_PID;
20781.94Skamil		name[3] = tracee;
20791.94Skamil		name[4] = sizeof(kp);
20801.94Skamil		name[5] = 1;
20811.94Skamil
20821.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20831.94Skamil
20841.94Skamil		if (masked)
20851.94Skamil			kp_sigmask = kp.p_sigmask;
20861.94Skamil
20871.94Skamil		if (ignored)
20881.94Skamil			kp_sigignore = kp.p_sigignore;
20891.94Skamil
20901.94Skamil		/* Resume tracee with PT_CONTINUE */
20911.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20921.94Skamil
20931.94Skamil		/* Wait for tracee and assert that it exited */
20941.94Skamil		FORKEE_REQUIRE_SUCCESS(
20951.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20961.94Skamil
20971.93Skamil		forkee_status_stopped(status, sig);
20981.59Skamil
20991.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
21001.61Skre		    "traced process\n");
21011.61Skre		SYSCALL_REQUIRE(
21021.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
21031.59Skamil
21041.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
21051.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
21061.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
21071.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
21081.59Skamil
21091.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
21101.94Skamil
21111.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
21121.94Skamil
21131.94Skamil		if (masked) {
21141.94Skamil			DPRINTF("kp_sigmask="
21151.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21161.94Skamil			    PRIx32 "\n",
21171.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
21181.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
21191.94Skamil
21201.94Skamil			DPRINTF("kp.p_sigmask="
21211.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21221.94Skamil			    PRIx32 "\n",
21231.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
21241.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
21251.94Skamil
21261.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
21271.94Skamil			    sizeof(kp_sigmask)));
21281.94Skamil		}
21291.94Skamil
21301.94Skamil		if (ignored) {
21311.94Skamil			DPRINTF("kp_sigignore="
21321.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21331.94Skamil			    PRIx32 "\n",
21341.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21351.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21361.94Skamil
21371.94Skamil			DPRINTF("kp.p_sigignore="
21381.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21391.94Skamil			    PRIx32 "\n",
21401.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21411.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21421.94Skamil
21431.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21441.94Skamil			    sizeof(kp_sigignore)));
21451.94Skamil		}
21461.94Skamil
21471.59Skamil		switch (sig) {
21481.59Skamil		case SIGTRAP:
21491.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21501.59Skamil			break;
21511.59Skamil		case SIGSEGV:
21521.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21531.59Skamil			break;
21541.71Skamil		case SIGILL:
21551.113Skamil			FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC &&
21561.112Skamil			            info.psi_siginfo.si_code <= ILL_BADSTK);
21571.71Skamil			break;
21581.59Skamil		case SIGFPE:
21591.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21601.59Skamil			break;
21611.59Skamil		case SIGBUS:
21621.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21631.59Skamil			break;
21641.59Skamil		}
21651.59Skamil
21661.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21671.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21681.93Skamil		FORKEE_REQUIRE_SUCCESS(
21691.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21701.59Skamil
21711.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21721.59Skamil
21731.71Skamil		/* Inform parent that tracer is exiting normally */
21741.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21751.71Skamil
21761.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21771.59Skamil		_exit(0 /* collect by initproc */);
21781.59Skamil	}
21791.59Skamil
21801.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21811.59Skamil	    "calling %s()\n", TWAIT_FNAME);
21821.59Skamil	TWAIT_REQUIRE_SUCCESS(
21831.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21841.59Skamil
21851.59Skamil	validate_status_exited(status, exitval);
21861.59Skamil
21871.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
21881.59Skamil	    TWAIT_FNAME);
21891.59Skamil	TWAIT_REQUIRE_SUCCESS(
21901.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
21911.59Skamil
21921.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
21931.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
21941.59Skamil
21951.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
21961.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
21971.59Skamil
21981.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
21991.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
22001.59Skamil
22011.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
22021.59Skamil	    TWAIT_FNAME);
22031.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22041.59Skamil
22051.59Skamil	validate_status_signaled(status, SIGKILL, 0);
22061.59Skamil
22071.71Skamil	DPRINTF("Await normal exit of tracer\n");
22081.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
22091.71Skamil
22101.59Skamil	msg_close(&parent_tracer);
22111.59Skamil	msg_close(&parent_tracee);
22121.59Skamil}
22131.59Skamil
22141.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
22151.61SkreATF_TC(test);								\
22161.61SkreATF_TC_HEAD(test, tc)							\
22171.61Skre{									\
22181.61Skre	atf_tc_set_md_var(tc, "descr",					\
22191.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22201.94Skamil	    "the debuggee");						\
22211.61Skre}									\
22221.61Skre									\
22231.61SkreATF_TC_BODY(test, tc)							\
22241.61Skre{									\
22251.61Skre									\
22261.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
22271.59Skamil}
22281.59Skamil
22291.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
22301.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
22311.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
22321.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
22331.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22341.94Skamil
22351.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22361.94SkamilATF_TC(test);								\
22371.94SkamilATF_TC_HEAD(test, tc)							\
22381.94Skamil{									\
22391.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22401.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22411.94Skamil	    "the debuggee with masked signal");				\
22421.94Skamil}									\
22431.94Skamil									\
22441.94SkamilATF_TC_BODY(test, tc)							\
22451.94Skamil{									\
22461.94Skamil									\
22471.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22481.94Skamil}
22491.94Skamil
22501.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22511.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22521.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22531.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22541.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22551.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22561.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22571.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22581.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22591.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22601.94Skamil
22611.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22621.94SkamilATF_TC(test);								\
22631.94SkamilATF_TC_HEAD(test, tc)							\
22641.94Skamil{									\
22651.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22661.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22671.94Skamil	    "the debuggee with signal ignored");			\
22681.94Skamil}									\
22691.94Skamil									\
22701.94SkamilATF_TC_BODY(test, tc)							\
22711.94Skamil{									\
22721.94Skamil									\
22731.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22741.94Skamil}
22751.94Skamil
22761.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22771.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22781.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22791.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22801.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22811.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
22821.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22831.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
22841.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22851.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
22861.59Skamil#endif
22871.59Skamil
22881.59Skamil/// ----------------------------------------------------------------------------
22891.59Skamil
22901.59Skamil#if defined(TWAIT_HAVE_PID)
22911.59Skamilstatic void
22921.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
22931.67Skamil                                             bool stopped)
22941.1Skamil{
22951.51Skamil	/*
22961.51Skamil	 * notimeout - disable timeout in await zombie function
22971.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
22981.67Skamil	 * stopped - attach to a stopped process
22991.51Skamil	 */
23001.1Skamil
23011.1Skamil	struct msg_fds parent_tracee, parent_tracer;
23021.1Skamil	const int exitval_tracee = 5;
23031.1Skamil	const int exitval_tracer = 10;
23041.1Skamil	pid_t tracee, tracer, wpid;
23051.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
23061.1Skamil#if defined(TWAIT_HAVE_STATUS)
23071.1Skamil	int status;
23081.1Skamil#endif
23091.1Skamil
23101.67Skamil	/*
23111.67Skamil	 * Only a subset of options are supported.
23121.67Skamil	 */
23131.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
23141.67Skamil	            (!notimeout && unrelated && !stopped) ||
23151.67Skamil	            (notimeout && !unrelated && !stopped) ||
23161.67Skamil	            (!notimeout && unrelated && stopped));
23171.67Skamil
23181.13Schristos	DPRINTF("Spawn tracee\n");
23191.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
23201.1Skamil	tracee = atf_utils_fork();
23211.1Skamil	if (tracee == 0) {
23221.67Skamil		if (stopped) {
23231.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
23241.67Skamil			raise(SIGSTOP);
23251.67Skamil		}
23261.67Skamil
23271.1Skamil		// Wait for parent to let us exit
23281.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
23291.1Skamil		_exit(exitval_tracee);
23301.1Skamil	}
23311.1Skamil
23321.13Schristos	DPRINTF("Spawn debugger\n");
23331.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23341.1Skamil	tracer = atf_utils_fork();
23351.1Skamil	if (tracer == 0) {
23361.51Skamil		if(unrelated) {
23371.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23381.51Skamil			tracer = atf_utils_fork();
23391.51Skamil			if (tracer != 0)
23401.51Skamil				_exit(exitval_tracer);
23411.51Skamil		}
23421.51Skamil
23431.67Skamil		if (stopped) {
23441.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23451.67Skamil			await_stopped(tracee);
23461.67Skamil		}
23471.67Skamil
23481.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23491.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23501.1Skamil
23511.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23521.1Skamil		FORKEE_REQUIRE_SUCCESS(
23531.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23541.1Skamil
23551.1Skamil		forkee_status_stopped(status, SIGSTOP);
23561.1Skamil
23571.1Skamil		/* Resume tracee with PT_CONTINUE */
23581.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23591.1Skamil
23601.1Skamil		/* Inform parent that tracer has attached to tracee */
23611.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23621.1Skamil
23631.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23641.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23651.1Skamil
23661.1Skamil		/* Wait for tracee and assert that it exited */
23671.1Skamil		FORKEE_REQUIRE_SUCCESS(
23681.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23691.1Skamil
23701.1Skamil		forkee_status_exited(status, exitval_tracee);
23711.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23721.1Skamil
23731.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23741.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23751.51Skamil	}
23761.51Skamil
23771.51Skamil	if (unrelated) {
23781.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23791.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23801.51Skamil		TWAIT_REQUIRE_SUCCESS(
23811.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23821.51Skamil
23831.51Skamil		validate_status_exited(status, exitval_tracer);
23841.51Skamil
23851.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
23861.51Skamil		    TWAIT_FNAME);
23871.51Skamil		TWAIT_REQUIRE_SUCCESS(
23881.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
23891.1Skamil	}
23901.1Skamil
23911.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
23921.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
23931.1Skamil
23941.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
23951.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
23961.1Skamil
23971.13Schristos	DPRINTF("Detect that tracee is zombie\n");
23981.51Skamil	if (notimeout)
23991.26Skamil		await_zombie_raw(tracee, 0);
24001.26Skamil	else
24011.26Skamil		await_zombie(tracee);
24021.1Skamil
24031.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
24041.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
24051.1Skamil	    TWAIT_FNAME);
24061.1Skamil	TWAIT_REQUIRE_SUCCESS(
24071.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
24081.1Skamil
24091.51Skamil	if (unrelated) {
24101.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
24111.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
24121.51Skamil	} else {
24131.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
24141.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
24151.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
24161.59Skamil			"%s()\n", TWAIT_FNAME);
24171.51Skamil
24181.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
24191.59Skamil			"tracee\n");
24201.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
24211.51Skamil		    tracer);
24221.1Skamil
24231.51Skamil		validate_status_exited(status, exitval_tracer);
24241.51Skamil	}
24251.1Skamil
24261.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
24271.1Skamil	    TWAIT_FNAME);
24281.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
24291.1Skamil
24301.1Skamil	validate_status_exited(status, exitval_tracee);
24311.1Skamil
24321.1Skamil	msg_close(&parent_tracer);
24331.1Skamil	msg_close(&parent_tracee);
24341.1Skamil}
24351.26Skamil
24361.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24371.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24381.51Skamil{
24391.51Skamil	atf_tc_set_md_var(tc, "descr",
24401.51Skamil	    "Assert that tracer sees process termination before the parent");
24411.51Skamil}
24421.51Skamil
24431.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24441.26Skamil{
24451.26Skamil
24461.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24471.26Skamil}
24481.26Skamil
24491.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24501.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24511.1Skamil{
24521.1Skamil	atf_tc_set_md_var(tc, "descr",
24531.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24541.51Skamil	    "process and no other error is reported");
24551.1Skamil}
24561.1Skamil
24571.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24581.1Skamil{
24591.51Skamil	time_t start, end;
24601.51Skamil	double diff;
24611.51Skamil	unsigned long N = 0;
24621.1Skamil
24631.51Skamil	/*
24641.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24651.51Skamil	 * This test body isn't specific to this race, however it's just good
24661.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24671.51Skamil	 */
24681.1Skamil
24691.51Skamil	start = time(NULL);
24701.51Skamil	while (true) {
24711.51Skamil		DPRINTF("Step: %lu\n", N);
24721.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24731.67Skamil		                                             false);
24741.51Skamil		end = time(NULL);
24751.51Skamil		diff = difftime(end, start);
24761.51Skamil		if (diff >= 5.0)
24771.51Skamil			break;
24781.51Skamil		++N;
24791.1Skamil	}
24801.51Skamil	DPRINTF("Iterations: %lu\n", N);
24811.51Skamil}
24821.1Skamil
24831.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
24841.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24851.51Skamil{
24861.51Skamil	atf_tc_set_md_var(tc, "descr",
24871.51Skamil	    "Assert that tracer sees process termination before the parent");
24881.51Skamil}
24891.1Skamil
24901.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24911.51Skamil{
24921.1Skamil
24931.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
24941.67Skamil}
24951.67Skamil
24961.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
24971.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
24981.67Skamil{
24991.67Skamil	atf_tc_set_md_var(tc, "descr",
25001.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
25011.67Skamil}
25021.67Skamil
25031.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
25041.67Skamil{
25051.67Skamil
25061.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
25071.1Skamil}
25081.1Skamil#endif
25091.1Skamil
25101.51Skamil/// ----------------------------------------------------------------------------
25111.51Skamil
25121.66Skamilstatic void
25131.66Skamilparent_attach_to_its_child(bool stopped)
25141.1Skamil{
25151.1Skamil	struct msg_fds parent_tracee;
25161.1Skamil	const int exitval_tracee = 5;
25171.1Skamil	pid_t tracee, wpid;
25181.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25191.1Skamil#if defined(TWAIT_HAVE_STATUS)
25201.1Skamil	int status;
25211.1Skamil#endif
25221.1Skamil
25231.13Schristos	DPRINTF("Spawn tracee\n");
25241.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25251.1Skamil	tracee = atf_utils_fork();
25261.1Skamil	if (tracee == 0) {
25271.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25281.13Schristos		DPRINTF("Parent should now attach to tracee\n");
25291.1Skamil
25301.66Skamil		if (stopped) {
25311.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
25321.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
25331.66Skamil		}
25341.66Skamil
25351.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25361.1Skamil		/* Wait for message from the parent */
25371.1Skamil		_exit(exitval_tracee);
25381.1Skamil	}
25391.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25401.57Skamil
25411.66Skamil	if (stopped) {
25421.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25431.66Skamil		await_stopped(tracee);
25441.66Skamil	}
25451.66Skamil
25461.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25481.1Skamil
25491.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25501.1Skamil	    TWAIT_FNAME);
25511.1Skamil	TWAIT_REQUIRE_SUCCESS(
25521.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25531.1Skamil
25541.1Skamil	validate_status_stopped(status, SIGSTOP);
25551.1Skamil
25561.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25581.1Skamil
25591.13Schristos	DPRINTF("Let the tracee exit now\n");
25601.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25611.1Skamil
25621.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25631.1Skamil	TWAIT_REQUIRE_SUCCESS(
25641.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25651.1Skamil
25661.1Skamil	validate_status_exited(status, exitval_tracee);
25671.1Skamil
25681.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25701.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25711.1Skamil
25721.1Skamil	msg_close(&parent_tracee);
25731.1Skamil}
25741.1Skamil
25751.66SkamilATF_TC(parent_attach_to_its_child);
25761.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25771.66Skamil{
25781.66Skamil	atf_tc_set_md_var(tc, "descr",
25791.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25801.66Skamil}
25811.66Skamil
25821.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
25831.66Skamil{
25841.66Skamil
25851.66Skamil	parent_attach_to_its_child(false);
25861.66Skamil}
25871.66Skamil
25881.66SkamilATF_TC(parent_attach_to_its_stopped_child);
25891.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
25901.66Skamil{
25911.66Skamil	atf_tc_set_md_var(tc, "descr",
25921.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
25931.66Skamil}
25941.66Skamil
25951.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
25961.66Skamil{
25971.66Skamil
25981.66Skamil	parent_attach_to_its_child(true);
25991.66Skamil}
26001.66Skamil
26011.51Skamil/// ----------------------------------------------------------------------------
26021.51Skamil
26031.65Skamilstatic void
26041.65Skamilchild_attach_to_its_parent(bool stopped)
26051.1Skamil{
26061.1Skamil	struct msg_fds parent_tracee;
26071.1Skamil	const int exitval_tracer = 5;
26081.1Skamil	pid_t tracer, wpid;
26091.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
26101.1Skamil#if defined(TWAIT_HAVE_STATUS)
26111.1Skamil	int status;
26121.1Skamil#endif
26131.1Skamil
26141.13Schristos	DPRINTF("Spawn tracer\n");
26151.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
26161.1Skamil	tracer = atf_utils_fork();
26171.1Skamil	if (tracer == 0) {
26181.1Skamil		/* Wait for message from the parent */
26191.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
26201.1Skamil
26211.65Skamil		if (stopped) {
26221.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
26231.65Skamil			        getppid());
26241.65Skamil			await_stopped(getppid());
26251.65Skamil		}
26261.65Skamil
26271.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
26281.1Skamil		    getppid());
26291.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
26301.1Skamil
26311.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
26321.1Skamil		    TWAIT_FNAME);
26331.1Skamil		FORKEE_REQUIRE_SUCCESS(
26341.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26351.1Skamil
26361.1Skamil		forkee_status_stopped(status, SIGSTOP);
26371.1Skamil
26381.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26391.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26401.1Skamil		    != -1);
26411.1Skamil
26421.1Skamil		/* Tell parent we are ready */
26431.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26441.1Skamil
26451.1Skamil		_exit(exitval_tracer);
26461.1Skamil	}
26471.1Skamil
26481.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26491.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26501.65Skamil
26511.65Skamil	if (stopped) {
26521.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26531.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26541.65Skamil	}
26551.65Skamil
26561.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26571.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26581.1Skamil
26591.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26601.1Skamil	TWAIT_REQUIRE_SUCCESS(
26611.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26621.1Skamil
26631.1Skamil	validate_status_exited(status, exitval_tracer);
26641.1Skamil
26651.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26671.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26681.1Skamil
26691.1Skamil	msg_close(&parent_tracee);
26701.1Skamil}
26711.1Skamil
26721.65SkamilATF_TC(child_attach_to_its_parent);
26731.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26741.65Skamil{
26751.65Skamil	atf_tc_set_md_var(tc, "descr",
26761.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26771.65Skamil}
26781.65Skamil
26791.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26801.65Skamil{
26811.65Skamil
26821.65Skamil	child_attach_to_its_parent(false);
26831.65Skamil}
26841.65Skamil
26851.65SkamilATF_TC(child_attach_to_its_stopped_parent);
26861.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
26871.65Skamil{
26881.65Skamil	atf_tc_set_md_var(tc, "descr",
26891.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
26901.65Skamil}
26911.65Skamil
26921.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
26931.65Skamil{
26941.65Skamil	/*
26951.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
26961.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
26971.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
26981.65Skamil	 *
26991.65Skamil	 * As a workaround spawn this test as a subprocess.
27001.65Skamil	 */
27011.65Skamil
27021.65Skamil	const int exitval = 15;
27031.65Skamil	pid_t child, wpid;
27041.65Skamil#if defined(TWAIT_HAVE_STATUS)
27051.65Skamil	int status;
27061.65Skamil#endif
27071.65Skamil
27081.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
27091.65Skamil	if (child == 0) {
27101.65Skamil		child_attach_to_its_parent(true);
27111.65Skamil		_exit(exitval);
27121.65Skamil	} else {
27131.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27141.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27151.65Skamil
27161.65Skamil		validate_status_exited(status, exitval);
27171.65Skamil
27181.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
27191.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27201.65Skamil	}
27211.65Skamil}
27221.65Skamil
27231.51Skamil/// ----------------------------------------------------------------------------
27241.51Skamil
27251.1Skamil#if defined(TWAIT_HAVE_PID)
27261.1Skamil
27271.51Skamilenum tracee_sees_its_original_parent_type {
27281.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
27291.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
27301.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
27311.51Skamil};
27321.51Skamil
27331.51Skamilstatic void
27341.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27351.1Skamil{
27361.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27371.1Skamil	const int exitval_tracee = 5;
27381.1Skamil	const int exitval_tracer = 10;
27391.1Skamil	pid_t parent, tracee, tracer, wpid;
27401.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27411.1Skamil#if defined(TWAIT_HAVE_STATUS)
27421.1Skamil	int status;
27431.1Skamil#endif
27441.51Skamil	/* sysctl(3) - kinfo_proc2 */
27451.51Skamil	int name[CTL_MAXNAME];
27461.51Skamil	struct kinfo_proc2 kp;
27471.51Skamil	size_t len = sizeof(kp);
27481.51Skamil	unsigned int namelen;
27491.51Skamil
27501.51Skamil	/* procfs - status  */
27511.51Skamil	FILE *fp;
27521.51Skamil	struct stat st;
27531.51Skamil	const char *fname = "/proc/curproc/status";
27541.51Skamil	char s_executable[MAXPATHLEN];
27551.51Skamil	int s_pid, s_ppid;
27561.51Skamil	int rv;
27571.51Skamil
27581.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27591.61Skre		SYSCALL_REQUIRE(
27601.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27611.61Skre		if (rv != 0)
27621.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27631.51Skamil	}
27641.1Skamil
27651.13Schristos	DPRINTF("Spawn tracee\n");
27661.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27671.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27681.1Skamil	tracee = atf_utils_fork();
27691.1Skamil	if (tracee == 0) {
27701.1Skamil		parent = getppid();
27711.1Skamil
27721.1Skamil		/* Emit message to the parent */
27731.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27741.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27751.1Skamil
27761.51Skamil		switch (type) {
27771.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27781.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27791.51Skamil			break;
27801.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27811.51Skamil			namelen = 0;
27821.51Skamil			name[namelen++] = CTL_KERN;
27831.51Skamil			name[namelen++] = KERN_PROC2;
27841.51Skamil			name[namelen++] = KERN_PROC_PID;
27851.51Skamil			name[namelen++] = getpid();
27861.51Skamil			name[namelen++] = len;
27871.51Skamil			name[namelen++] = 1;
27881.51Skamil
27891.61Skre			FORKEE_ASSERT_EQ(
27901.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
27911.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
27921.51Skamil			break;
27931.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
27941.51Skamil			/*
27951.51Skamil			 * Format:
27961.51Skamil			 *  EXECUTABLE PID PPID ...
27971.51Skamil			 */
27981.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
27991.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
28001.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
28011.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
28021.51Skamil			break;
28031.51Skamil		}
28041.1Skamil
28051.1Skamil		_exit(exitval_tracee);
28061.1Skamil	}
28071.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
28081.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
28091.1Skamil
28101.13Schristos	DPRINTF("Spawn debugger\n");
28111.1Skamil	tracer = atf_utils_fork();
28121.1Skamil	if (tracer == 0) {
28131.1Skamil		/* No IPC to communicate with the child */
28141.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
28151.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
28161.1Skamil
28171.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
28181.1Skamil		FORKEE_REQUIRE_SUCCESS(
28191.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28201.1Skamil
28211.1Skamil		forkee_status_stopped(status, SIGSTOP);
28221.1Skamil
28231.1Skamil		/* Resume tracee with PT_CONTINUE */
28241.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
28251.1Skamil
28261.1Skamil		/* Inform parent that tracer has attached to tracee */
28271.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
28281.1Skamil
28291.1Skamil		/* Wait for parent to tell use that tracee should have exited */
28301.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
28311.1Skamil
28321.1Skamil		/* Wait for tracee and assert that it exited */
28331.1Skamil		FORKEE_REQUIRE_SUCCESS(
28341.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28351.1Skamil
28361.1Skamil		forkee_status_exited(status, exitval_tracee);
28371.1Skamil
28381.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28391.1Skamil		_exit(exitval_tracer);
28401.1Skamil	}
28411.1Skamil
28421.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28431.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28441.1Skamil
28451.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28461.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28471.1Skamil
28481.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28491.1Skamil	await_zombie(tracee);
28501.1Skamil
28511.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28521.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28531.1Skamil	TWAIT_REQUIRE_SUCCESS(
28541.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28551.1Skamil
28561.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28571.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28581.1Skamil
28591.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28611.1Skamil	    tracer);
28621.1Skamil
28631.1Skamil	validate_status_exited(status, exitval_tracer);
28641.1Skamil
28651.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28661.1Skamil	    TWAIT_FNAME);
28671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28681.1Skamil	    tracee);
28691.1Skamil
28701.1Skamil	validate_status_exited(status, exitval_tracee);
28711.1Skamil
28721.1Skamil	msg_close(&parent_tracer);
28731.1Skamil	msg_close(&parent_tracee);
28741.1Skamil}
28751.1Skamil
28761.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28771.61SkreATF_TC(test);								\
28781.61SkreATF_TC_HEAD(test, tc)							\
28791.61Skre{									\
28801.61Skre	atf_tc_set_md_var(tc, "descr",					\
28811.61Skre	    "Assert that tracee sees its original parent when being traced " \
28821.61Skre	    "(check " descr ")");					\
28831.61Skre}									\
28841.61Skre									\
28851.61SkreATF_TC_BODY(test, tc)							\
28861.61Skre{									\
28871.61Skre									\
28881.61Skre	tracee_sees_its_original_parent(type);				\
28891.1Skamil}
28901.1Skamil
28911.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28921.51Skamil	tracee_sees_its_original_parent_getppid,
28931.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
28941.51Skamil	"getppid(2)");
28951.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28961.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
28971.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
28981.51Skamil	"sysctl(3) and kinfo_proc2");
28991.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29001.51Skamil	tracee_sees_its_original_parent_procfs_status,
29011.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
29021.51Skamil	"the status file in procfs");
29031.1Skamil#endif
29041.1Skamil
29051.51Skamil/// ----------------------------------------------------------------------------
29061.1Skamil
29071.53Skamilstatic void
29081.53Skamileventmask_preserved(int event)
29091.1Skamil{
29101.1Skamil	const int exitval = 5;
29111.1Skamil	const int sigval = SIGSTOP;
29121.1Skamil	pid_t child, wpid;
29131.1Skamil#if defined(TWAIT_HAVE_STATUS)
29141.1Skamil	int status;
29151.1Skamil#endif
29161.1Skamil	ptrace_event_t set_event, get_event;
29171.1Skamil	const int len = sizeof(ptrace_event_t);
29181.1Skamil
29191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29211.1Skamil	if (child == 0) {
29221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29241.1Skamil
29251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29271.1Skamil
29281.13Schristos		DPRINTF("Before exiting of the child process\n");
29291.1Skamil		_exit(exitval);
29301.1Skamil	}
29311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29321.1Skamil
29331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29351.1Skamil
29361.1Skamil	validate_status_stopped(status, sigval);
29371.1Skamil
29381.53Skamil	set_event.pe_set_event = event;
29391.61Skre	SYSCALL_REQUIRE(
29401.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29411.61Skre	SYSCALL_REQUIRE(
29421.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29431.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29441.1Skamil
29451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29461.1Skamil	    "without signal to be sent\n");
29471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29481.1Skamil
29491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29511.1Skamil
29521.1Skamil	validate_status_exited(status, exitval);
29531.1Skamil
29541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29561.1Skamil}
29571.1Skamil
29581.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29591.61SkreATF_TC(test);								\
29601.61SkreATF_TC_HEAD(test, tc)							\
29611.61Skre{									\
29621.61Skre	atf_tc_set_md_var(tc, "descr",					\
29631.61Skre	    "Verify that eventmask " #event " is preserved");		\
29641.61Skre}									\
29651.61Skre									\
29661.61SkreATF_TC_BODY(test, tc)							\
29671.61Skre{									\
29681.61Skre									\
29691.61Skre	eventmask_preserved(event);					\
29701.1Skamil}
29711.1Skamil
29721.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29731.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29741.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29751.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29761.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29771.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29781.1Skamil
29791.53Skamil/// ----------------------------------------------------------------------------
29801.1Skamil
29811.28Skamilstatic void
29821.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
29831.105Skamil    bool trackvforkdone)
29841.1Skamil{
29851.1Skamil	const int exitval = 5;
29861.1Skamil	const int exitval2 = 15;
29871.1Skamil	const int sigval = SIGSTOP;
29881.31Skamil	pid_t child, child2 = 0, wpid;
29891.1Skamil#if defined(TWAIT_HAVE_STATUS)
29901.1Skamil	int status;
29911.1Skamil#endif
29921.1Skamil	ptrace_state_t state;
29931.1Skamil	const int slen = sizeof(state);
29941.1Skamil	ptrace_event_t event;
29951.1Skamil	const int elen = sizeof(event);
29961.1Skamil
29971.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29981.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29991.1Skamil	if (child == 0) {
30001.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30011.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30021.1Skamil
30031.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30041.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30051.1Skamil
30061.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
30071.1Skamil
30081.1Skamil		if (child2 == 0)
30091.1Skamil			_exit(exitval2);
30101.1Skamil
30111.1Skamil		FORKEE_REQUIRE_SUCCESS
30121.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30131.1Skamil
30141.1Skamil		forkee_status_exited(status, exitval2);
30151.1Skamil
30161.13Schristos		DPRINTF("Before exiting of the child process\n");
30171.1Skamil		_exit(exitval);
30181.1Skamil	}
30191.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30201.1Skamil
30211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30231.1Skamil
30241.1Skamil	validate_status_stopped(status, sigval);
30251.1Skamil
30261.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
30271.61Skre	    trackfork ? "|PTRACE_FORK" : "",
30281.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
30291.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
30301.30Skamil	event.pe_set_event = 0;
30311.30Skamil	if (trackfork)
30321.30Skamil		event.pe_set_event |= PTRACE_FORK;
30331.30Skamil	if (trackvfork)
30341.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30351.30Skamil	if (trackvforkdone)
30361.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30381.1Skamil
30391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30401.1Skamil	    "without signal to be sent\n");
30411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30421.1Skamil
30431.29Skamil#if defined(TWAIT_HAVE_PID)
30441.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30451.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30461.61Skre		    child);
30471.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30481.61Skre		    child);
30491.1Skamil
30501.29Skamil		validate_status_stopped(status, SIGTRAP);
30511.1Skamil
30521.61Skre		SYSCALL_REQUIRE(
30531.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30541.31Skamil		if (trackfork && fn == fork) {
30551.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30561.30Skamil			       PTRACE_FORK);
30571.30Skamil		}
30581.31Skamil		if (trackvfork && fn == vfork) {
30591.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30601.30Skamil			       PTRACE_VFORK);
30611.30Skamil		}
30621.29Skamil
30631.29Skamil		child2 = state.pe_other_pid;
30641.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
30651.29Skamil
30661.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
30671.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
30681.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
30691.29Skamil		    child2);
30701.1Skamil
30711.29Skamil		validate_status_stopped(status, SIGTRAP);
30721.1Skamil
30731.61Skre		SYSCALL_REQUIRE(
30741.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
30751.31Skamil		if (trackfork && fn == fork) {
30761.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30771.30Skamil			       PTRACE_FORK);
30781.30Skamil		}
30791.31Skamil		if (trackvfork && fn == vfork) {
30801.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30811.30Skamil			       PTRACE_VFORK);
30821.30Skamil		}
30831.30Skamil
30841.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
30851.29Skamil
30861.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
30871.29Skamil		    "and without signal to be sent\n");
30881.61Skre		SYSCALL_REQUIRE(
30891.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
30901.29Skamil
30911.29Skamil		DPRINTF("Before resuming the child process where it left off "
30921.61Skre		    "and without signal to be sent\n");
30931.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30941.30Skamil	}
30951.30Skamil#endif
30961.30Skamil
30971.31Skamil	if (trackvforkdone && fn == vfork) {
30981.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30991.61Skre		    child);
31001.61Skre		TWAIT_REQUIRE_SUCCESS(
31011.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
31021.30Skamil
31031.30Skamil		validate_status_stopped(status, SIGTRAP);
31041.30Skamil
31051.61Skre		SYSCALL_REQUIRE(
31061.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
31071.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
31081.30Skamil
31091.30Skamil		child2 = state.pe_other_pid;
31101.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
31111.61Skre		    child2);
31121.30Skamil
31131.30Skamil		DPRINTF("Before resuming the child process where it left off "
31141.61Skre		    "and without signal to be sent\n");
31151.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31161.30Skamil	}
31171.29Skamil
31181.30Skamil#if defined(TWAIT_HAVE_PID)
31191.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
31201.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
31211.61Skre		    "\n", TWAIT_FNAME);
31221.61Skre		TWAIT_REQUIRE_SUCCESS(
31231.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
31241.29Skamil
31251.29Skamil		validate_status_exited(status, exitval2);
31261.29Skamil
31271.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
31281.61Skre		    "process\n", TWAIT_FNAME);
31291.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
31301.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
31311.29Skamil	}
31321.29Skamil#endif
31331.1Skamil
31341.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31351.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31371.1Skamil
31381.1Skamil	validate_status_stopped(status, SIGCHLD);
31391.1Skamil
31401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31411.1Skamil	    "without signal to be sent\n");
31421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31431.1Skamil
31441.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31451.1Skamil	    TWAIT_FNAME);
31461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31471.1Skamil
31481.1Skamil	validate_status_exited(status, exitval);
31491.1Skamil
31501.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31511.1Skamil	    TWAIT_FNAME);
31521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31531.1Skamil}
31541.28Skamil
31551.105Skamil#define FORK_TEST(name,fun,tfork,tvfork,tvforkdone)			\
31561.61SkreATF_TC(name);								\
31571.61SkreATF_TC_HEAD(name, tc)							\
31581.61Skre{									\
31591.105Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
31601.105Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
31611.105Skamil	    tfork ? "|PTRACE_FORK" : "",				\
31621.105Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
31631.105Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
31641.61Skre}									\
31651.61Skre									\
31661.61SkreATF_TC_BODY(name, tc)							\
31671.61Skre{									\
31681.61Skre									\
31691.105Skamil	fork_body(fun, tfork, tvfork, tvforkdone);			\
31701.32Skamil}
31711.32Skamil
31721.105SkamilFORK_TEST(fork1, fork, false, false, false)
31731.31Skamil#if defined(TWAIT_HAVE_PID)
31741.105SkamilFORK_TEST(fork2, fork, true, false, false)
31751.105SkamilFORK_TEST(fork3, fork, false, true, false)
31761.105SkamilFORK_TEST(fork4, fork, true, true, false)
31771.31Skamil#endif
31781.105SkamilFORK_TEST(fork5, fork, false, false, true)
31791.31Skamil#if defined(TWAIT_HAVE_PID)
31801.105SkamilFORK_TEST(fork6, fork, true, false, true)
31811.105SkamilFORK_TEST(fork7, fork, false, true, true)
31821.105SkamilFORK_TEST(fork8, fork, true, true, true)
31831.31Skamil#endif
31841.1Skamil
31851.110Skamil#if TEST_VFORK_ENABLED
31861.105SkamilFORK_TEST(vfork1, vfork, false, false, false)
31871.31Skamil#if defined(TWAIT_HAVE_PID)
31881.105SkamilFORK_TEST(vfork2, vfork, true, false, false)
31891.105SkamilFORK_TEST(vfork3, vfork, false, true, false)
31901.105SkamilFORK_TEST(vfork4, vfork, true, true, false)
31911.31Skamil#endif
31921.105SkamilFORK_TEST(vfork5, vfork, false, false, true)
31931.31Skamil#if defined(TWAIT_HAVE_PID)
31941.105SkamilFORK_TEST(vfork6, vfork, true, false, true)
31951.105SkamilFORK_TEST(vfork7, vfork, false, true, true)
31961.105SkamilFORK_TEST(vfork8, vfork, true, true, true)
31971.31Skamil#endif
31981.110Skamil#endif
31991.31Skamil
32001.54Skamil/// ----------------------------------------------------------------------------
32011.31Skamil
32021.110Skamil#if TEST_VFORK_ENABLED
32031.108Skamilstatic void
32041.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void))
32051.108Skamil{
32061.108Skamil	const int exitval = 5;
32071.108Skamil	const int exitval2 = 15;
32081.108Skamil	pid_t child, child2 = 0, wpid;
32091.108Skamil#if defined(TWAIT_HAVE_STATUS)
32101.108Skamil	int status;
32111.108Skamil#endif
32121.108Skamil
32131.108Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
32141.108Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
32151.108Skamil	if (child == 0) {
32161.108Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32171.108Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32181.108Skamil
32191.108Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
32201.108Skamil
32211.108Skamil		if (child2 == 0)
32221.108Skamil			_exit(exitval2);
32231.108Skamil
32241.108Skamil		FORKEE_REQUIRE_SUCCESS
32251.108Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
32261.108Skamil
32271.108Skamil		forkee_status_exited(status, exitval2);
32281.108Skamil
32291.108Skamil		DPRINTF("Before exiting of the child process\n");
32301.108Skamil		_exit(exitval);
32311.108Skamil	}
32321.108Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32331.108Skamil
32341.108Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
32351.108Skamil	    TWAIT_FNAME);
32361.108Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32371.108Skamil
32381.108Skamil	validate_status_exited(status, exitval);
32391.108Skamil
32401.108Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
32411.108Skamil	    TWAIT_FNAME);
32421.108Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32431.108Skamil}
32441.108Skamil
32451.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun)				\
32461.108SkamilATF_TC(name);								\
32471.108SkamilATF_TC_HEAD(name, tc)							\
32481.108Skamil{									\
32491.108Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
32501.108Skamil	    "called from vfork(2)ed child");				\
32511.108Skamil}									\
32521.108Skamil									\
32531.108SkamilATF_TC_BODY(name, tc)							\
32541.108Skamil{									\
32551.108Skamil									\
32561.108Skamil	traceme_vfork_fork_body(fun);					\
32571.108Skamil}
32581.108Skamil
32591.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork)
32601.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork)
32611.110Skamil#endif
32621.108Skamil
32631.108Skamil/// ----------------------------------------------------------------------------
32641.108Skamil
32651.54Skamilenum bytes_transfer_type {
32661.54Skamil	BYTES_TRANSFER_DATA,
32671.54Skamil	BYTES_TRANSFER_DATAIO,
32681.54Skamil	BYTES_TRANSFER_TEXT,
32691.54Skamil	BYTES_TRANSFER_TEXTIO,
32701.54Skamil	BYTES_TRANSFER_AUXV
32711.54Skamil};
32721.31Skamil
32731.54Skamilstatic int __used
32741.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
32751.54Skamil{
32761.54Skamil	int e, f, g, h;
32771.1Skamil
32781.54Skamil	a *= 4;
32791.54Skamil	b += 3;
32801.54Skamil	c -= 2;
32811.54Skamil	d /= 1;
32821.1Skamil
32831.54Skamil	e = strtol("10", NULL, 10);
32841.54Skamil	f = strtol("20", NULL, 10);
32851.54Skamil	g = strtol("30", NULL, 10);
32861.54Skamil	h = strtol("40", NULL, 10);
32871.1Skamil
32881.54Skamil	return (a + b * c - d) + (e * f - g / h);
32891.1Skamil}
32901.1Skamil
32911.54Skamilstatic void
32921.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
32931.1Skamil{
32941.1Skamil	const int exitval = 5;
32951.1Skamil	const int sigval = SIGSTOP;
32961.1Skamil	pid_t child, wpid;
32971.54Skamil	bool skip = false;
32981.1Skamil
32991.54Skamil	int lookup_me = 0;
33001.54Skamil	uint8_t lookup_me8 = 0;
33011.54Skamil	uint16_t lookup_me16 = 0;
33021.54Skamil	uint32_t lookup_me32 = 0;
33031.54Skamil	uint64_t lookup_me64 = 0;
33041.1Skamil
33051.54Skamil	int magic = 0x13579246;
33061.54Skamil	uint8_t magic8 = 0xab;
33071.54Skamil	uint16_t magic16 = 0x1234;
33081.54Skamil	uint32_t magic32 = 0x98765432;
33091.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
33101.1Skamil
33111.54Skamil	struct ptrace_io_desc io;
33121.1Skamil#if defined(TWAIT_HAVE_STATUS)
33131.1Skamil	int status;
33141.1Skamil#endif
33151.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
33161.60Skre	AuxInfo ai[513], *aip;
33171.55Schristos
33181.55Schristos	ATF_REQUIRE(size < sizeof(ai));
33191.1Skamil
33201.54Skamil	/* Prepare variables for .TEXT transfers */
33211.54Skamil	switch (type) {
33221.54Skamil	case BYTES_TRANSFER_TEXT:
33231.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
33241.54Skamil		break;
33251.54Skamil	case BYTES_TRANSFER_TEXTIO:
33261.54Skamil		switch (size) {
33271.54Skamil		case 8:
33281.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
33291.54Skamil			break;
33301.54Skamil		case 16:
33311.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
33321.54Skamil			break;
33331.54Skamil		case 32:
33341.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
33351.54Skamil			break;
33361.54Skamil		case 64:
33371.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
33381.54Skamil			break;
33391.54Skamil		}
33401.54Skamil		break;
33411.54Skamil	default:
33421.54Skamil		break;
33431.54Skamil	}
33441.1Skamil
33451.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
33461.54Skamil	switch (type) {
33471.54Skamil	case BYTES_TRANSFER_TEXTIO:
33481.54Skamil	case BYTES_TRANSFER_DATAIO:
33491.54Skamil		io.piod_op = operation;
33501.54Skamil		switch (size) {
33511.54Skamil		case 8:
33521.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33531.54Skamil			               (void *)bytes_transfer_dummy :
33541.54Skamil			               &lookup_me8;
33551.54Skamil			io.piod_addr = &lookup_me8;
33561.54Skamil			io.piod_len = sizeof(lookup_me8);
33571.54Skamil			break;
33581.54Skamil		case 16:
33591.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33601.54Skamil			               (void *)bytes_transfer_dummy :
33611.54Skamil			               &lookup_me16;
33621.54Skamil			io.piod_addr = &lookup_me16;
33631.54Skamil			io.piod_len = sizeof(lookup_me16);
33641.54Skamil			break;
33651.54Skamil		case 32:
33661.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33671.54Skamil			               (void *)bytes_transfer_dummy :
33681.54Skamil			               &lookup_me32;
33691.54Skamil			io.piod_addr = &lookup_me32;
33701.54Skamil			io.piod_len = sizeof(lookup_me32);
33711.54Skamil			break;
33721.54Skamil		case 64:
33731.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33741.54Skamil			               (void *)bytes_transfer_dummy :
33751.54Skamil			               &lookup_me64;
33761.54Skamil			io.piod_addr = &lookup_me64;
33771.54Skamil			io.piod_len = sizeof(lookup_me64);
33781.54Skamil			break;
33791.54Skamil		default:
33801.54Skamil			break;
33811.54Skamil		}
33821.54Skamil		break;
33831.54Skamil	case BYTES_TRANSFER_AUXV:
33841.54Skamil		io.piod_op = operation;
33851.54Skamil		io.piod_offs = 0;
33861.54Skamil		io.piod_addr = ai;
33871.54Skamil		io.piod_len = size;
33881.54Skamil		break;
33891.54Skamil	default:
33901.54Skamil		break;
33911.1Skamil	}
33921.1Skamil
33931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33951.1Skamil	if (child == 0) {
33961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33981.1Skamil
33991.54Skamil		switch (type) {
34001.54Skamil		case BYTES_TRANSFER_DATA:
34011.54Skamil			switch (operation) {
34021.54Skamil			case PT_READ_D:
34031.54Skamil			case PT_READ_I:
34041.54Skamil				lookup_me = magic;
34051.54Skamil				break;
34061.54Skamil			default:
34071.54Skamil				break;
34081.54Skamil			}
34091.54Skamil			break;
34101.54Skamil		case BYTES_TRANSFER_DATAIO:
34111.54Skamil			switch (operation) {
34121.54Skamil			case PIOD_READ_D:
34131.54Skamil			case PIOD_READ_I:
34141.54Skamil				switch (size) {
34151.54Skamil				case 8:
34161.54Skamil					lookup_me8 = magic8;
34171.54Skamil					break;
34181.54Skamil				case 16:
34191.54Skamil					lookup_me16 = magic16;
34201.54Skamil					break;
34211.54Skamil				case 32:
34221.54Skamil					lookup_me32 = magic32;
34231.54Skamil					break;
34241.54Skamil				case 64:
34251.54Skamil					lookup_me64 = magic64;
34261.54Skamil					break;
34271.54Skamil				default:
34281.54Skamil					break;
34291.54Skamil				}
34301.54Skamil				break;
34311.54Skamil			default:
34321.54Skamil				break;
34331.54Skamil			}
34341.54Skamil		default:
34351.54Skamil			break;
34361.54Skamil		}
34371.54Skamil
34381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34401.1Skamil
34411.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
34421.54Skamil		switch (type) {
34431.54Skamil		case BYTES_TRANSFER_DATA:
34441.54Skamil			switch (operation) {
34451.54Skamil			case PT_WRITE_D:
34461.54Skamil			case PT_WRITE_I:
34471.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
34481.54Skamil				break;
34491.54Skamil			default:
34501.54Skamil				break;
34511.54Skamil			}
34521.54Skamil			break;
34531.54Skamil		case BYTES_TRANSFER_DATAIO:
34541.54Skamil			switch (operation) {
34551.54Skamil			case PIOD_WRITE_D:
34561.54Skamil			case PIOD_WRITE_I:
34571.54Skamil				switch (size) {
34581.54Skamil				case 8:
34591.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
34601.54Skamil					break;
34611.54Skamil				case 16:
34621.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
34631.54Skamil					break;
34641.54Skamil				case 32:
34651.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
34661.54Skamil					break;
34671.54Skamil				case 64:
34681.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
34691.54Skamil					break;
34701.54Skamil				default:
34711.54Skamil					break;
34721.54Skamil				}
34731.54Skamil				break;
34741.54Skamil			default:
34751.54Skamil				break;
34761.54Skamil			}
34771.54Skamil			break;
34781.54Skamil		case BYTES_TRANSFER_TEXT:
34791.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
34801.54Skamil			                     sizeof(magic)) == 0);
34811.54Skamil			break;
34821.54Skamil		case BYTES_TRANSFER_TEXTIO:
34831.54Skamil			switch (size) {
34841.54Skamil			case 8:
34851.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
34861.54Skamil				                     bytes_transfer_dummy,
34871.54Skamil				                     sizeof(magic8)) == 0);
34881.54Skamil				break;
34891.54Skamil			case 16:
34901.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
34911.54Skamil				                     bytes_transfer_dummy,
34921.54Skamil				                     sizeof(magic16)) == 0);
34931.54Skamil				break;
34941.54Skamil			case 32:
34951.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
34961.54Skamil				                     bytes_transfer_dummy,
34971.54Skamil				                     sizeof(magic32)) == 0);
34981.54Skamil				break;
34991.54Skamil			case 64:
35001.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
35011.54Skamil				                     bytes_transfer_dummy,
35021.54Skamil				                     sizeof(magic64)) == 0);
35031.54Skamil				break;
35041.54Skamil			}
35051.54Skamil			break;
35061.54Skamil		default:
35071.54Skamil			break;
35081.54Skamil		}
35091.54Skamil
35101.13Schristos		DPRINTF("Before exiting of the child process\n");
35111.1Skamil		_exit(exitval);
35121.1Skamil	}
35131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35141.1Skamil
35151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35171.1Skamil
35181.1Skamil	validate_status_stopped(status, sigval);
35191.1Skamil
35201.54Skamil	/* Check PaX MPROTECT */
35211.54Skamil	if (!can_we_write_to_text(child)) {
35221.54Skamil		switch (type) {
35231.54Skamil		case BYTES_TRANSFER_TEXTIO:
35241.54Skamil			switch (operation) {
35251.54Skamil			case PIOD_WRITE_D:
35261.54Skamil			case PIOD_WRITE_I:
35271.54Skamil				skip = true;
35281.54Skamil				break;
35291.54Skamil			default:
35301.54Skamil				break;
35311.54Skamil			}
35321.54Skamil			break;
35331.54Skamil		case BYTES_TRANSFER_TEXT:
35341.54Skamil			switch (operation) {
35351.54Skamil			case PT_WRITE_D:
35361.54Skamil			case PT_WRITE_I:
35371.54Skamil				skip = true;
35381.54Skamil				break;
35391.54Skamil			default:
35401.54Skamil				break;
35411.54Skamil			}
35421.54Skamil			break;
35431.54Skamil		default:
35441.54Skamil			break;
35451.54Skamil		}
35461.54Skamil	}
35471.1Skamil
35481.54Skamil	/* Bailout cleanly killing the child process */
35491.54Skamil	if (skip) {
35501.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
35511.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35521.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
35531.54Skamil		                      child);
35541.1Skamil
35551.54Skamil		validate_status_signaled(status, SIGKILL, 0);
35561.1Skamil
35571.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
35581.54Skamil	}
35591.1Skamil
35601.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
35611.54Skamil	       "parent=%d\n", child, getpid());
35621.1Skamil
35631.54Skamil	switch (type) {
35641.54Skamil	case BYTES_TRANSFER_TEXTIO:
35651.54Skamil	case BYTES_TRANSFER_DATAIO:
35661.54Skamil	case BYTES_TRANSFER_AUXV:
35671.54Skamil		switch (operation) {
35681.54Skamil		case PIOD_WRITE_D:
35691.54Skamil		case PIOD_WRITE_I:
35701.54Skamil			switch (size) {
35711.54Skamil			case 8:
35721.54Skamil				lookup_me8 = magic8;
35731.54Skamil				break;
35741.54Skamil			case 16:
35751.54Skamil				lookup_me16 = magic16;
35761.54Skamil				break;
35771.54Skamil			case 32:
35781.54Skamil				lookup_me32 = magic32;
35791.54Skamil				break;
35801.54Skamil			case 64:
35811.54Skamil				lookup_me64 = magic64;
35821.54Skamil				break;
35831.54Skamil			default:
35841.54Skamil				break;
35851.54Skamil			}
35861.54Skamil			break;
35871.54Skamil		default:
35881.54Skamil			break;
35891.54Skamil		}
35901.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35911.54Skamil		switch (operation) {
35921.54Skamil		case PIOD_READ_D:
35931.54Skamil		case PIOD_READ_I:
35941.54Skamil			switch (size) {
35951.54Skamil			case 8:
35961.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
35971.54Skamil				break;
35981.54Skamil			case 16:
35991.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
36001.54Skamil				break;
36011.54Skamil			case 32:
36021.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
36031.54Skamil				break;
36041.54Skamil			case 64:
36051.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
36061.54Skamil				break;
36071.54Skamil			default:
36081.54Skamil				break;
36091.54Skamil			}
36101.54Skamil			break;
36111.54Skamil		case PIOD_READ_AUXV:
36121.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
36131.54Skamil			        io.piod_len);
36141.54Skamil			ATF_REQUIRE(io.piod_len > 0);
36151.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
36161.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
36171.54Skamil				    (long long int)aip->a_type,
36181.54Skamil				    (long long int)aip->a_v);
36191.54Skamil			break;
36201.54Skamil		default:
36211.54Skamil			break;
36221.54Skamil		}
36231.54Skamil		break;
36241.54Skamil	case BYTES_TRANSFER_TEXT:
36251.54Skamil		switch (operation) {
36261.54Skamil		case PT_READ_D:
36271.54Skamil		case PT_READ_I:
36281.54Skamil			errno = 0;
36291.54Skamil			lookup_me = ptrace(operation, child,
36301.54Skamil			                   bytes_transfer_dummy, 0);
36311.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
36321.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
36331.54Skamil			break;
36341.54Skamil		case PT_WRITE_D:
36351.54Skamil		case PT_WRITE_I:
36361.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
36371.54Skamil			                       bytes_transfer_dummy, magic)
36381.54Skamil			                != -1);
36391.54Skamil			break;
36401.54Skamil		default:
36411.54Skamil			break;
36421.54Skamil		}
36431.54Skamil		break;
36441.54Skamil	case BYTES_TRANSFER_DATA:
36451.54Skamil		switch (operation) {
36461.54Skamil		case PT_READ_D:
36471.54Skamil		case PT_READ_I:
36481.54Skamil			errno = 0;
36491.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
36501.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
36511.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
36521.54Skamil			break;
36531.54Skamil		case PT_WRITE_D:
36541.54Skamil		case PT_WRITE_I:
36551.54Skamil			lookup_me = magic;
36561.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
36571.54Skamil			                       magic) != -1);
36581.54Skamil			break;
36591.54Skamil		default:
36601.54Skamil			break;
36611.54Skamil		}
36621.54Skamil		break;
36631.54Skamil	default:
36641.54Skamil		break;
36651.54Skamil	}
36661.1Skamil
36671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36681.1Skamil	    "without signal to be sent\n");
36691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36701.1Skamil
36711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36731.1Skamil
36741.1Skamil	validate_status_exited(status, exitval);
36751.1Skamil
36761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36781.1Skamil}
36791.1Skamil
36801.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
36811.61SkreATF_TC(test);								\
36821.61SkreATF_TC_HEAD(test, tc)							\
36831.61Skre{									\
36841.61Skre	atf_tc_set_md_var(tc, "descr",					\
36851.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
36861.61Skre	    " of type " #type);						\
36871.61Skre}									\
36881.61Skre									\
36891.61SkreATF_TC_BODY(test, tc)							\
36901.61Skre{									\
36911.61Skre									\
36921.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
36931.1Skamil}
36941.1Skamil
36951.54Skamil// DATA
36961.1Skamil
36971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
36981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
36991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
37001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
37011.54Skamil
37021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
37031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
37041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
37051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
37061.54Skamil
37071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
37081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
37091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
37101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
37111.54Skamil
37121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
37131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
37141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
37151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
37161.54Skamil
37171.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
37181.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
37191.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
37201.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
37211.54Skamil
37221.54Skamil// TEXT
37231.54Skamil
37241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
37251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
37261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
37271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
37281.54Skamil
37291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
37301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
37311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
37321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
37331.54Skamil
37341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
37351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
37361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
37371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
37381.54Skamil
37391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
37401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
37411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
37421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
37431.54Skamil
37441.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
37451.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
37461.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
37471.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
37481.1Skamil
37491.54Skamil// AUXV
37501.1Skamil
37511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
37521.1Skamil
37531.54Skamil/// ----------------------------------------------------------------------------
37541.1Skamil
37551.101Skamilstatic void
37561.101Skamilbytes_transfer_alignment(const char *operation)
37571.101Skamil{
37581.101Skamil	const int exitval = 5;
37591.101Skamil	const int sigval = SIGSTOP;
37601.101Skamil	pid_t child, wpid;
37611.101Skamil#if defined(TWAIT_HAVE_STATUS)
37621.101Skamil	int status;
37631.101Skamil#endif
37641.101Skamil	char *buffer;
37651.101Skamil	int vector;
37661.101Skamil	size_t len;
37671.101Skamil	size_t i;
37681.101Skamil	int op;
37691.101Skamil
37701.101Skamil	struct ptrace_io_desc io;
37711.101Skamil	struct ptrace_siginfo info;
37721.101Skamil
37731.101Skamil	memset(&io, 0, sizeof(io));
37741.101Skamil	memset(&info, 0, sizeof(info));
37751.101Skamil
37761.101Skamil	/* Testing misaligned byte transfer crossing page boundaries */
37771.101Skamil	len = sysconf(_SC_PAGESIZE) * 2;
37781.101Skamil	buffer = malloc(len);
37791.101Skamil	ATF_REQUIRE(buffer != NULL);
37801.101Skamil
37811.101Skamil	/* Initialize the buffer with random data */
37821.101Skamil	for (i = 0; i < len; i++)
37831.101Skamil		buffer[i] = i & 0xff;
37841.101Skamil
37851.101Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
37861.101Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
37871.101Skamil	if (child == 0) {
37881.101Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37891.101Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37901.101Skamil
37911.101Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37921.101Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37931.101Skamil
37941.101Skamil		DPRINTF("Before exiting of the child process\n");
37951.101Skamil		_exit(exitval);
37961.101Skamil	}
37971.101Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37981.101Skamil
37991.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38001.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38011.101Skamil
38021.101Skamil	validate_status_stopped(status, sigval);
38031.101Skamil
38041.101Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38051.101Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
38061.101Skamil		!= -1);
38071.101Skamil
38081.101Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
38091.101Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
38101.101Skamil		"si_errno=%#x\n",
38111.101Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
38121.101Skamil		info.psi_siginfo.si_errno);
38131.101Skamil
38141.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
38151.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
38161.101Skamil
38171.101Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
38181.101Skamil	    strcmp(operation, "PT_READ_D") == 0) {
38191.101Skamil		if (strcmp(operation, "PT_READ_I"))
38201.101Skamil			op = PT_READ_I;
38211.101Skamil		else
38221.101Skamil			op = PT_READ_D;
38231.101Skamil
38241.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38251.101Skamil			errno = 0;
38261.101Skamil			vector = ptrace(op, child, buffer + i, 0);
38271.101Skamil			ATF_REQUIRE_EQ(errno, 0);
38281.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
38291.101Skamil		}
38301.101Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
38311.101Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
38321.101Skamil		if (strcmp(operation, "PT_WRITE_I"))
38331.101Skamil			op = PT_WRITE_I;
38341.101Skamil		else
38351.101Skamil			op = PT_WRITE_D;
38361.101Skamil
38371.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38381.101Skamil			memcpy(&vector, buffer + i, sizeof(int));
38391.101Skamil			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
38401.101Skamil			    != -1);
38411.101Skamil		}
38421.101Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
38431.101Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
38441.101Skamil		if (strcmp(operation, "PIOD_READ_I"))
38451.101Skamil			op = PIOD_READ_I;
38461.101Skamil		else
38471.101Skamil			op = PIOD_READ_D;
38481.101Skamil
38491.101Skamil		io.piod_op = op;
38501.101Skamil		io.piod_addr = &vector;
38511.101Skamil		io.piod_len = sizeof(int);
38521.101Skamil
38531.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38541.101Skamil			io.piod_offs = buffer + i;
38551.101Skamil
38561.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38571.101Skamil			                != -1);
38581.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
38591.101Skamil		}
38601.101Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
38611.101Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
38621.101Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
38631.101Skamil			op = PIOD_WRITE_I;
38641.101Skamil		else
38651.101Skamil			op = PIOD_WRITE_D;
38661.101Skamil
38671.101Skamil		io.piod_op = op;
38681.101Skamil		io.piod_addr = &vector;
38691.101Skamil		io.piod_len = sizeof(int);
38701.101Skamil
38711.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38721.101Skamil			io.piod_offs = buffer + i;
38731.101Skamil
38741.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38751.101Skamil			                != -1);
38761.101Skamil		}
38771.101Skamil	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
38781.101Skamil		io.piod_op = PIOD_READ_AUXV;
38791.101Skamil		io.piod_addr = &vector;
38801.101Skamil		io.piod_len = sizeof(int);
38811.101Skamil
38821.101Skamil		errno = 0;
38831.101Skamil		i = 0;
38841.101Skamil		/* Read the whole AUXV vector, it has no clear length */
38851.101Skamil		while (errno != EIO) {
38861.101Skamil			io.piod_offs = (void *)(intptr_t)i;
38871.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38881.101Skamil			                != -1 || (errno == EIO && i > 0));
38891.101Skamil			++i;
38901.101Skamil		}
38911.101Skamil	}
38921.101Skamil
38931.101Skamil	DPRINTF("Before resuming the child process where it left off "
38941.101Skamil	    "and without signal to be sent\n");
38951.101Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38961.101Skamil
38971.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38981.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
38991.101Skamil	    child);
39001.101Skamil
39011.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39021.101Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39031.101Skamil}
39041.101Skamil
39051.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
39061.101SkamilATF_TC(test);								\
39071.101SkamilATF_TC_HEAD(test, tc)							\
39081.101Skamil{									\
39091.101Skamil	atf_tc_set_md_var(tc, "descr",					\
39101.101Skamil	    "Verify bytes transfer for potentially misaligned "		\
39111.101Skamil	    "operation " operation);					\
39121.101Skamil}									\
39131.101Skamil									\
39141.101SkamilATF_TC_BODY(test, tc)							\
39151.101Skamil{									\
39161.101Skamil									\
39171.101Skamil	bytes_transfer_alignment(operation);				\
39181.101Skamil}
39191.101Skamil
39201.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
39211.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
39221.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
39231.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
39241.101Skamil
39251.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
39261.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
39271.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
39281.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
39291.101Skamil
39301.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
39311.101Skamil
39321.101Skamil/// ----------------------------------------------------------------------------
39331.101Skamil
39341.115Skamilstatic void
39351.115Skamilbytes_transfer_eof(const char *operation)
39361.115Skamil{
39371.115Skamil	const int exitval = 5;
39381.115Skamil	const int sigval = SIGSTOP;
39391.115Skamil	pid_t child, wpid;
39401.115Skamil#if defined(TWAIT_HAVE_STATUS)
39411.115Skamil	int status;
39421.115Skamil#endif
39431.115Skamil	FILE *fp;
39441.115Skamil	char *p;
39451.115Skamil	int vector;
39461.115Skamil	int op;
39471.115Skamil
39481.115Skamil	struct ptrace_io_desc io;
39491.115Skamil	struct ptrace_siginfo info;
39501.115Skamil
39511.115Skamil	memset(&io, 0, sizeof(io));
39521.115Skamil	memset(&info, 0, sizeof(info));
39531.115Skamil
39541.115Skamil	vector = 0;
39551.115Skamil
39561.115Skamil	fp = tmpfile();
39571.115Skamil	ATF_REQUIRE(fp != NULL);
39581.115Skamil
39591.115Skamil	p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
39601.115Skamil	ATF_REQUIRE(p != MAP_FAILED);
39611.115Skamil
39621.115Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
39631.115Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
39641.115Skamil	if (child == 0) {
39651.115Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39661.115Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39671.115Skamil
39681.115Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39691.115Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39701.115Skamil
39711.115Skamil		DPRINTF("Before exiting of the child process\n");
39721.115Skamil		_exit(exitval);
39731.115Skamil	}
39741.115Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39751.115Skamil
39761.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39771.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39781.115Skamil
39791.115Skamil	validate_status_stopped(status, sigval);
39801.115Skamil
39811.115Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39821.115Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
39831.115Skamil		!= -1);
39841.115Skamil
39851.115Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
39861.115Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
39871.115Skamil		"si_errno=%#x\n",
39881.115Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
39891.115Skamil		info.psi_siginfo.si_errno);
39901.115Skamil
39911.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
39921.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
39931.115Skamil
39941.115Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
39951.115Skamil	    strcmp(operation, "PT_READ_D") == 0) {
39961.115Skamil		if (strcmp(operation, "PT_READ_I"))
39971.115Skamil			op = PT_READ_I;
39981.115Skamil		else
39991.115Skamil			op = PT_READ_D;
40001.115Skamil
40011.115Skamil		errno = 0;
40021.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1);
40031.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
40041.115Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
40051.115Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
40061.115Skamil		if (strcmp(operation, "PT_WRITE_I"))
40071.115Skamil			op = PT_WRITE_I;
40081.115Skamil		else
40091.115Skamil			op = PT_WRITE_D;
40101.115Skamil
40111.115Skamil		errno = 0;
40121.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1);
40131.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
40141.115Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
40151.115Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
40161.115Skamil		if (strcmp(operation, "PIOD_READ_I"))
40171.115Skamil			op = PIOD_READ_I;
40181.115Skamil		else
40191.115Skamil			op = PIOD_READ_D;
40201.115Skamil
40211.115Skamil		io.piod_op = op;
40221.115Skamil		io.piod_addr = &vector;
40231.115Skamil		io.piod_len = sizeof(int);
40241.115Skamil		io.piod_offs = p;
40251.115Skamil
40261.115Skamil		errno = 0;
40271.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
40281.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
40291.115Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
40301.115Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
40311.115Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
40321.115Skamil			op = PIOD_WRITE_I;
40331.115Skamil		else
40341.115Skamil			op = PIOD_WRITE_D;
40351.115Skamil
40361.115Skamil		io.piod_op = op;
40371.115Skamil		io.piod_addr = &vector;
40381.115Skamil		io.piod_len = sizeof(int);
40391.115Skamil		io.piod_offs = p;
40401.115Skamil
40411.115Skamil		errno = 0;
40421.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
40431.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
40441.115Skamil	}
40451.115Skamil
40461.115Skamil	DPRINTF("Before resuming the child process where it left off "
40471.115Skamil	    "and without signal to be sent\n");
40481.115Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40491.115Skamil
40501.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40511.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
40521.115Skamil	    child);
40531.115Skamil
40541.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40551.115Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40561.115Skamil}
40571.115Skamil
40581.115Skamil#define BYTES_TRANSFER_EOF(test, operation)				\
40591.115SkamilATF_TC(test);								\
40601.115SkamilATF_TC_HEAD(test, tc)							\
40611.115Skamil{									\
40621.115Skamil	atf_tc_set_md_var(tc, "descr",					\
40631.115Skamil	    "Verify bytes EOF byte transfer for the " operation		\
40641.115Skamil	    " operation");						\
40651.115Skamil}									\
40661.115Skamil									\
40671.115SkamilATF_TC_BODY(test, tc)							\
40681.115Skamil{									\
40691.115Skamil									\
40701.115Skamil	bytes_transfer_eof(operation);					\
40711.115Skamil}
40721.115Skamil
40731.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I")
40741.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D")
40751.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I")
40761.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D")
40771.115Skamil
40781.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I")
40791.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D")
40801.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I")
40811.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D")
40821.115Skamil
40831.115Skamil/// ----------------------------------------------------------------------------
40841.115Skamil
40851.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
40861.72Skamilstatic void
40871.72Skamilaccess_regs(const char *regset, const char *aux)
40881.1Skamil{
40891.1Skamil	const int exitval = 5;
40901.1Skamil	const int sigval = SIGSTOP;
40911.1Skamil	pid_t child, wpid;
40921.1Skamil#if defined(TWAIT_HAVE_STATUS)
40931.1Skamil	int status;
40941.1Skamil#endif
40951.72Skamil#if defined(HAVE_GPREGS)
40961.72Skamil	struct reg gpr;
40971.76Sscole	register_t rgstr;
40981.1Skamil#endif
40991.72Skamil#if defined(HAVE_FPREGS)
41001.72Skamil	struct fpreg fpr;
41011.1Skamil#endif
41021.76Sscole
41031.72Skamil#if !defined(HAVE_GPREGS)
41041.72Skamil	if (strcmp(regset, "regs") == 0)
41051.72Skamil		atf_tc_fail("Impossible test scenario!");
41061.1Skamil#endif
41071.1Skamil
41081.72Skamil#if !defined(HAVE_FPREGS)
41091.72Skamil	if (strcmp(regset, "fpregs") == 0)
41101.72Skamil		atf_tc_fail("Impossible test scenario!");
41111.1Skamil#endif
41121.1Skamil
41131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41151.1Skamil	if (child == 0) {
41161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41181.1Skamil
41191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41211.1Skamil
41221.13Schristos		DPRINTF("Before exiting of the child process\n");
41231.1Skamil		_exit(exitval);
41241.1Skamil	}
41251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41261.1Skamil
41271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41291.1Skamil
41301.1Skamil	validate_status_stopped(status, sigval);
41311.1Skamil
41321.1Skamil#if defined(HAVE_GPREGS)
41331.72Skamil	if (strcmp(regset, "regs") == 0) {
41341.72Skamil		DPRINTF("Call GETREGS for the child process\n");
41351.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
41361.72Skamil
41371.72Skamil		if (strcmp(aux, "none") == 0) {
41381.72Skamil			DPRINTF("Retrieved registers\n");
41391.72Skamil		} else if (strcmp(aux, "pc") == 0) {
41401.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
41411.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
41421.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
41431.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
41441.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
41451.72Skamil		} else if (strcmp(aux, "sp") == 0) {
41461.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
41471.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
41481.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
41491.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
41501.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
41511.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
41521.72Skamil			DPRINTF("Call SETREGS for the child process\n");
41531.72Skamil			SYSCALL_REQUIRE(
41541.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
41551.72Skamil		}
41561.72Skamil	}
41571.1Skamil#endif
41581.1Skamil
41591.72Skamil#if defined(HAVE_FPREGS)
41601.72Skamil	if (strcmp(regset, "fpregs") == 0) {
41611.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
41621.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
41631.72Skamil
41641.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
41651.72Skamil			DPRINTF("Retrieved FP registers\n");
41661.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
41671.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
41681.72Skamil			SYSCALL_REQUIRE(
41691.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
41701.72Skamil		}
41711.1Skamil	}
41721.1Skamil#endif
41731.1Skamil
41741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41751.1Skamil	    "without signal to be sent\n");
41761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41771.1Skamil
41781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41801.1Skamil
41811.1Skamil	validate_status_exited(status, exitval);
41821.1Skamil
41831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41851.1Skamil}
41861.1Skamil
41871.72Skamil#define ACCESS_REGS(test, regset, aux)					\
41881.72SkamilATF_TC(test);								\
41891.72SkamilATF_TC_HEAD(test, tc)							\
41901.72Skamil{									\
41911.72Skamil        atf_tc_set_md_var(tc, "descr",					\
41921.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
41931.72Skamil}									\
41941.72Skamil									\
41951.72SkamilATF_TC_BODY(test, tc)							\
41961.72Skamil{									\
41971.72Skamil									\
41981.72Skamil        access_regs(regset, aux);					\
41991.1Skamil}
42001.1Skamil#endif
42011.1Skamil
42021.72Skamil#if defined(HAVE_GPREGS)
42031.72SkamilACCESS_REGS(access_regs1, "regs", "none")
42041.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
42051.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
42061.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
42071.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
42081.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
42091.1Skamil#endif
42101.1Skamil#if defined(HAVE_FPREGS)
42111.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
42121.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
42131.1Skamil#endif
42141.1Skamil
42151.72Skamil/// ----------------------------------------------------------------------------
42161.1Skamil
42171.1Skamil#if defined(PT_STEP)
42181.1Skamilstatic void
42191.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
42201.1Skamil{
42211.1Skamil	const int exitval = 5;
42221.1Skamil	const int sigval = SIGSTOP;
42231.1Skamil	pid_t child, wpid;
42241.1Skamil#if defined(TWAIT_HAVE_STATUS)
42251.1Skamil	int status;
42261.1Skamil#endif
42271.1Skamil	int happy;
42281.95Skamil	struct sigaction sa;
42291.81Skamil	struct ptrace_siginfo info;
42301.95Skamil	sigset_t intmask;
42311.95Skamil	struct kinfo_proc2 kp;
42321.95Skamil	size_t len = sizeof(kp);
42331.95Skamil
42341.95Skamil	int name[6];
42351.95Skamil	const size_t namelen = __arraycount(name);
42361.95Skamil	ki_sigset_t kp_sigmask;
42371.95Skamil	ki_sigset_t kp_sigignore;
42381.1Skamil
42391.1Skamil#if defined(__arm__)
42401.1Skamil	/* PT_STEP not supported on arm 32-bit */
42411.1Skamil	atf_tc_expect_fail("PR kern/52119");
42421.1Skamil#endif
42431.1Skamil
42441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42461.1Skamil	if (child == 0) {
42471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42491.1Skamil
42501.95Skamil		if (masked) {
42511.95Skamil			sigemptyset(&intmask);
42521.95Skamil			sigaddset(&intmask, SIGTRAP);
42531.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
42541.95Skamil		}
42551.95Skamil
42561.95Skamil		if (ignored) {
42571.95Skamil			memset(&sa, 0, sizeof(sa));
42581.95Skamil			sa.sa_handler = SIG_IGN;
42591.95Skamil			sigemptyset(&sa.sa_mask);
42601.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
42611.95Skamil		}
42621.95Skamil
42631.1Skamil		happy = check_happy(999);
42641.1Skamil
42651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42671.1Skamil
42681.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
42691.1Skamil
42701.13Schristos		DPRINTF("Before exiting of the child process\n");
42711.1Skamil		_exit(exitval);
42721.1Skamil	}
42731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42741.1Skamil
42751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42771.1Skamil
42781.1Skamil	validate_status_stopped(status, sigval);
42791.1Skamil
42801.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
42811.81Skamil	SYSCALL_REQUIRE(
42821.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
42831.81Skamil
42841.81Skamil	DPRINTF("Before checking siginfo_t\n");
42851.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
42861.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
42871.81Skamil
42881.95Skamil	name[0] = CTL_KERN,
42891.95Skamil	name[1] = KERN_PROC2,
42901.95Skamil	name[2] = KERN_PROC_PID;
42911.95Skamil	name[3] = child;
42921.95Skamil	name[4] = sizeof(kp);
42931.95Skamil	name[5] = 1;
42941.95Skamil
42951.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
42961.95Skamil
42971.95Skamil	if (masked)
42981.95Skamil		kp_sigmask = kp.p_sigmask;
42991.95Skamil
43001.95Skamil	if (ignored)
43011.95Skamil		kp_sigignore = kp.p_sigignore;
43021.95Skamil
43031.1Skamil	while (N --> 0) {
43041.2Skamil		if (setstep) {
43051.13Schristos			DPRINTF("Before resuming the child process where it "
43061.2Skamil			    "left off and without signal to be sent (use "
43071.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
43081.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
43091.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
43101.2Skamil			    != -1);
43111.2Skamil		} else {
43121.13Schristos			DPRINTF("Before resuming the child process where it "
43131.2Skamil			    "left off and without signal to be sent (use "
43141.2Skamil			    "PT_STEP)\n");
43151.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
43161.2Skamil			    != -1);
43171.2Skamil		}
43181.1Skamil
43191.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43201.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
43211.1Skamil		    child);
43221.1Skamil
43231.1Skamil		validate_status_stopped(status, SIGTRAP);
43241.2Skamil
43251.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
43261.81Skamil		SYSCALL_REQUIRE(
43271.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
43281.81Skamil
43291.81Skamil		DPRINTF("Before checking siginfo_t\n");
43301.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
43311.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
43321.81Skamil
43331.2Skamil		if (setstep) {
43341.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
43351.2Skamil		}
43361.95Skamil
43371.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
43381.95Skamil
43391.95Skamil		if (masked) {
43401.95Skamil			DPRINTF("kp_sigmask="
43411.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
43421.95Skamil			    PRIx32 "\n",
43431.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
43441.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
43451.95Skamil
43461.95Skamil			DPRINTF("kp.p_sigmask="
43471.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
43481.95Skamil			    PRIx32 "\n",
43491.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
43501.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
43511.95Skamil
43521.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
43531.95Skamil			    sizeof(kp_sigmask)));
43541.95Skamil		}
43551.95Skamil
43561.95Skamil		if (ignored) {
43571.95Skamil			DPRINTF("kp_sigignore="
43581.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
43591.95Skamil			    PRIx32 "\n",
43601.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
43611.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
43621.95Skamil
43631.95Skamil			DPRINTF("kp.p_sigignore="
43641.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
43651.95Skamil			    PRIx32 "\n",
43661.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
43671.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
43681.95Skamil
43691.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
43701.95Skamil			    sizeof(kp_sigignore)));
43711.95Skamil		}
43721.1Skamil	}
43731.1Skamil
43741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43751.1Skamil	    "without signal to be sent\n");
43761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43771.1Skamil
43781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43801.1Skamil
43811.1Skamil	validate_status_exited(status, exitval);
43821.1Skamil
43831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43851.1Skamil}
43861.1Skamil
43871.73Skamil#define PTRACE_STEP(test, N, setstep)					\
43881.73SkamilATF_TC(test);								\
43891.73SkamilATF_TC_HEAD(test, tc)							\
43901.73Skamil{									\
43911.73Skamil        atf_tc_set_md_var(tc, "descr",					\
43921.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
43931.73Skamil}									\
43941.73Skamil									\
43951.73SkamilATF_TC_BODY(test, tc)							\
43961.73Skamil{									\
43971.73Skamil									\
43981.95Skamil        ptrace_step(N, setstep, false, false);				\
43991.1Skamil}
44001.1Skamil
44011.73SkamilPTRACE_STEP(step1, 1, 0)
44021.73SkamilPTRACE_STEP(step2, 2, 0)
44031.73SkamilPTRACE_STEP(step3, 3, 0)
44041.73SkamilPTRACE_STEP(step4, 4, 0)
44051.73SkamilPTRACE_STEP(setstep1, 1, 1)
44061.73SkamilPTRACE_STEP(setstep2, 2, 1)
44071.73SkamilPTRACE_STEP(setstep3, 3, 1)
44081.73SkamilPTRACE_STEP(setstep4, 4, 1)
44091.95Skamil
44101.95SkamilATF_TC(step_signalmasked);
44111.95SkamilATF_TC_HEAD(step_signalmasked, tc)
44121.95Skamil{
44131.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
44141.95Skamil}
44151.95Skamil
44161.95SkamilATF_TC_BODY(step_signalmasked, tc)
44171.95Skamil{
44181.95Skamil
44191.95Skamil	ptrace_step(1, 0, true, false);
44201.95Skamil}
44211.95Skamil
44221.95SkamilATF_TC(step_signalignored);
44231.95SkamilATF_TC_HEAD(step_signalignored, tc)
44241.95Skamil{
44251.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
44261.95Skamil}
44271.95Skamil
44281.95SkamilATF_TC_BODY(step_signalignored, tc)
44291.95Skamil{
44301.95Skamil
44311.95Skamil	ptrace_step(1, 0, false, true);
44321.95Skamil}
44331.1Skamil#endif
44341.1Skamil
44351.73Skamil/// ----------------------------------------------------------------------------
44361.1Skamil
44371.75Skamilstatic void
44381.75Skamilptrace_kill(const char *type)
44391.1Skamil{
44401.75Skamil	const int sigval = SIGSTOP;
44411.1Skamil	pid_t child, wpid;
44421.1Skamil#if defined(TWAIT_HAVE_STATUS)
44431.1Skamil	int status;
44441.1Skamil#endif
44451.1Skamil
44461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44481.1Skamil	if (child == 0) {
44491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44511.1Skamil
44521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44541.1Skamil
44551.1Skamil		/* NOTREACHED */
44561.1Skamil		FORKEE_ASSERTX(0 &&
44571.1Skamil		    "Child should be terminated by a signal from its parent");
44581.1Skamil	}
44591.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44601.1Skamil
44611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44631.1Skamil
44641.1Skamil	validate_status_stopped(status, sigval);
44651.1Skamil
44661.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
44671.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
44681.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
44691.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
44701.75Skamil		kill(child, SIGKILL);
44711.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
44721.75Skamil		setpgid(child, 0);
44731.75Skamil		killpg(getpgid(child), SIGKILL);
44741.75Skamil	}
44751.1Skamil
44761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44781.1Skamil
44791.75Skamil	validate_status_signaled(status, SIGKILL, 0);
44801.1Skamil
44811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44831.1Skamil}
44841.1Skamil
44851.75Skamil#define PTRACE_KILL(test, type)						\
44861.75SkamilATF_TC(test);								\
44871.75SkamilATF_TC_HEAD(test, tc)							\
44881.75Skamil{									\
44891.75Skamil        atf_tc_set_md_var(tc, "descr",					\
44901.75Skamil            "Verify killing the child with " type);			\
44911.75Skamil}									\
44921.75Skamil									\
44931.75SkamilATF_TC_BODY(test, tc)							\
44941.75Skamil{									\
44951.75Skamil									\
44961.75Skamil        ptrace_kill(type);						\
44971.1Skamil}
44981.1Skamil
44991.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
45001.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
45011.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
45021.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
45031.1Skamil
45041.75Skamil/// ----------------------------------------------------------------------------
45051.1Skamil
45061.77Skamilstatic void
45071.77Skamiltraceme_lwpinfo(const int threads)
45081.1Skamil{
45091.1Skamil	const int sigval = SIGSTOP;
45101.77Skamil	const int sigval2 = SIGINT;
45111.1Skamil	pid_t child, wpid;
45121.1Skamil#if defined(TWAIT_HAVE_STATUS)
45131.1Skamil	int status;
45141.1Skamil#endif
45151.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
45161.77Skamil	struct ptrace_siginfo info;
45171.77Skamil
45181.77Skamil	/* Maximum number of supported threads in this test */
45191.77Skamil	pthread_t t[3];
45201.77Skamil	int n, rv;
45211.77Skamil
45221.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
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.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45321.1Skamil
45331.77Skamil		for (n = 0; n < threads; n++) {
45341.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
45351.77Skamil			FORKEE_ASSERT(rv == 0);
45361.77Skamil		}
45371.77Skamil
45381.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
45391.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
45401.77Skamil
45411.77Skamil		/* NOTREACHED */
45421.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
45431.1Skamil	}
45441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45451.1Skamil
45461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45481.1Skamil
45491.1Skamil	validate_status_stopped(status, sigval);
45501.1Skamil
45511.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
45521.77Skamil	SYSCALL_REQUIRE(
45531.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45541.77Skamil
45551.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45561.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
45571.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45581.77Skamil	    info.psi_siginfo.si_errno);
45591.77Skamil
45601.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
45611.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
45621.77Skamil
45631.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
45641.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
45651.1Skamil
45661.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
45671.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
45681.1Skamil
45691.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
45701.77Skamil	    lwp.pl_lwpid);
45711.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
45721.1Skamil
45731.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
45741.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
45751.1Skamil
45761.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
45771.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
45781.1Skamil
45791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45801.1Skamil	    "without signal to be sent\n");
45811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45821.1Skamil
45831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45851.1Skamil
45861.77Skamil	validate_status_stopped(status, sigval2);
45871.77Skamil
45881.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
45891.77Skamil	SYSCALL_REQUIRE(
45901.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45911.77Skamil
45921.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45931.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
45941.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45951.77Skamil	    info.psi_siginfo.si_errno);
45961.77Skamil
45971.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
45981.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
45991.77Skamil
46001.77Skamil	memset(&lwp, 0, sizeof(lwp));
46011.77Skamil
46021.77Skamil	for (n = 0; n <= threads; n++) {
46031.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46041.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
46051.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
46061.77Skamil
46071.77Skamil		DPRINTF("Assert that the thread exists\n");
46081.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
46091.77Skamil
46101.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
46111.77Skamil		    lwp.pl_lwpid);
46121.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
46131.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
46141.77Skamil	}
46151.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46161.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
46171.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
46181.77Skamil
46191.77Skamil	DPRINTF("Assert that there are no more threads\n");
46201.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
46211.77Skamil
46221.77Skamil	DPRINTF("Before resuming the child process where it left off and "
46231.77Skamil	    "without signal to be sent\n");
46241.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
46251.77Skamil
46261.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46271.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46281.77Skamil
46291.77Skamil	validate_status_signaled(status, SIGKILL, 0);
46301.1Skamil
46311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46331.1Skamil}
46341.1Skamil
46351.77Skamil#define TRACEME_LWPINFO(test, threads)					\
46361.77SkamilATF_TC(test);								\
46371.77SkamilATF_TC_HEAD(test, tc)							\
46381.77Skamil{									\
46391.77Skamil	atf_tc_set_md_var(tc, "descr",					\
46401.77Skamil	    "Verify LWPINFO with the child with " #threads		\
46411.77Skamil	    " spawned extra threads");					\
46421.77Skamil}									\
46431.77Skamil									\
46441.77SkamilATF_TC_BODY(test, tc)							\
46451.77Skamil{									\
46461.77Skamil									\
46471.77Skamil	traceme_lwpinfo(threads);					\
46481.1Skamil}
46491.1Skamil
46501.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
46511.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
46521.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
46531.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
46541.77Skamil
46551.77Skamil/// ----------------------------------------------------------------------------
46561.77Skamil
46571.77Skamil#if defined(TWAIT_HAVE_PID)
46581.77Skamilstatic void
46591.77Skamilattach_lwpinfo(const int threads)
46601.1Skamil{
46611.77Skamil	const int sigval = SIGINT;
46621.1Skamil	struct msg_fds parent_tracee, parent_tracer;
46631.1Skamil	const int exitval_tracer = 10;
46641.1Skamil	pid_t tracee, tracer, wpid;
46651.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
46661.1Skamil#if defined(TWAIT_HAVE_STATUS)
46671.1Skamil	int status;
46681.1Skamil#endif
46691.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
46701.77Skamil	struct ptrace_siginfo info;
46711.77Skamil
46721.77Skamil	/* Maximum number of supported threads in this test */
46731.77Skamil	pthread_t t[3];
46741.77Skamil	int n, rv;
46751.1Skamil
46761.13Schristos	DPRINTF("Spawn tracee\n");
46771.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
46781.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
46791.1Skamil	tracee = atf_utils_fork();
46801.1Skamil	if (tracee == 0) {
46811.1Skamil		/* Wait for message from the parent */
46821.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
46831.1Skamil
46841.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
46851.77Skamil
46861.77Skamil		for (n = 0; n < threads; n++) {
46871.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
46881.77Skamil			FORKEE_ASSERT(rv == 0);
46891.77Skamil		}
46901.77Skamil
46911.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
46921.77Skamil
46931.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46941.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46951.77Skamil
46961.77Skamil		/* NOTREACHED */
46971.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
46981.1Skamil	}
46991.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
47001.1Skamil
47011.13Schristos	DPRINTF("Spawn debugger\n");
47021.1Skamil	tracer = atf_utils_fork();
47031.1Skamil	if (tracer == 0) {
47041.1Skamil		/* No IPC to communicate with the child */
47051.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
47061.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
47071.1Skamil
47081.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
47091.1Skamil		FORKEE_REQUIRE_SUCCESS(
47101.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47111.1Skamil
47121.1Skamil		forkee_status_stopped(status, SIGSTOP);
47131.1Skamil
47141.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
47151.77Skamil		    "tracee");
47161.77Skamil		FORKEE_ASSERT(
47171.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
47181.77Skamil
47191.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47201.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
47211.77Skamil		    "si_errno=%#x\n",
47221.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47231.77Skamil		    info.psi_siginfo.si_errno);
47241.77Skamil
47251.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
47261.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
47271.77Skamil
47281.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47291.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
47301.1Skamil		    != -1);
47311.1Skamil
47321.13Schristos		DPRINTF("Assert that there exists a thread\n");
47331.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
47341.1Skamil
47351.13Schristos		DPRINTF("Assert that lwp thread %d received event "
47361.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
47371.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
47381.1Skamil
47391.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
47401.77Skamil		    "tracee\n");
47411.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
47421.1Skamil		    != -1);
47431.1Skamil
47441.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
47451.77Skamil		    "tracee\n");
47461.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
47471.1Skamil
47481.1Skamil		/* Resume tracee with PT_CONTINUE */
47491.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
47501.1Skamil
47511.1Skamil		/* Inform parent that tracer has attached to tracee */
47521.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
47531.77Skamil
47541.1Skamil		/* Wait for parent */
47551.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
47561.1Skamil
47571.77Skamil		/* Wait for tracee and assert that it raised a signal */
47581.77Skamil		FORKEE_REQUIRE_SUCCESS(
47591.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47601.77Skamil
47611.77Skamil		forkee_status_stopped(status, SIGINT);
47621.77Skamil
47631.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
47641.77Skamil		    "child");
47651.77Skamil		FORKEE_ASSERT(
47661.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
47671.77Skamil
47681.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47691.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
47701.77Skamil		    "si_errno=%#x\n",
47711.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47721.77Skamil		    info.psi_siginfo.si_errno);
47731.77Skamil
47741.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
47751.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
47761.77Skamil
47771.77Skamil		memset(&lwp, 0, sizeof(lwp));
47781.77Skamil
47791.77Skamil		for (n = 0; n <= threads; n++) {
47801.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
47811.77Skamil			    "child\n");
47821.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
47831.77Skamil			    sizeof(lwp)) != -1);
47841.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
47851.77Skamil
47861.77Skamil			DPRINTF("Assert that the thread exists\n");
47871.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
47881.77Skamil
47891.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
47901.77Skamil			    "event\n", lwp.pl_lwpid);
47911.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
47921.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
47931.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
47941.77Skamil		}
47951.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
47961.77Skamil		    "tracee\n");
47971.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
47981.77Skamil		    != -1);
47991.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
48001.77Skamil
48011.77Skamil		DPRINTF("Assert that there are no more threads\n");
48021.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
48031.77Skamil
48041.77Skamil		DPRINTF("Before resuming the child process where it left off "
48051.77Skamil		    "and without signal to be sent\n");
48061.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
48071.77Skamil		    != -1);
48081.77Skamil
48091.1Skamil		/* Wait for tracee and assert that it exited */
48101.1Skamil		FORKEE_REQUIRE_SUCCESS(
48111.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
48121.1Skamil
48131.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
48141.1Skamil
48151.13Schristos		DPRINTF("Before exiting of the tracer process\n");
48161.1Skamil		_exit(exitval_tracer);
48171.1Skamil	}
48181.1Skamil
48191.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
48201.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
48211.1Skamil
48221.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
48231.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
48241.77Skamil
48251.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
48261.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
48271.1Skamil
48281.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
48291.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
48301.1Skamil
48311.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
48321.1Skamil	    TWAIT_FNAME);
48331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
48341.1Skamil	    tracer);
48351.1Skamil
48361.1Skamil	validate_status_exited(status, exitval_tracer);
48371.1Skamil
48381.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
48391.1Skamil	    TWAIT_FNAME);
48401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
48411.1Skamil	    tracee);
48421.1Skamil
48431.77Skamil	validate_status_signaled(status, SIGKILL, 0);
48441.1Skamil
48451.1Skamil	msg_close(&parent_tracer);
48461.1Skamil	msg_close(&parent_tracee);
48471.1Skamil}
48481.77Skamil
48491.77Skamil#define ATTACH_LWPINFO(test, threads)					\
48501.77SkamilATF_TC(test);								\
48511.77SkamilATF_TC_HEAD(test, tc)							\
48521.77Skamil{									\
48531.77Skamil	atf_tc_set_md_var(tc, "descr",					\
48541.77Skamil	    "Verify LWPINFO with the child with " #threads		\
48551.77Skamil	    " spawned extra threads (tracer is not the original "	\
48561.77Skamil	    "parent)");							\
48571.77Skamil}									\
48581.77Skamil									\
48591.77SkamilATF_TC_BODY(test, tc)							\
48601.77Skamil{									\
48611.77Skamil									\
48621.77Skamil	attach_lwpinfo(threads);					\
48631.77Skamil}
48641.77Skamil
48651.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
48661.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
48671.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
48681.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
48691.1Skamil#endif
48701.1Skamil
48711.77Skamil/// ----------------------------------------------------------------------------
48721.77Skamil
48731.1Skamilstatic void
48741.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
48751.1Skamil{
48761.1Skamil	const int exitval = 5;
48771.1Skamil	const int sigval = SIGINT;
48781.1Skamil	const int sigfaked = SIGTRAP;
48791.1Skamil	const int sicodefaked = TRAP_BRKPT;
48801.1Skamil	pid_t child, wpid;
48811.1Skamil	struct sigaction sa;
48821.1Skamil#if defined(TWAIT_HAVE_STATUS)
48831.1Skamil	int status;
48841.1Skamil#endif
48851.1Skamil	struct ptrace_siginfo info;
48861.1Skamil	memset(&info, 0, sizeof(info));
48871.1Skamil
48881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48901.1Skamil	if (child == 0) {
48911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48931.1Skamil
48941.79Skamil		sa.sa_sigaction = sah;
48951.1Skamil		sa.sa_flags = SA_SIGINFO;
48961.1Skamil		sigemptyset(&sa.sa_mask);
48971.1Skamil
48981.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
48991.79Skamil		    != -1);
49001.1Skamil
49011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49031.1Skamil
49041.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
49051.1Skamil
49061.13Schristos		DPRINTF("Before exiting of the child process\n");
49071.1Skamil		_exit(exitval);
49081.1Skamil	}
49091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49101.1Skamil
49111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49131.1Skamil
49141.1Skamil	validate_status_stopped(status, sigval);
49151.1Skamil
49161.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49171.61Skre	SYSCALL_REQUIRE(
49181.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49191.1Skamil
49201.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49211.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49221.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49231.1Skamil	    info.psi_siginfo.si_errno);
49241.1Skamil
49251.79Skamil	if (faked) {
49261.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
49271.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
49281.79Skamil		info.psi_siginfo.si_signo = sigfaked;
49291.79Skamil		info.psi_siginfo.si_code = sicodefaked;
49301.79Skamil	}
49311.1Skamil
49321.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49331.61Skre	SYSCALL_REQUIRE(
49341.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
49351.1Skamil
49361.79Skamil	if (faked) {
49371.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
49381.79Skamil		    "child\n");
49391.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
49401.79Skamil		    sizeof(info)) != -1);
49411.1Skamil
49421.79Skamil		DPRINTF("Before checking siginfo_t\n");
49431.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
49441.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
49451.79Skamil	}
49461.1Skamil
49471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49481.1Skamil	    "without signal to be sent\n");
49491.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
49501.79Skamil	    faked ? sigfaked : sigval) != -1);
49511.1Skamil
49521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49541.1Skamil
49551.1Skamil	validate_status_exited(status, exitval);
49561.1Skamil
49571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49591.1Skamil}
49601.1Skamil
49611.79Skamil#define PTRACE_SIGINFO(test, faked)					\
49621.79SkamilATF_TC(test);								\
49631.79SkamilATF_TC_HEAD(test, tc)							\
49641.79Skamil{									\
49651.79Skamil	atf_tc_set_md_var(tc, "descr",					\
49661.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
49671.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
49681.79Skamil}									\
49691.79Skamil									\
49701.79Skamilstatic int test##_caught = 0;						\
49711.79Skamil									\
49721.79Skamilstatic void								\
49731.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
49741.79Skamil{									\
49751.79Skamil	if (faked) {							\
49761.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
49771.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
49781.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
49791.79Skamil	} else {							\
49801.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
49811.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
49821.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
49831.79Skamil	}								\
49841.79Skamil									\
49851.79Skamil	++ test##_caught;						\
49861.79Skamil}									\
49871.79Skamil									\
49881.79SkamilATF_TC_BODY(test, tc)							\
49891.79Skamil{									\
49901.79Skamil									\
49911.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
49921.79Skamil}
49931.79Skamil
49941.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
49951.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
49961.79Skamil
49971.79Skamil/// ----------------------------------------------------------------------------
49981.79Skamil
49991.97Skamilstatic void
50001.97Skamiltraceme_exec(bool masked, bool ignored)
50011.1Skamil{
50021.1Skamil	const int sigval = SIGTRAP;
50031.1Skamil	pid_t child, wpid;
50041.1Skamil#if defined(TWAIT_HAVE_STATUS)
50051.1Skamil	int status;
50061.1Skamil#endif
50071.97Skamil	struct sigaction sa;
50081.97Skamil	struct ptrace_siginfo info;
50091.97Skamil	sigset_t intmask;
50101.97Skamil	struct kinfo_proc2 kp;
50111.97Skamil	size_t len = sizeof(kp);
50121.97Skamil
50131.97Skamil	int name[6];
50141.97Skamil	const size_t namelen = __arraycount(name);
50151.97Skamil	ki_sigset_t kp_sigmask;
50161.97Skamil	ki_sigset_t kp_sigignore;
50171.1Skamil
50181.1Skamil	memset(&info, 0, sizeof(info));
50191.1Skamil
50201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50221.1Skamil	if (child == 0) {
50231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50251.1Skamil
50261.97Skamil		if (masked) {
50271.97Skamil			sigemptyset(&intmask);
50281.97Skamil			sigaddset(&intmask, sigval);
50291.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
50301.97Skamil		}
50311.97Skamil
50321.97Skamil		if (ignored) {
50331.97Skamil			memset(&sa, 0, sizeof(sa));
50341.97Skamil			sa.sa_handler = SIG_IGN;
50351.97Skamil			sigemptyset(&sa.sa_mask);
50361.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
50371.97Skamil		}
50381.97Skamil
50391.13Schristos		DPRINTF("Before calling execve(2) from child\n");
50401.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
50411.1Skamil
50421.1Skamil		FORKEE_ASSERT(0 && "Not reached");
50431.1Skamil	}
50441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50451.1Skamil
50461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50481.1Skamil
50491.1Skamil	validate_status_stopped(status, sigval);
50501.1Skamil
50511.97Skamil	name[0] = CTL_KERN,
50521.97Skamil	name[1] = KERN_PROC2,
50531.97Skamil	name[2] = KERN_PROC_PID;
50541.97Skamil	name[3] = getpid();
50551.97Skamil	name[4] = sizeof(kp);
50561.97Skamil	name[5] = 1;
50571.97Skamil
50581.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
50591.97Skamil
50601.97Skamil	if (masked)
50611.97Skamil		kp_sigmask = kp.p_sigmask;
50621.97Skamil
50631.97Skamil	if (ignored)
50641.97Skamil		kp_sigignore = kp.p_sigignore;
50651.97Skamil
50661.97Skamil	name[3] = getpid();
50671.97Skamil
50681.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
50691.97Skamil
50701.97Skamil	if (masked) {
50711.97Skamil		DPRINTF("kp_sigmask="
50721.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
50731.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
50741.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
50751.97Skamil
50761.97Skamil		DPRINTF("kp.p_sigmask="
50771.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
50781.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
50791.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
50801.97Skamil
50811.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
50821.97Skamil		    sizeof(kp_sigmask)));
50831.97Skamil	}
50841.97Skamil
50851.97Skamil	if (ignored) {
50861.97Skamil		DPRINTF("kp_sigignore="
50871.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
50881.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
50891.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
50901.97Skamil
50911.97Skamil		DPRINTF("kp.p_sigignore="
50921.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
50931.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
50941.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
50951.97Skamil
50961.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
50971.97Skamil		    sizeof(kp_sigignore)));
50981.97Skamil	}
50991.97Skamil
51001.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51011.61Skre	SYSCALL_REQUIRE(
51021.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51031.1Skamil
51041.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
51051.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
51061.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
51071.1Skamil	    info.psi_siginfo.si_errno);
51081.1Skamil
51091.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
51101.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
51111.1Skamil
51121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51131.1Skamil	    "without signal to be sent\n");
51141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51151.1Skamil
51161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51181.1Skamil
51191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51211.1Skamil}
51221.1Skamil
51231.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
51241.97SkamilATF_TC(test);								\
51251.97SkamilATF_TC_HEAD(test, tc)							\
51261.97Skamil{									\
51271.97Skamil       atf_tc_set_md_var(tc, "descr",					\
51281.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
51291.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
51301.97Skamil           masked ? " with ignored signal" : "");			\
51311.97Skamil}									\
51321.97Skamil									\
51331.97SkamilATF_TC_BODY(test, tc)							\
51341.97Skamil{									\
51351.97Skamil									\
51361.97Skamil       traceme_exec(masked, ignored);					\
51371.97Skamil}
51381.97Skamil
51391.97SkamilTRACEME_EXEC(traceme_exec, false, false)
51401.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
51411.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
51421.97Skamil
51431.82Skamil/// ----------------------------------------------------------------------------
51441.82Skamil
51451.83Skamilstatic volatile int done;
51461.1Skamil
51471.83Skamilstatic void *
51481.83Skamiltrace_threads_cb(void *arg __unused)
51491.1Skamil{
51501.1Skamil
51511.83Skamil	done++;
51521.83Skamil
51531.83Skamil	while (done < 3)
51541.83Skamil		continue;
51551.83Skamil
51561.83Skamil	return NULL;
51571.1Skamil}
51581.1Skamil
51591.83Skamilstatic void
51601.83Skamiltrace_threads(bool trace_create, bool trace_exit)
51611.1Skamil{
51621.1Skamil	const int sigval = SIGSTOP;
51631.1Skamil	pid_t child, wpid;
51641.1Skamil#if defined(TWAIT_HAVE_STATUS)
51651.1Skamil	int status;
51661.1Skamil#endif
51671.1Skamil	ptrace_state_t state;
51681.1Skamil	const int slen = sizeof(state);
51691.1Skamil	ptrace_event_t event;
51701.1Skamil	const int elen = sizeof(event);
51711.83Skamil	struct ptrace_siginfo info;
51721.83Skamil
51731.83Skamil	pthread_t t[3];
51741.83Skamil	int rv;
51751.83Skamil	size_t n;
51761.1Skamil	lwpid_t lid;
51771.83Skamil
51781.83Skamil	/* Track created and exited threads */
51791.83Skamil	bool traced_lwps[__arraycount(t)];
51801.83Skamil
51811.83Skamil	atf_tc_skip("PR kern/51995");
51821.1Skamil
51831.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51841.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51851.1Skamil	if (child == 0) {
51861.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51871.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51881.1Skamil
51891.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51901.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51911.1Skamil
51921.83Skamil		for (n = 0; n < __arraycount(t); n++) {
51931.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
51941.83Skamil			    NULL);
51951.83Skamil			FORKEE_ASSERT(rv == 0);
51961.83Skamil		}
51971.1Skamil
51981.83Skamil		for (n = 0; n < __arraycount(t); n++) {
51991.83Skamil			rv = pthread_join(t[n], NULL);
52001.83Skamil			FORKEE_ASSERT(rv == 0);
52011.83Skamil		}
52021.1Skamil
52031.83Skamil		/*
52041.83Skamil		 * There is race between _exit() and pthread_join() detaching
52051.83Skamil		 * a thread. For simplicity kill the process after detecting
52061.83Skamil		 * LWP events.
52071.83Skamil		 */
52081.83Skamil		while (true)
52091.83Skamil			continue;
52101.1Skamil
52111.83Skamil		FORKEE_ASSERT(0 && "Not reached");
52121.1Skamil	}
52131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52141.1Skamil
52151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52171.1Skamil
52181.1Skamil	validate_status_stopped(status, sigval);
52191.1Skamil
52201.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52211.83Skamil	SYSCALL_REQUIRE(
52221.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52231.1Skamil
52241.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
52251.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
52261.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
52271.83Skamil	    info.psi_siginfo.si_errno);
52281.1Skamil
52291.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
52301.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
52311.1Skamil
52321.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
52331.83Skamil	memset(&event, 0, sizeof(event));
52341.83Skamil	if (trace_create)
52351.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
52361.83Skamil	if (trace_exit)
52371.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
52381.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
52391.1Skamil
52401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52411.1Skamil	    "without signal to be sent\n");
52421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52431.1Skamil
52441.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
52451.1Skamil
52461.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
52471.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
52481.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
52491.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
52501.83Skamil		    child);
52511.1Skamil
52521.83Skamil		validate_status_stopped(status, SIGTRAP);
52531.1Skamil
52541.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
52551.83Skamil		    "child\n");
52561.83Skamil		SYSCALL_REQUIRE(
52571.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52581.1Skamil
52591.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
52601.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
52611.83Skamil		    "si_errno=%#x\n",
52621.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
52631.83Skamil		    info.psi_siginfo.si_errno);
52641.1Skamil
52651.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
52661.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
52671.1Skamil
52681.83Skamil		SYSCALL_REQUIRE(
52691.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
52701.1Skamil
52711.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
52721.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
52731.1Skamil
52741.83Skamil		lid = state.pe_lwp;
52751.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
52761.1Skamil
52771.83Skamil		traced_lwps[lid - 1] = true;
52781.1Skamil
52791.83Skamil		DPRINTF("Before resuming the child process where it left off "
52801.83Skamil		    "and without signal to be sent\n");
52811.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52821.83Skamil	}
52831.1Skamil
52841.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
52851.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
52861.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
52871.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
52881.83Skamil		    child);
52891.1Skamil
52901.83Skamil		validate_status_stopped(status, SIGTRAP);
52911.1Skamil
52921.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
52931.83Skamil		    "child\n");
52941.83Skamil		SYSCALL_REQUIRE(
52951.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52961.1Skamil
52971.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
52981.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
52991.83Skamil		    "si_errno=%#x\n",
53001.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
53011.83Skamil		    info.psi_siginfo.si_errno);
53021.1Skamil
53031.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
53041.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
53051.1Skamil
53061.83Skamil		SYSCALL_REQUIRE(
53071.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
53081.1Skamil
53091.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
53101.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
53111.1Skamil
53121.83Skamil		lid = state.pe_lwp;
53131.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
53141.1Skamil
53151.83Skamil		if (trace_create) {
53161.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
53171.83Skamil			traced_lwps[lid - 1] = false;
53181.83Skamil		}
53191.1Skamil
53201.83Skamil		DPRINTF("Before resuming the child process where it left off "
53211.83Skamil		    "and without signal to be sent\n");
53221.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53231.83Skamil	}
53241.1Skamil
53251.83Skamil	kill(child, SIGKILL);
53261.1Skamil
53271.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53281.1Skamil	    TWAIT_FNAME);
53291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53301.1Skamil
53311.83Skamil	validate_status_signaled(status, SIGKILL, 0);
53321.1Skamil
53331.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53341.1Skamil	    TWAIT_FNAME);
53351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53361.1Skamil}
53371.1Skamil
53381.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
53391.83SkamilATF_TC(test);								\
53401.83SkamilATF_TC_HEAD(test, tc)							\
53411.83Skamil{									\
53421.83Skamil        atf_tc_set_md_var(tc, "descr",					\
53431.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
53441.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
53451.83Skamil	    trace_exit ? "" : "out");					\
53461.83Skamil}									\
53471.83Skamil									\
53481.83SkamilATF_TC_BODY(test, tc)							\
53491.83Skamil{									\
53501.83Skamil									\
53511.83Skamil        trace_threads(trace_create, trace_exit);			\
53521.83Skamil}
53531.83Skamil
53541.83SkamilTRACE_THREADS(trace_thread1, false, false)
53551.83SkamilTRACE_THREADS(trace_thread2, false, true)
53561.83SkamilTRACE_THREADS(trace_thread3, true, false)
53571.83SkamilTRACE_THREADS(trace_thread4, true, true)
53581.83Skamil
53591.83Skamil/// ----------------------------------------------------------------------------
53601.83Skamil
53611.84SkamilATF_TC(signal_mask_unrelated);
53621.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
53631.1Skamil{
53641.1Skamil	atf_tc_set_md_var(tc, "descr",
53651.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
53661.1Skamil	    "from catching other signals");
53671.1Skamil}
53681.1Skamil
53691.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
53701.1Skamil{
53711.1Skamil	const int exitval = 5;
53721.1Skamil	const int sigval = SIGSTOP;
53731.1Skamil	const int sigmasked = SIGTRAP;
53741.1Skamil	const int signotmasked = SIGINT;
53751.1Skamil	pid_t child, wpid;
53761.1Skamil#if defined(TWAIT_HAVE_STATUS)
53771.1Skamil	int status;
53781.1Skamil#endif
53791.1Skamil	sigset_t intmask;
53801.1Skamil
53811.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53821.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53831.1Skamil	if (child == 0) {
53841.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53851.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53861.1Skamil
53871.1Skamil		sigemptyset(&intmask);
53881.1Skamil		sigaddset(&intmask, sigmasked);
53891.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
53901.1Skamil
53911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53931.1Skamil
53941.13Schristos		DPRINTF("Before raising %s from child\n",
53951.1Skamil		    strsignal(signotmasked));
53961.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
53971.1Skamil
53981.13Schristos		DPRINTF("Before exiting of the child process\n");
53991.1Skamil		_exit(exitval);
54001.1Skamil	}
54011.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54021.1Skamil
54031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54051.1Skamil
54061.1Skamil	validate_status_stopped(status, sigval);
54071.1Skamil
54081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54091.1Skamil	    "without signal to be sent\n");
54101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54111.1Skamil
54121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54141.1Skamil
54151.1Skamil	validate_status_stopped(status, signotmasked);
54161.1Skamil
54171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54181.1Skamil	    "without signal to be sent\n");
54191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54201.1Skamil
54211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54231.1Skamil
54241.1Skamil	validate_status_exited(status, exitval);
54251.1Skamil
54261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54271.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54281.1Skamil}
54291.1Skamil
54301.84Skamil/// ----------------------------------------------------------------------------
54311.84Skamil
54321.1Skamil#if defined(TWAIT_HAVE_PID)
54331.99Skamilstatic void
54341.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked,
54351.99Skamil           bool ignored)
54361.1Skamil{
54371.1Skamil	const int exitval = 5;
54381.1Skamil	const int exitval2 = 15;
54391.1Skamil	const int sigval = SIGSTOP;
54401.99Skamil	pid_t child, child2 = 0, wpid;
54411.1Skamil#if defined(TWAIT_HAVE_STATUS)
54421.1Skamil	int status;
54431.1Skamil#endif
54441.1Skamil	ptrace_state_t state;
54451.1Skamil	const int slen = sizeof(state);
54461.1Skamil	ptrace_event_t event;
54471.1Skamil	const int elen = sizeof(event);
54481.99Skamil	pid_t (*fn)(void);
54491.99Skamil	struct sigaction sa;
54501.99Skamil	struct ptrace_siginfo info;
54511.99Skamil	sigset_t intmask;
54521.99Skamil	struct kinfo_proc2 kp;
54531.99Skamil	size_t len = sizeof(kp);
54541.99Skamil
54551.99Skamil	int name[6];
54561.99Skamil	const size_t namelen = __arraycount(name);
54571.99Skamil	ki_sigset_t kp_sigmask;
54581.99Skamil	ki_sigset_t kp_sigignore;
54591.1Skamil
54601.99Skamil	if (trackfork)
54611.99Skamil		fn = fork;
54621.99Skamil	if (trackvfork || trackvforkdone)
54631.99Skamil		fn = vfork;
54641.14Schristos
54651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54671.1Skamil	if (child == 0) {
54681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54701.1Skamil
54711.99Skamil		if (masked) {
54721.99Skamil			sigemptyset(&intmask);
54731.99Skamil			sigaddset(&intmask, SIGTRAP);
54741.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
54751.99Skamil		}
54761.99Skamil
54771.99Skamil		if (ignored) {
54781.99Skamil			memset(&sa, 0, sizeof(sa));
54791.99Skamil			sa.sa_handler = SIG_IGN;
54801.99Skamil			sigemptyset(&sa.sa_mask);
54811.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
54821.99Skamil		}
54831.1Skamil
54841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54861.1Skamil
54871.99Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
54881.1Skamil
54891.1Skamil		if (child2 == 0)
54901.1Skamil			_exit(exitval2);
54911.1Skamil
54921.1Skamil		FORKEE_REQUIRE_SUCCESS
54931.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
54941.1Skamil
54951.1Skamil		forkee_status_exited(status, exitval2);
54961.1Skamil
54971.13Schristos		DPRINTF("Before exiting of the child process\n");
54981.1Skamil		_exit(exitval);
54991.1Skamil	}
55001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55011.1Skamil
55021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55041.1Skamil
55051.1Skamil	validate_status_stopped(status, sigval);
55061.1Skamil
55071.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55081.99Skamil	SYSCALL_REQUIRE(
55091.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55101.99Skamil
55111.99Skamil	DPRINTF("Before checking siginfo_t\n");
55121.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
55131.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
55141.1Skamil
55151.99Skamil	name[0] = CTL_KERN,
55161.99Skamil	name[1] = KERN_PROC2,
55171.99Skamil	name[2] = KERN_PROC_PID;
55181.99Skamil	name[3] = child;
55191.99Skamil	name[4] = sizeof(kp);
55201.99Skamil	name[5] = 1;
55211.1Skamil
55221.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
55231.1Skamil
55241.99Skamil	if (masked)
55251.99Skamil		kp_sigmask = kp.p_sigmask;
55261.1Skamil
55271.99Skamil	if (ignored)
55281.99Skamil		kp_sigignore = kp.p_sigignore;
55291.1Skamil
55301.99Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
55311.99Skamil	    trackfork ? "|PTRACE_FORK" : "",
55321.99Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
55331.99Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
55341.99Skamil	event.pe_set_event = 0;
55351.99Skamil	if (trackfork)
55361.99Skamil		event.pe_set_event |= PTRACE_FORK;
55371.99Skamil	if (trackvfork)
55381.99Skamil		event.pe_set_event |= PTRACE_VFORK;
55391.99Skamil	if (trackvforkdone)
55401.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
55411.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
55421.1Skamil
55431.99Skamil	DPRINTF("Before resuming the child process where it left off and "
55441.99Skamil	    "without signal to be sent\n");
55451.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55461.1Skamil
55471.99Skamil	if (trackfork || trackvfork) {
55481.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
55491.99Skamil		    child);
55501.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
55511.99Skamil		    child);
55521.1Skamil
55531.99Skamil		validate_status_stopped(status, SIGTRAP);
55541.1Skamil
55551.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
55561.1Skamil
55571.99Skamil		if (masked) {
55581.99Skamil			DPRINTF("kp_sigmask="
55591.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55601.99Skamil			    PRIx32 "\n",
55611.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
55621.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
55631.1Skamil
55641.99Skamil			DPRINTF("kp.p_sigmask="
55651.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55661.99Skamil			    PRIx32 "\n",
55671.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
55681.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
55691.1Skamil
55701.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
55711.99Skamil			    sizeof(kp_sigmask)));
55721.99Skamil		}
55731.1Skamil
55741.99Skamil		if (ignored) {
55751.99Skamil			DPRINTF("kp_sigignore="
55761.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55771.99Skamil			    PRIx32 "\n",
55781.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
55791.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
55801.1Skamil
55811.99Skamil			DPRINTF("kp.p_sigignore="
55821.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55831.99Skamil			    PRIx32 "\n",
55841.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
55851.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
55861.1Skamil
55871.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
55881.99Skamil			    sizeof(kp_sigignore)));
55891.99Skamil		}
55901.1Skamil
55911.99Skamil		SYSCALL_REQUIRE(
55921.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55931.99Skamil		if (trackfork) {
55941.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
55951.99Skamil			       PTRACE_FORK);
55961.99Skamil		}
55971.99Skamil		if (trackvfork) {
55981.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
55991.99Skamil			       PTRACE_VFORK);
56001.99Skamil		}
56011.1Skamil
56021.99Skamil		child2 = state.pe_other_pid;
56031.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
56041.1Skamil
56051.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
56061.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
56071.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
56081.99Skamil		    child2);
56091.1Skamil
56101.99Skamil		validate_status_stopped(status, SIGTRAP);
56111.1Skamil
56121.99Skamil		name[3] = child2;
56131.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
56141.1Skamil
56151.99Skamil		if (masked) {
56161.99Skamil			DPRINTF("kp_sigmask="
56171.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
56181.99Skamil			    PRIx32 "\n",
56191.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
56201.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
56211.1Skamil
56221.99Skamil			DPRINTF("kp.p_sigmask="
56231.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
56241.99Skamil			    PRIx32 "\n",
56251.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
56261.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
56271.14Schristos
56281.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
56291.99Skamil			    sizeof(kp_sigmask)));
56301.99Skamil		}
56311.1Skamil
56321.99Skamil		if (ignored) {
56331.99Skamil			DPRINTF("kp_sigignore="
56341.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
56351.99Skamil			    PRIx32 "\n",
56361.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
56371.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
56381.1Skamil
56391.99Skamil			DPRINTF("kp.p_sigignore="
56401.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
56411.99Skamil			    PRIx32 "\n",
56421.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
56431.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
56441.1Skamil
56451.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
56461.99Skamil			    sizeof(kp_sigignore)));
56471.99Skamil		}
56481.1Skamil
56491.99Skamil		SYSCALL_REQUIRE(
56501.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
56511.99Skamil		if (trackfork) {
56521.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
56531.99Skamil			       PTRACE_FORK);
56541.99Skamil		}
56551.99Skamil		if (trackvfork) {
56561.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
56571.99Skamil			       PTRACE_VFORK);
56581.99Skamil		}
56591.1Skamil
56601.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
56611.1Skamil
56621.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
56631.99Skamil		    "and without signal to be sent\n");
56641.99Skamil		SYSCALL_REQUIRE(
56651.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
56661.1Skamil
56671.99Skamil		DPRINTF("Before resuming the child process where it left off "
56681.99Skamil		    "and without signal to be sent\n");
56691.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56701.1Skamil	}
56711.1Skamil
56721.99Skamil	if (trackvforkdone) {
56731.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
56741.99Skamil		    child);
56751.99Skamil		TWAIT_REQUIRE_SUCCESS(
56761.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
56771.1Skamil
56781.99Skamil		validate_status_stopped(status, SIGTRAP);
56791.1Skamil
56801.99Skamil		name[3] = child;
56811.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
56821.1Skamil
56831.102Skamil		/*
56841.102Skamil		 * SIGCHLD is now pending in the signal queue and
56851.102Skamil		 * the kernel presents it to userland as a masked signal.
56861.102Skamil		 */
56871.102Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
56881.102Skamil
56891.99Skamil		if (masked) {
56901.99Skamil			DPRINTF("kp_sigmask="
56911.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
56921.99Skamil			    PRIx32 "\n",
56931.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
56941.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
56951.1Skamil
56961.99Skamil			DPRINTF("kp.p_sigmask="
56971.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
56981.99Skamil			    PRIx32 "\n",
56991.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
57001.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
57011.1Skamil
57021.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
57031.99Skamil			    sizeof(kp_sigmask)));
57041.99Skamil		}
57051.1Skamil
57061.99Skamil		if (ignored) {
57071.99Skamil			DPRINTF("kp_sigignore="
57081.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
57091.99Skamil			    PRIx32 "\n",
57101.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
57111.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
57121.1Skamil
57131.99Skamil			DPRINTF("kp.p_sigignore="
57141.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
57151.99Skamil			    PRIx32 "\n",
57161.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
57171.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
57181.1Skamil
57191.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
57201.99Skamil			    sizeof(kp_sigignore)));
57211.99Skamil		}
57221.1Skamil
57231.99Skamil		SYSCALL_REQUIRE(
57241.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
57251.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
57261.1Skamil
57271.99Skamil		child2 = state.pe_other_pid;
57281.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
57291.99Skamil		    child2);
57301.1Skamil
57311.99Skamil		DPRINTF("Before resuming the child process where it left off "
57321.99Skamil		    "and without signal to be sent\n");
57331.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57341.99Skamil	}
57351.1Skamil
57361.99Skamil	if (trackfork || trackvfork) {
57371.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
57381.99Skamil		    "\n", TWAIT_FNAME);
57391.99Skamil		TWAIT_REQUIRE_SUCCESS(
57401.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
57411.1Skamil
57421.99Skamil		validate_status_exited(status, exitval2);
57431.1Skamil
57441.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
57451.99Skamil		    "process\n", TWAIT_FNAME);
57461.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
57471.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
57481.99Skamil	}
57491.1Skamil
57501.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
57511.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
57521.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57531.1Skamil
57541.1Skamil	validate_status_stopped(status, SIGCHLD);
57551.1Skamil
57561.57Skamil	DPRINTF("Before resuming the child process where it left off and "
57571.1Skamil	    "without signal to be sent\n");
57581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57591.1Skamil
57601.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
57611.1Skamil	    TWAIT_FNAME);
57621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57631.1Skamil
57641.1Skamil	validate_status_exited(status, exitval);
57651.1Skamil
57661.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
57671.57Skamil	    TWAIT_FNAME);
57681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57691.1Skamil}
57701.1Skamil
57711.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone,		\
57721.99Skamil                   masked,ignored)					\
57731.99SkamilATF_TC(name);								\
57741.99SkamilATF_TC_HEAD(name, tc)							\
57751.99Skamil{									\
57761.99Skamil	atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught "	\
57771.99Skamil	    "regardless of signal %s%s", 				\
57781.99Skamil	    trackfork ? "PTRACE_FORK" : "",				\
57791.99Skamil	    trackvfork ? "PTRACE_VFORK" : "",				\
57801.99Skamil	    trackvforkdone ? "PTRACE_VFORK_DONE" : "",			\
57811.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
57821.99Skamil}									\
57831.99Skamil									\
57841.99SkamilATF_TC_BODY(name, tc)							\
57851.99Skamil{									\
57861.99Skamil									\
57871.99Skamil	fork2_body(trackfork, trackvfork, trackvforkdone, masked,	\
57881.99Skamil	           ignored);						\
57891.1Skamil}
57901.1Skamil
57911.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false)
57921.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true)
57931.110Skamil#if TEST_VFORK_ENABLED
57941.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false)
57951.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true)
57961.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false)
57971.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true)
57981.1Skamil#endif
57991.110Skamil#endif
58001.1Skamil
58011.99Skamil/// ----------------------------------------------------------------------------
58021.1Skamil
58031.83Skamilvolatile lwpid_t the_lwp_id = 0;
58041.83Skamil
58051.83Skamilstatic void
58061.83Skamillwp_main_func(void *arg)
58071.83Skamil{
58081.83Skamil	the_lwp_id = _lwp_self();
58091.83Skamil	_lwp_exit();
58101.83Skamil}
58111.83Skamil
58121.1SkamilATF_TC(signal9);
58131.1SkamilATF_TC_HEAD(signal9, tc)
58141.1Skamil{
58151.1Skamil	atf_tc_set_md_var(tc, "descr",
58161.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58171.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
58181.1Skamil}
58191.1Skamil
58201.1SkamilATF_TC_BODY(signal9, tc)
58211.1Skamil{
58221.1Skamil	const int exitval = 5;
58231.1Skamil	const int sigval = SIGSTOP;
58241.1Skamil	const int sigmasked = SIGTRAP;
58251.1Skamil	pid_t child, wpid;
58261.1Skamil#if defined(TWAIT_HAVE_STATUS)
58271.1Skamil	int status;
58281.1Skamil#endif
58291.1Skamil	sigset_t intmask;
58301.1Skamil	ptrace_state_t state;
58311.1Skamil	const int slen = sizeof(state);
58321.1Skamil	ptrace_event_t event;
58331.1Skamil	const int elen = sizeof(event);
58341.1Skamil	ucontext_t uc;
58351.1Skamil	lwpid_t lid;
58361.1Skamil	static const size_t ssize = 16*1024;
58371.1Skamil	void *stack;
58381.1Skamil
58391.14Schristos	atf_tc_expect_fail("PR kern/51918");
58401.14Schristos
58411.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58421.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58431.1Skamil	if (child == 0) {
58441.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58451.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58461.1Skamil
58471.1Skamil		sigemptyset(&intmask);
58481.1Skamil		sigaddset(&intmask, sigmasked);
58491.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
58501.1Skamil
58511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58531.1Skamil
58541.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
58551.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
58561.1Skamil
58571.13Schristos		DPRINTF("Before making context for new lwp in child\n");
58581.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
58591.1Skamil
58601.13Schristos		DPRINTF("Before creating new in child\n");
58611.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
58621.1Skamil
58631.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
58641.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
58651.1Skamil
58661.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
58671.1Skamil		    "are the same\n", lid, the_lwp_id);
58681.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
58691.1Skamil
58701.13Schristos		DPRINTF("Before exiting of the child process\n");
58711.1Skamil		_exit(exitval);
58721.1Skamil	}
58731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58741.1Skamil
58751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58771.1Skamil
58781.1Skamil	validate_status_stopped(status, sigval);
58791.1Skamil
58801.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
58811.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
58821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
58831.1Skamil
58841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58851.1Skamil	    "without signal to be sent\n");
58861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58871.1Skamil
58881.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
58891.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
58901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58911.1Skamil
58921.1Skamil	validate_status_stopped(status, sigmasked);
58931.1Skamil
58941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
58951.1Skamil
58961.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
58971.1Skamil
58981.1Skamil	lid = state.pe_lwp;
58991.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
59001.1Skamil
59011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59021.1Skamil	    "without signal to be sent\n");
59031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59041.1Skamil
59051.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59061.1Skamil	    TWAIT_FNAME);
59071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59081.1Skamil
59091.1Skamil	validate_status_exited(status, exitval);
59101.1Skamil
59111.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59121.1Skamil	    TWAIT_FNAME);
59131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59141.1Skamil}
59151.1Skamil
59161.1SkamilATF_TC(signal10);
59171.1SkamilATF_TC_HEAD(signal10, tc)
59181.1Skamil{
59191.1Skamil	atf_tc_set_md_var(tc, "descr",
59201.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
59211.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
59221.1Skamil}
59231.1Skamil
59241.1SkamilATF_TC_BODY(signal10, tc)
59251.1Skamil{
59261.1Skamil	const int exitval = 5;
59271.1Skamil	const int sigval = SIGSTOP;
59281.1Skamil	const int sigmasked = SIGTRAP;
59291.1Skamil	pid_t child, wpid;
59301.1Skamil#if defined(TWAIT_HAVE_STATUS)
59311.1Skamil	int status;
59321.1Skamil#endif
59331.1Skamil	sigset_t intmask;
59341.1Skamil	ptrace_state_t state;
59351.1Skamil	const int slen = sizeof(state);
59361.1Skamil	ptrace_event_t event;
59371.1Skamil	const int elen = sizeof(event);
59381.1Skamil	ucontext_t uc;
59391.1Skamil	lwpid_t lid;
59401.1Skamil	static const size_t ssize = 16*1024;
59411.1Skamil	void *stack;
59421.1Skamil
59431.14Schristos	atf_tc_expect_fail("PR kern/51918");
59441.14Schristos
59451.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59461.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59471.1Skamil	if (child == 0) {
59481.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59491.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59501.1Skamil
59511.1Skamil		sigemptyset(&intmask);
59521.1Skamil		sigaddset(&intmask, sigmasked);
59531.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
59541.1Skamil
59551.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59561.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59571.1Skamil
59581.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
59591.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
59601.1Skamil
59611.13Schristos		DPRINTF("Before making context for new lwp in child\n");
59621.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
59631.1Skamil
59641.13Schristos		DPRINTF("Before creating new in child\n");
59651.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
59661.1Skamil
59671.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
59681.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
59691.1Skamil
59701.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
59711.1Skamil		    "are the same\n", lid, the_lwp_id);
59721.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
59731.1Skamil
59741.13Schristos		DPRINTF("Before exiting of the child process\n");
59751.1Skamil		_exit(exitval);
59761.1Skamil	}
59771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59781.1Skamil
59791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59811.1Skamil
59821.1Skamil	validate_status_stopped(status, sigval);
59831.1Skamil
59841.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
59851.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
59861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
59871.1Skamil
59881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59891.1Skamil	    "without signal to be sent\n");
59901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59911.1Skamil
59921.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59931.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
59941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59951.1Skamil
59961.1Skamil	validate_status_stopped(status, sigmasked);
59971.1Skamil
59981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
59991.1Skamil
60001.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
60011.1Skamil
60021.1Skamil	lid = state.pe_lwp;
60031.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
60041.1Skamil
60051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60061.1Skamil	    "without signal to be sent\n");
60071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60081.1Skamil
60091.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60101.1Skamil	    TWAIT_FNAME);
60111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60121.1Skamil
60131.1Skamil	validate_status_exited(status, exitval);
60141.1Skamil
60151.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60161.1Skamil	    TWAIT_FNAME);
60171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60181.1Skamil}
60191.1Skamil
60201.1Skamilstatic void
60211.1Skamillwp_main_stop(void *arg)
60221.1Skamil{
60231.1Skamil	the_lwp_id = _lwp_self();
60241.1Skamil
60251.1Skamil	raise(SIGTRAP);
60261.1Skamil
60271.1Skamil	_lwp_exit();
60281.1Skamil}
60291.1Skamil
60301.1SkamilATF_TC(suspend1);
60311.1SkamilATF_TC_HEAD(suspend1, tc)
60321.1Skamil{
60331.1Skamil	atf_tc_set_md_var(tc, "descr",
60341.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
60351.1Skamil	    "resumed by a tracee");
60361.1Skamil}
60371.1Skamil
60381.1SkamilATF_TC_BODY(suspend1, tc)
60391.1Skamil{
60401.1Skamil	const int exitval = 5;
60411.1Skamil	const int sigval = SIGSTOP;
60421.1Skamil	pid_t child, wpid;
60431.1Skamil#if defined(TWAIT_HAVE_STATUS)
60441.1Skamil	int status;
60451.1Skamil#endif
60461.1Skamil	ucontext_t uc;
60471.1Skamil	lwpid_t lid;
60481.1Skamil	static const size_t ssize = 16*1024;
60491.1Skamil	void *stack;
60501.1Skamil	struct ptrace_lwpinfo pl;
60511.1Skamil	struct ptrace_siginfo psi;
60521.1Skamil	volatile int go = 0;
60531.1Skamil
60541.17Skamil	// Feature pending for refactoring
60551.17Skamil	atf_tc_expect_fail("PR kern/51995");
60561.17Skamil
60571.16Skamil	// Hangs with qemu
60581.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
60591.16Skamil
60601.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60611.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60621.1Skamil	if (child == 0) {
60631.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60641.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60651.1Skamil
60661.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60671.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60681.1Skamil
60691.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
60701.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
60711.1Skamil
60721.13Schristos		DPRINTF("Before making context for new lwp in child\n");
60731.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
60741.1Skamil
60751.13Schristos		DPRINTF("Before creating new in child\n");
60761.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
60771.1Skamil
60781.1Skamil		while (go == 0)
60791.1Skamil			continue;
60801.1Skamil
60811.1Skamil		raise(SIGINT);
60821.1Skamil
60831.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
60841.1Skamil
60851.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
60861.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
60871.1Skamil
60881.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
60891.1Skamil		    "are the same\n", lid, the_lwp_id);
60901.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
60911.1Skamil
60921.13Schristos		DPRINTF("Before exiting of the child process\n");
60931.1Skamil		_exit(exitval);
60941.1Skamil	}
60951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60961.1Skamil
60971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60991.1Skamil
61001.1Skamil	validate_status_stopped(status, sigval);
61011.1Skamil
61021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61031.1Skamil	    "without signal to be sent\n");
61041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61051.1Skamil
61061.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61071.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
61081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61091.1Skamil
61101.1Skamil	validate_status_stopped(status, SIGTRAP);
61111.1Skamil
61121.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
61131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
61141.1Skamil
61151.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
61161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
61171.1Skamil
61181.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
61191.1Skamil	    child, getpid());
61201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
61211.1Skamil
61221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61231.1Skamil	    "without signal to be sent\n");
61241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61251.1Skamil
61261.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61271.1Skamil	    "SIGINT\n", TWAIT_FNAME);
61281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61291.1Skamil
61301.1Skamil	validate_status_stopped(status, SIGINT);
61311.1Skamil
61321.1Skamil	pl.pl_lwpid = 0;
61331.1Skamil
61341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
61351.1Skamil	while (pl.pl_lwpid != 0) {
61361.1Skamil
61371.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
61381.1Skamil		switch (pl.pl_lwpid) {
61391.1Skamil		case 1:
61401.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
61411.1Skamil			break;
61421.1Skamil		case 2:
61431.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
61441.1Skamil			break;
61451.1Skamil		}
61461.1Skamil	}
61471.1Skamil
61481.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61491.1Skamil	    "without signal to be sent\n");
61501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61511.1Skamil
61521.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61531.1Skamil	    TWAIT_FNAME);
61541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61551.1Skamil
61561.1Skamil	validate_status_exited(status, exitval);
61571.1Skamil
61581.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61591.1Skamil	    TWAIT_FNAME);
61601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61611.1Skamil}
61621.1Skamil
61631.1SkamilATF_TC(suspend2);
61641.1SkamilATF_TC_HEAD(suspend2, tc)
61651.1Skamil{
61661.1Skamil	atf_tc_set_md_var(tc, "descr",
61671.1Skamil	    "Verify that the while the only thread within a process is "
61681.1Skamil	    "suspended, the whole process cannot be unstopped");
61691.1Skamil}
61701.1Skamil
61711.1SkamilATF_TC_BODY(suspend2, tc)
61721.1Skamil{
61731.1Skamil	const int exitval = 5;
61741.1Skamil	const int sigval = SIGSTOP;
61751.1Skamil	pid_t child, wpid;
61761.1Skamil#if defined(TWAIT_HAVE_STATUS)
61771.1Skamil	int status;
61781.1Skamil#endif
61791.1Skamil	struct ptrace_siginfo psi;
61801.1Skamil
61811.17Skamil	// Feature pending for refactoring
61821.17Skamil	atf_tc_expect_fail("PR kern/51995");
61831.17Skamil
61841.16Skamil	// Hangs with qemu
61851.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
61861.16Skamil
61871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61891.1Skamil	if (child == 0) {
61901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61921.1Skamil
61931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61951.1Skamil
61961.13Schristos		DPRINTF("Before exiting of the child process\n");
61971.1Skamil		_exit(exitval);
61981.1Skamil	}
61991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62001.1Skamil
62011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62031.1Skamil
62041.1Skamil	validate_status_stopped(status, sigval);
62051.1Skamil
62061.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
62071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
62081.1Skamil
62091.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
62101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
62111.1Skamil
62121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62131.1Skamil	    "without signal to be sent\n");
62141.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
62151.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
62161.1Skamil
62171.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
62181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
62191.1Skamil
62201.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62211.1Skamil	    "without signal to be sent\n");
62221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62231.1Skamil
62241.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62251.1Skamil	    TWAIT_FNAME);
62261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62271.1Skamil
62281.1Skamil	validate_status_exited(status, exitval);
62291.1Skamil
62301.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62311.1Skamil	    TWAIT_FNAME);
62321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62331.1Skamil}
62341.1Skamil
62351.1SkamilATF_TC(resume1);
62361.1SkamilATF_TC_HEAD(resume1, tc)
62371.1Skamil{
62381.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
62391.1Skamil	atf_tc_set_md_var(tc, "descr",
62401.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
62411.1Skamil	    "resumed by the debugger");
62421.1Skamil}
62431.1Skamil
62441.1SkamilATF_TC_BODY(resume1, tc)
62451.1Skamil{
62461.1Skamil	struct msg_fds fds;
62471.1Skamil	const int exitval = 5;
62481.1Skamil	const int sigval = SIGSTOP;
62491.1Skamil	pid_t child, wpid;
62501.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
62511.1Skamil#if defined(TWAIT_HAVE_STATUS)
62521.1Skamil	int status;
62531.1Skamil#endif
62541.1Skamil	ucontext_t uc;
62551.1Skamil	lwpid_t lid;
62561.1Skamil	static const size_t ssize = 16*1024;
62571.1Skamil	void *stack;
62581.1Skamil	struct ptrace_lwpinfo pl;
62591.1Skamil	struct ptrace_siginfo psi;
62601.1Skamil
62611.17Skamil	// Feature pending for refactoring
62621.17Skamil	atf_tc_expect_fail("PR kern/51995");
62631.17Skamil
62641.15Schristos	// Hangs with qemu
62651.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
62661.1Skamil
62671.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
62681.1Skamil
62691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62711.1Skamil	if (child == 0) {
62721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62741.1Skamil
62751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62771.1Skamil
62781.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62791.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62801.1Skamil
62811.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62821.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
62831.1Skamil
62841.13Schristos		DPRINTF("Before creating new in child\n");
62851.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62861.1Skamil
62871.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
62881.1Skamil
62891.1Skamil		raise(SIGINT);
62901.1Skamil
62911.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62921.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62931.1Skamil
62941.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62951.1Skamil		    "are the same\n", lid, the_lwp_id);
62961.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
62971.1Skamil
62981.13Schristos		DPRINTF("Before exiting of the child process\n");
62991.1Skamil		_exit(exitval);
63001.1Skamil	}
63011.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63021.1Skamil
63031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63051.1Skamil
63061.1Skamil	validate_status_stopped(status, sigval);
63071.1Skamil
63081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63091.1Skamil	    "without signal to be sent\n");
63101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63111.1Skamil
63121.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63131.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63151.1Skamil
63161.1Skamil	validate_status_stopped(status, SIGTRAP);
63171.1Skamil
63181.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
63191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
63201.1Skamil
63211.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
63221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
63231.1Skamil
63241.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
63251.1Skamil
63261.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63271.1Skamil	    "without signal to be sent\n");
63281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63291.1Skamil
63301.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63311.1Skamil	    "SIGINT\n", TWAIT_FNAME);
63321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63331.1Skamil
63341.1Skamil	validate_status_stopped(status, SIGINT);
63351.1Skamil
63361.1Skamil	pl.pl_lwpid = 0;
63371.1Skamil
63381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
63391.1Skamil	while (pl.pl_lwpid != 0) {
63401.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
63411.1Skamil		switch (pl.pl_lwpid) {
63421.1Skamil		case 1:
63431.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
63441.1Skamil			break;
63451.1Skamil		case 2:
63461.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
63471.1Skamil			break;
63481.1Skamil		}
63491.1Skamil	}
63501.1Skamil
63511.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
63521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
63531.1Skamil
63541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63551.1Skamil	    "without signal to be sent\n");
63561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63571.1Skamil
63581.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63591.1Skamil	    TWAIT_FNAME);
63601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63611.1Skamil
63621.1Skamil	validate_status_exited(status, exitval);
63631.1Skamil
63641.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63651.1Skamil	    TWAIT_FNAME);
63661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63671.1Skamil
63681.1Skamil	msg_close(&fds);
63691.1Skamil
63701.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
63711.1Skamil	sleep(10);
63721.1Skamil}
63731.1Skamil
63741.1SkamilATF_TC(syscall1);
63751.1SkamilATF_TC_HEAD(syscall1, tc)
63761.1Skamil{
63771.1Skamil	atf_tc_set_md_var(tc, "descr",
63781.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
63791.1Skamil}
63801.1Skamil
63811.1SkamilATF_TC_BODY(syscall1, tc)
63821.1Skamil{
63831.1Skamil	const int exitval = 5;
63841.1Skamil	const int sigval = SIGSTOP;
63851.1Skamil	pid_t child, wpid;
63861.1Skamil#if defined(TWAIT_HAVE_STATUS)
63871.1Skamil	int status;
63881.1Skamil#endif
63891.1Skamil	struct ptrace_siginfo info;
63901.1Skamil	memset(&info, 0, sizeof(info));
63911.1Skamil
63921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63941.1Skamil	if (child == 0) {
63951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63971.1Skamil
63981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64001.1Skamil
64011.1Skamil		syscall(SYS_getpid);
64021.1Skamil
64031.13Schristos		DPRINTF("Before exiting of the child process\n");
64041.1Skamil		_exit(exitval);
64051.1Skamil	}
64061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64071.1Skamil
64081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64101.1Skamil
64111.1Skamil	validate_status_stopped(status, sigval);
64121.1Skamil
64131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64141.1Skamil	    "without signal to be sent\n");
64151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
64161.1Skamil
64171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64191.1Skamil
64201.1Skamil	validate_status_stopped(status, SIGTRAP);
64211.1Skamil
64221.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
64231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
64241.1Skamil
64251.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
64261.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
64271.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
64281.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
64291.1Skamil
64301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64311.1Skamil	    "without signal to be sent\n");
64321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
64331.1Skamil
64341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64361.1Skamil
64371.1Skamil	validate_status_stopped(status, SIGTRAP);
64381.1Skamil
64391.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
64401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
64411.1Skamil
64421.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
64431.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
64441.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
64451.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
64461.1Skamil
64471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64481.1Skamil	    "without signal to be sent\n");
64491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64501.1Skamil
64511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64531.1Skamil
64541.1Skamil	validate_status_exited(status, exitval);
64551.1Skamil
64561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64581.1Skamil}
64591.1Skamil
64601.1SkamilATF_TC(syscallemu1);
64611.1SkamilATF_TC_HEAD(syscallemu1, tc)
64621.1Skamil{
64631.1Skamil	atf_tc_set_md_var(tc, "descr",
64641.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
64651.1Skamil}
64661.1Skamil
64671.1SkamilATF_TC_BODY(syscallemu1, tc)
64681.1Skamil{
64691.1Skamil	const int exitval = 5;
64701.1Skamil	const int sigval = SIGSTOP;
64711.1Skamil	pid_t child, wpid;
64721.1Skamil#if defined(TWAIT_HAVE_STATUS)
64731.1Skamil	int status;
64741.1Skamil#endif
64751.1Skamil
64761.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
64771.6Skamil	/* syscallemu does not work on sparc (32-bit) */
64781.6Skamil	atf_tc_expect_fail("PR kern/52166");
64791.6Skamil#endif
64801.6Skamil
64811.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64821.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64831.1Skamil	if (child == 0) {
64841.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64851.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64861.1Skamil
64871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64891.1Skamil
64901.1Skamil		syscall(SYS_exit, 100);
64911.1Skamil
64921.13Schristos		DPRINTF("Before exiting of the child process\n");
64931.1Skamil		_exit(exitval);
64941.1Skamil	}
64951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64961.1Skamil
64971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64991.1Skamil
65001.1Skamil	validate_status_stopped(status, sigval);
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_SYSCALL, child, (void *)1, 0) != -1);
65051.1Skamil
65061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65081.1Skamil
65091.1Skamil	validate_status_stopped(status, SIGTRAP);
65101.1Skamil
65111.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
65121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
65131.1Skamil
65141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65151.1Skamil	    "without signal to be sent\n");
65161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
65171.1Skamil
65181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65201.1Skamil
65211.1Skamil	validate_status_stopped(status, SIGTRAP);
65221.1Skamil
65231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65241.1Skamil	    "without signal to be sent\n");
65251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65261.1Skamil
65271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65291.1Skamil
65301.1Skamil	validate_status_exited(status, exitval);
65311.1Skamil
65321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65341.1Skamil}
65351.1Skamil
65361.103Skamil/// ----------------------------------------------------------------------------
65371.103Skamil
65381.106Skamilstatic void
65391.106Skamilclone_body(int flags, bool trackfork, bool trackvfork,
65401.106Skamil    bool trackvforkdone)
65411.106Skamil{
65421.106Skamil	const int exitval = 5;
65431.106Skamil	const int exitval2 = 15;
65441.106Skamil	const int sigval = SIGSTOP;
65451.106Skamil	pid_t child, child2 = 0, wpid;
65461.106Skamil#if defined(TWAIT_HAVE_STATUS)
65471.106Skamil	int status;
65481.106Skamil#endif
65491.106Skamil	ptrace_state_t state;
65501.106Skamil	const int slen = sizeof(state);
65511.106Skamil	ptrace_event_t event;
65521.106Skamil	const int elen = sizeof(event);
65531.106Skamil
65541.106Skamil	const size_t stack_size = 1024 * 1024;
65551.106Skamil	void *stack, *stack_base;
65561.106Skamil
65571.106Skamil	stack = malloc(stack_size);
65581.106Skamil	ATF_REQUIRE(stack != NULL);
65591.106Skamil
65601.106Skamil#ifdef __MACHINE_STACK_GROWS_UP
65611.106Skamil	stack_base = stack;
65621.106Skamil#else
65631.106Skamil	stack_base = (char *)stack + stack_size;
65641.106Skamil#endif
65651.106Skamil
65661.106Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
65671.106Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
65681.106Skamil	if (child == 0) {
65691.106Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65701.106Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65711.106Skamil
65721.106Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65731.106Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65741.106Skamil
65751.106Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
65761.106Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
65771.106Skamil
65781.106Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
65791.106Skamil		    child2);
65801.106Skamil
65811.106Skamil		// XXX WALLSIG?
65821.106Skamil		FORKEE_REQUIRE_SUCCESS
65831.106Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
65841.106Skamil
65851.106Skamil		forkee_status_exited(status, exitval2);
65861.106Skamil
65871.106Skamil		DPRINTF("Before exiting of the child process\n");
65881.106Skamil		_exit(exitval);
65891.106Skamil	}
65901.106Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65911.106Skamil
65921.106Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65931.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65941.106Skamil
65951.106Skamil	validate_status_stopped(status, sigval);
65961.106Skamil
65971.106Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
65981.106Skamil	    trackfork ? "|PTRACE_FORK" : "",
65991.106Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
66001.106Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
66011.106Skamil	event.pe_set_event = 0;
66021.106Skamil	if (trackfork)
66031.106Skamil		event.pe_set_event |= PTRACE_FORK;
66041.106Skamil	if (trackvfork)
66051.106Skamil		event.pe_set_event |= PTRACE_VFORK;
66061.106Skamil	if (trackvforkdone)
66071.106Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
66081.106Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
66091.106Skamil
66101.106Skamil	DPRINTF("Before resuming the child process where it left off and "
66111.106Skamil	    "without signal to be sent\n");
66121.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66131.106Skamil
66141.106Skamil#if defined(TWAIT_HAVE_PID)
66151.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
66161.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
66171.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
66181.106Skamil		    child);
66191.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
66201.106Skamil		    child);
66211.106Skamil
66221.106Skamil		validate_status_stopped(status, SIGTRAP);
66231.106Skamil
66241.106Skamil		SYSCALL_REQUIRE(
66251.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
66261.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
66271.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
66281.106Skamil			       PTRACE_FORK);
66291.106Skamil		}
66301.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
66311.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
66321.106Skamil			       PTRACE_VFORK);
66331.106Skamil		}
66341.106Skamil
66351.106Skamil		child2 = state.pe_other_pid;
66361.106Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
66371.106Skamil
66381.106Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
66391.106Skamil		    "%d\n", TWAIT_FNAME, child2, child);
66401.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
66411.106Skamil		    child2);
66421.106Skamil
66431.106Skamil		validate_status_stopped(status, SIGTRAP);
66441.106Skamil
66451.106Skamil		SYSCALL_REQUIRE(
66461.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
66471.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
66481.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
66491.106Skamil			       PTRACE_FORK);
66501.106Skamil		}
66511.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
66521.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
66531.106Skamil			       PTRACE_VFORK);
66541.106Skamil		}
66551.106Skamil
66561.106Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
66571.106Skamil
66581.106Skamil		DPRINTF("Before resuming the forkee process where it left off "
66591.106Skamil		    "and without signal to be sent\n");
66601.106Skamil		SYSCALL_REQUIRE(
66611.106Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
66621.106Skamil
66631.106Skamil		DPRINTF("Before resuming the child process where it left off "
66641.106Skamil		    "and without signal to be sent\n");
66651.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66661.106Skamil	}
66671.106Skamil#endif
66681.106Skamil
66691.106Skamil	if (trackvforkdone && (flags & CLONE_VFORK)) {
66701.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
66711.106Skamil		    child);
66721.106Skamil		TWAIT_REQUIRE_SUCCESS(
66731.106Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
66741.106Skamil
66751.106Skamil		validate_status_stopped(status, SIGTRAP);
66761.106Skamil
66771.106Skamil		SYSCALL_REQUIRE(
66781.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
66791.106Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
66801.106Skamil
66811.106Skamil		child2 = state.pe_other_pid;
66821.106Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
66831.106Skamil		    child2);
66841.106Skamil
66851.106Skamil		DPRINTF("Before resuming the child process where it left off "
66861.106Skamil		    "and without signal to be sent\n");
66871.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66881.106Skamil	}
66891.106Skamil
66901.103Skamil#if defined(TWAIT_HAVE_PID)
66911.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
66921.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
66931.106Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
66941.106Skamil		    "\n", TWAIT_FNAME);
66951.106Skamil		TWAIT_REQUIRE_SUCCESS(
66961.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
66971.106Skamil
66981.106Skamil		validate_status_exited(status, exitval2);
66991.106Skamil
67001.106Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
67011.106Skamil		    "process\n", TWAIT_FNAME);
67021.106Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
67031.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
67041.106Skamil	}
67051.106Skamil#endif
67061.106Skamil
67071.106Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
67081.106Skamil	    "SIGCHLD\n", TWAIT_FNAME);
67091.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67101.106Skamil
67111.106Skamil	validate_status_stopped(status, SIGCHLD);
67121.106Skamil
67131.106Skamil	DPRINTF("Before resuming the child process where it left off and "
67141.106Skamil	    "without signal to be sent\n");
67151.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67161.106Skamil
67171.106Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
67181.106Skamil	    TWAIT_FNAME);
67191.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67201.106Skamil
67211.106Skamil	validate_status_exited(status, exitval);
67221.103Skamil
67231.106Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
67241.106Skamil	    TWAIT_FNAME);
67251.106Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67261.106Skamil}
67271.103Skamil
67281.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone)			\
67291.106SkamilATF_TC(name);								\
67301.106SkamilATF_TC_HEAD(name, tc)							\
67311.106Skamil{									\
67321.106Skamil	atf_tc_set_md_var(tc, "descr", "Verify clone(%s) "		\
67331.106Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
67341.106Skamil	    #flags,							\
67351.106Skamil	    tfork ? "|PTRACE_FORK" : "",				\
67361.106Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
67371.106Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
67381.106Skamil}									\
67391.106Skamil									\
67401.106SkamilATF_TC_BODY(name, tc)							\
67411.106Skamil{									\
67421.106Skamil									\
67431.106Skamil	clone_body(flags, tfork, tvfork, tvforkdone);			\
67441.103Skamil}
67451.103Skamil
67461.106SkamilCLONE_TEST(clone1, 0, false, false, false)
67471.106Skamil#if defined(TWAIT_HAVE_PID)
67481.106SkamilCLONE_TEST(clone2, 0, true, false, false)
67491.106SkamilCLONE_TEST(clone3, 0, false, true, false)
67501.106SkamilCLONE_TEST(clone4, 0, true, true, false)
67511.106Skamil#endif
67521.106SkamilCLONE_TEST(clone5, 0, false, false, true)
67531.106Skamil#if defined(TWAIT_HAVE_PID)
67541.106SkamilCLONE_TEST(clone6, 0, true, false, true)
67551.106SkamilCLONE_TEST(clone7, 0, false, true, true)
67561.106SkamilCLONE_TEST(clone8, 0, true, true, true)
67571.106Skamil#endif
67581.106Skamil
67591.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false)
67601.106Skamil#if defined(TWAIT_HAVE_PID)
67611.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false)
67621.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false)
67631.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false)
67641.106Skamil#endif
67651.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true)
67661.106Skamil#if defined(TWAIT_HAVE_PID)
67671.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true)
67681.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true)
67691.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true)
67701.106Skamil#endif
67711.106Skamil
67721.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false)
67731.106Skamil#if defined(TWAIT_HAVE_PID)
67741.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false)
67751.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false)
67761.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false)
67771.106Skamil#endif
67781.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true)
67791.106Skamil#if defined(TWAIT_HAVE_PID)
67801.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true)
67811.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true)
67821.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true)
67831.106Skamil#endif
67841.106Skamil
67851.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false)
67861.106Skamil#if defined(TWAIT_HAVE_PID)
67871.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false)
67881.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false)
67891.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false)
67901.106Skamil#endif
67911.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true)
67921.106Skamil#if defined(TWAIT_HAVE_PID)
67931.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true)
67941.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true)
67951.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true)
67961.106Skamil#endif
67971.106Skamil
67981.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false)
67991.106Skamil#if defined(TWAIT_HAVE_PID)
68001.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false)
68011.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false)
68021.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false)
68031.106Skamil#endif
68041.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true)
68051.106Skamil#if defined(TWAIT_HAVE_PID)
68061.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true)
68071.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true)
68081.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true)
68091.106Skamil#endif
68101.106Skamil
68111.110Skamil#if TEST_VFORK_ENABLED
68121.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false)
68131.106Skamil#if defined(TWAIT_HAVE_PID)
68141.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false)
68151.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false)
68161.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false)
68171.106Skamil#endif
68181.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true)
68191.106Skamil#if defined(TWAIT_HAVE_PID)
68201.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true)
68211.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true)
68221.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true)
68231.106Skamil#endif
68241.110Skamil#endif
68251.106Skamil
68261.106Skamil/// ----------------------------------------------------------------------------
68271.106Skamil
68281.106Skamil#if defined(TWAIT_HAVE_PID)
68291.103Skamilstatic void
68301.106Skamilclone_body2(int flags, bool masked, bool ignored)
68311.103Skamil{
68321.103Skamil	const int exitval = 5;
68331.103Skamil	const int exitval2 = 15;
68341.103Skamil	const int sigval = SIGSTOP;
68351.103Skamil	pid_t child, child2 = 0, wpid;
68361.103Skamil#if defined(TWAIT_HAVE_STATUS)
68371.103Skamil	int status;
68381.103Skamil#endif
68391.103Skamil	ptrace_state_t state;
68401.103Skamil	const int slen = sizeof(state);
68411.103Skamil	ptrace_event_t event;
68421.103Skamil	const int elen = sizeof(event);
68431.103Skamil	struct sigaction sa;
68441.103Skamil	struct ptrace_siginfo info;
68451.103Skamil	sigset_t intmask;
68461.103Skamil	struct kinfo_proc2 kp;
68471.103Skamil	size_t len = sizeof(kp);
68481.103Skamil
68491.103Skamil	int name[6];
68501.103Skamil	const size_t namelen = __arraycount(name);
68511.103Skamil	ki_sigset_t kp_sigmask;
68521.103Skamil	ki_sigset_t kp_sigignore;
68531.103Skamil
68541.103Skamil	const size_t stack_size = 1024 * 1024;
68551.103Skamil	void *stack, *stack_base;
68561.103Skamil
68571.103Skamil	stack = malloc(stack_size);
68581.103Skamil	ATF_REQUIRE(stack != NULL);
68591.103Skamil
68601.103Skamil#ifdef __MACHINE_STACK_GROWS_UP
68611.103Skamil	stack_base = stack;
68621.103Skamil#else
68631.103Skamil	stack_base = (char *)stack + stack_size;
68641.103Skamil#endif
68651.103Skamil
68661.103Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
68671.103Skamil	if (child == 0) {
68681.103Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68691.103Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68701.103Skamil
68711.103Skamil		if (masked) {
68721.103Skamil			sigemptyset(&intmask);
68731.103Skamil			sigaddset(&intmask, SIGTRAP);
68741.103Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
68751.103Skamil		}
68761.103Skamil
68771.103Skamil		if (ignored) {
68781.103Skamil			memset(&sa, 0, sizeof(sa));
68791.103Skamil			sa.sa_handler = SIG_IGN;
68801.103Skamil			sigemptyset(&sa.sa_mask);
68811.103Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
68821.103Skamil		}
68831.103Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68841.103Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68851.103Skamil
68861.103Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
68871.103Skamil		    flags);
68881.103Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
68891.103Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
68901.103Skamil
68911.103Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
68921.103Skamil		    child2);
68931.103Skamil
68941.103Skamil		// XXX WALLSIG?
68951.103Skamil		FORKEE_REQUIRE_SUCCESS
68961.103Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
68971.103Skamil
68981.103Skamil		forkee_status_exited(status, exitval2);
68991.103Skamil
69001.103Skamil		DPRINTF("Before exiting of the child process\n");
69011.103Skamil		_exit(exitval);
69021.103Skamil	}
69031.103Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
69041.103Skamil
69051.103Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69061.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69071.103Skamil
69081.103Skamil	validate_status_stopped(status, sigval);
69091.103Skamil
69101.103Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
69111.103Skamil	SYSCALL_REQUIRE(
69121.103Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
69131.103Skamil
69141.103Skamil	DPRINTF("Before checking siginfo_t\n");
69151.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
69161.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
69171.103Skamil
69181.103Skamil	name[0] = CTL_KERN,
69191.103Skamil	name[1] = KERN_PROC2,
69201.103Skamil	name[2] = KERN_PROC_PID;
69211.103Skamil	name[3] = child;
69221.103Skamil	name[4] = sizeof(kp);
69231.103Skamil	name[5] = 1;
69241.103Skamil
69251.103Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
69261.103Skamil
69271.103Skamil	if (masked)
69281.103Skamil		kp_sigmask = kp.p_sigmask;
69291.103Skamil
69301.103Skamil	if (ignored)
69311.103Skamil		kp_sigignore = kp.p_sigignore;
69321.103Skamil
69331.103Skamil	DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in "
69341.103Skamil	    "EVENT_MASK for the child %d\n", child);
69351.103Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
69361.103Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
69371.103Skamil
69381.103Skamil	DPRINTF("Before resuming the child process where it left off and "
69391.103Skamil	    "without signal to be sent\n");
69401.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69411.103Skamil
69421.103Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
69431.103Skamil	    child);
69441.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
69451.103Skamil	    child);
69461.103Skamil
69471.103Skamil	validate_status_stopped(status, SIGTRAP);
69481.103Skamil
69491.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
69501.103Skamil
69511.103Skamil	if (masked) {
69521.103Skamil		DPRINTF("kp_sigmask="
69531.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69541.103Skamil		    PRIx32 "\n",
69551.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
69561.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
69571.103Skamil
69581.103Skamil		DPRINTF("kp.p_sigmask="
69591.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69601.103Skamil		    PRIx32 "\n",
69611.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
69621.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
69631.103Skamil
69641.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
69651.103Skamil		    sizeof(kp_sigmask)));
69661.103Skamil	}
69671.103Skamil
69681.103Skamil	if (ignored) {
69691.103Skamil		DPRINTF("kp_sigignore="
69701.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69711.103Skamil		    PRIx32 "\n",
69721.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
69731.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
69741.103Skamil
69751.103Skamil		DPRINTF("kp.p_sigignore="
69761.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69771.103Skamil		    PRIx32 "\n",
69781.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
69791.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
69801.103Skamil
69811.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
69821.103Skamil		    sizeof(kp_sigignore)));
69831.103Skamil	}
69841.103Skamil
69851.103Skamil	SYSCALL_REQUIRE(
69861.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
69871.103Skamil	DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event,
69881.103Skamil	    child2);
69891.103Skamil	if (!(flags & CLONE_VFORK)) {
69901.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
69911.103Skamil		       PTRACE_FORK);
69921.103Skamil	} else {
69931.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
69941.103Skamil		       PTRACE_VFORK);
69951.103Skamil	}
69961.103Skamil
69971.103Skamil	child2 = state.pe_other_pid;
69981.103Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
69991.103Skamil
70001.103Skamil	DPRINTF("Before calling %s() for the forkee %d of the child "
70011.103Skamil	    "%d\n", TWAIT_FNAME, child2, child);
70021.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
70031.103Skamil	    child2);
70041.103Skamil
70051.103Skamil	validate_status_stopped(status, SIGTRAP);
70061.103Skamil
70071.103Skamil	name[3] = child2;
70081.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
70091.103Skamil
70101.103Skamil	if (masked) {
70111.103Skamil		DPRINTF("kp_sigmask="
70121.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
70131.103Skamil		    PRIx32 "\n",
70141.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
70151.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
70161.103Skamil
70171.103Skamil		DPRINTF("kp.p_sigmask="
70181.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
70191.103Skamil		    PRIx32 "\n",
70201.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
70211.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
70221.103Skamil
70231.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
70241.103Skamil		    sizeof(kp_sigmask)));
70251.103Skamil	}
70261.103Skamil
70271.103Skamil	if (ignored) {
70281.103Skamil		DPRINTF("kp_sigignore="
70291.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
70301.103Skamil		    PRIx32 "\n",
70311.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
70321.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
70331.103Skamil
70341.103Skamil		DPRINTF("kp.p_sigignore="
70351.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
70361.103Skamil		    PRIx32 "\n",
70371.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
70381.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
70391.103Skamil
70401.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
70411.103Skamil		    sizeof(kp_sigignore)));
70421.103Skamil	}
70431.103Skamil
70441.103Skamil	SYSCALL_REQUIRE(
70451.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
70461.103Skamil	if (!(flags & CLONE_VFORK)) {
70471.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
70481.103Skamil		       PTRACE_FORK);
70491.103Skamil	} else {
70501.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
70511.103Skamil		       PTRACE_VFORK);
70521.103Skamil	}
70531.103Skamil
70541.103Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
70551.103Skamil
70561.103Skamil	DPRINTF("Before resuming the forkee process where it left off "
70571.103Skamil	    "and without signal to be sent\n");
70581.103Skamil	SYSCALL_REQUIRE(
70591.103Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
70601.103Skamil
70611.103Skamil	DPRINTF("Before resuming the child process where it left off "
70621.103Skamil	    "and without signal to be sent\n");
70631.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
70641.103Skamil
70651.103Skamil	if (flags & CLONE_VFORK) {
70661.103Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
70671.103Skamil		    child);
70681.103Skamil		TWAIT_REQUIRE_SUCCESS(
70691.103Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
70701.103Skamil
70711.103Skamil		validate_status_stopped(status, SIGTRAP);
70721.103Skamil
70731.103Skamil		name[3] = child;
70741.103Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
70751.103Skamil
70761.103Skamil		/*
70771.103Skamil		 * SIGCHLD is now pending in the signal queue and
70781.103Skamil		 * the kernel presents it to userland as a masked signal.
70791.103Skamil		 */
70801.103Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
70811.103Skamil
70821.103Skamil		if (masked) {
70831.103Skamil			DPRINTF("kp_sigmask="
70841.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
70851.103Skamil			    PRIx32 "\n",
70861.103Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
70871.103Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
70881.103Skamil
70891.103Skamil			DPRINTF("kp.p_sigmask="
70901.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
70911.103Skamil			    PRIx32 "\n",
70921.103Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
70931.103Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
70941.103Skamil
70951.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
70961.103Skamil			    sizeof(kp_sigmask)));
70971.103Skamil		}
70981.103Skamil
70991.103Skamil		if (ignored) {
71001.103Skamil			DPRINTF("kp_sigignore="
71011.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71021.103Skamil			    PRIx32 "\n",
71031.103Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
71041.103Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
71051.103Skamil
71061.103Skamil			DPRINTF("kp.p_sigignore="
71071.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71081.103Skamil			    PRIx32 "\n",
71091.103Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
71101.103Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
71111.103Skamil
71121.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
71131.103Skamil			    sizeof(kp_sigignore)));
71141.103Skamil		}
71151.103Skamil
71161.103Skamil		SYSCALL_REQUIRE(
71171.103Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
71181.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
71191.103Skamil
71201.103Skamil		child2 = state.pe_other_pid;
71211.103Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
71221.103Skamil		    child2);
71231.103Skamil
71241.103Skamil		DPRINTF("Before resuming the child process where it left off "
71251.103Skamil		    "and without signal to be sent\n");
71261.103Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
71271.103Skamil	}
71281.103Skamil
71291.103Skamil	DPRINTF("Before calling %s() for the forkee - expected exited"
71301.103Skamil	    "\n", TWAIT_FNAME);
71311.103Skamil	TWAIT_REQUIRE_SUCCESS(
71321.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
71331.103Skamil
71341.103Skamil	validate_status_exited(status, exitval2);
71351.103Skamil
71361.103Skamil	DPRINTF("Before calling %s() for the forkee - expected no "
71371.103Skamil	    "process\n", TWAIT_FNAME);
71381.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
71391.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
71401.103Skamil
71411.103Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
71421.103Skamil	    "SIGCHLD\n", TWAIT_FNAME);
71431.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
71441.103Skamil
71451.103Skamil	validate_status_stopped(status, SIGCHLD);
71461.103Skamil
71471.103Skamil	DPRINTF("Before resuming the child process where it left off and "
71481.103Skamil	    "without signal to be sent\n");
71491.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
71501.103Skamil
71511.103Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
71521.103Skamil	    TWAIT_FNAME);
71531.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
71541.103Skamil
71551.103Skamil	validate_status_exited(status, exitval);
71561.103Skamil
71571.103Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
71581.103Skamil	    TWAIT_FNAME);
71591.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
71601.103Skamil}
71611.103Skamil
71621.106Skamil#define CLONE_TEST2(name,flags,masked,ignored)				\
71631.103SkamilATF_TC(name);								\
71641.103SkamilATF_TC_HEAD(name, tc)							\
71651.103Skamil{									\
71661.103Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\
71671.103Skamil	    " regardless of signal %s%s", 				\
71681.103Skamil	    #flags, masked ? "masked" : "", ignored ? "ignored" : "");	\
71691.103Skamil}									\
71701.103Skamil									\
71711.103SkamilATF_TC_BODY(name, tc)							\
71721.103Skamil{									\
71731.103Skamil									\
71741.106Skamil	clone_body2(flags, masked, ignored);				\
71751.103Skamil}
71761.103Skamil
71771.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false)
71781.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true)
71791.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false)
71801.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true)
71811.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false)
71821.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true)
71831.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false)
71841.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true)
71851.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX
71861.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true)  // XXX
71871.110Skamil#if TEST_VFORK_ENABLED
71881.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false)
71891.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true)
71901.103Skamil#endif
71911.110Skamil#endif
71921.103Skamil
71931.103Skamil/// ----------------------------------------------------------------------------
71941.103Skamil
71951.111Skamil#if TEST_VFORK_ENABLED
71961.107Skamil#if defined(TWAIT_HAVE_PID)
71971.107Skamilstatic void
71981.107Skamiltraceme_vfork_clone_body(int flags)
71991.107Skamil{
72001.107Skamil	const int exitval = 5;
72011.107Skamil	const int exitval2 = 15;
72021.107Skamil	pid_t child, child2 = 0, wpid;
72031.107Skamil#if defined(TWAIT_HAVE_STATUS)
72041.107Skamil	int status;
72051.107Skamil#endif
72061.107Skamil
72071.107Skamil	const size_t stack_size = 1024 * 1024;
72081.107Skamil	void *stack, *stack_base;
72091.107Skamil
72101.107Skamil	stack = malloc(stack_size);
72111.107Skamil	ATF_REQUIRE(stack != NULL);
72121.107Skamil
72131.107Skamil#ifdef __MACHINE_STACK_GROWS_UP
72141.107Skamil	stack_base = stack;
72151.107Skamil#else
72161.107Skamil	stack_base = (char *)stack + stack_size;
72171.107Skamil#endif
72181.107Skamil
72191.107Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
72201.107Skamil	if (child == 0) {
72211.107Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
72221.107Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
72231.107Skamil
72241.107Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
72251.107Skamil		    flags);
72261.107Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
72271.107Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
72281.107Skamil
72291.107Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
72301.107Skamil		    child2);
72311.107Skamil
72321.107Skamil		// XXX WALLSIG?
72331.107Skamil		FORKEE_REQUIRE_SUCCESS
72341.107Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
72351.107Skamil
72361.107Skamil		forkee_status_exited(status, exitval2);
72371.107Skamil
72381.107Skamil		DPRINTF("Before exiting of the child process\n");
72391.107Skamil		_exit(exitval);
72401.107Skamil	}
72411.107Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
72421.107Skamil
72431.107Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
72441.107Skamil	    TWAIT_FNAME);
72451.107Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
72461.107Skamil
72471.107Skamil	validate_status_exited(status, exitval);
72481.107Skamil
72491.107Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
72501.107Skamil	    TWAIT_FNAME);
72511.107Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
72521.107Skamil}
72531.107Skamil
72541.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags)				\
72551.107SkamilATF_TC(name);								\
72561.107SkamilATF_TC_HEAD(name, tc)							\
72571.107Skamil{									\
72581.107Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is "	\
72591.107Skamil	    "handled correctly with vfork(2)ed tracer", 		\
72601.107Skamil	    #flags);							\
72611.107Skamil}									\
72621.107Skamil									\
72631.107SkamilATF_TC_BODY(name, tc)							\
72641.107Skamil{									\
72651.107Skamil									\
72661.107Skamil	traceme_vfork_clone_body(flags);				\
72671.107Skamil}
72681.107Skamil
72691.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0)
72701.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM)
72711.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS)
72721.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES)
72731.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND)  // XXX
72741.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK)
72751.107Skamil#endif
72761.110Skamil#endif
72771.107Skamil
72781.107Skamil/// ----------------------------------------------------------------------------
72791.107Skamil
72801.1Skamil#include "t_ptrace_amd64_wait.h"
72811.1Skamil#include "t_ptrace_i386_wait.h"
72821.1Skamil#include "t_ptrace_x86_wait.h"
72831.1Skamil
72841.1SkamilATF_TP_ADD_TCS(tp)
72851.1Skamil{
72861.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
72871.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
72881.33Skamil
72891.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
72901.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
72911.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
72921.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
72931.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
72941.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
72951.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
72961.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
72971.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
72981.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
72991.33Skamil
73001.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
73011.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
73021.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
73031.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
73041.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
73051.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
73061.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
73071.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
73081.87Skamil
73091.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
73101.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
73111.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
73121.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
73131.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
73141.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
73151.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
73161.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
73171.86Skamil
73181.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
73191.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
73201.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
73211.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
73221.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
73231.59Skamil
73241.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
73251.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
73261.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
73271.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
73281.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
73291.88Skamil
73301.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
73311.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
73321.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
73331.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
73341.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
73351.88Skamil
73361.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
73371.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
73381.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
73391.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
73401.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
73411.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
73421.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
73431.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
73441.50Skamil
73451.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
73461.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
73471.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
73481.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
73491.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
73501.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
73511.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
73521.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
73531.50Skamil
73541.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
73551.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
73561.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
73571.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
73581.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
73591.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
73601.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
73611.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
73621.50Skamil
73631.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
73641.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
73651.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
73661.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
73671.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
73681.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
73691.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
73701.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
73711.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
73721.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
73731.1Skamil
73741.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
73751.37Skamil
73761.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
73771.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
73781.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
73791.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
73801.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
73811.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
73821.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
73831.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
73841.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
73851.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
73861.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
73871.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
73881.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
73891.40Skamil
73901.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
73911.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
73921.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
73931.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
73941.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
73951.41Skamil
73961.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
73971.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
73981.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
73991.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
74001.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
74011.92Skamil
74021.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
74031.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
74041.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
74051.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
74061.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
74071.92Skamil
74081.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
74091.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
74101.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
74111.43Skamil
74121.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
74131.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
74141.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
74151.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
74161.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
74171.59Skamil
74181.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74191.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
74201.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74211.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
74221.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74231.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
74241.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74251.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
74261.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74271.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
74281.94Skamil
74291.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74301.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
74311.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74321.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
74331.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74341.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
74351.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74361.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
74371.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74381.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
74391.94Skamil
74401.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
74411.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
74421.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
74431.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
74441.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
74451.51Skamil
74461.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
74471.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
74481.51Skamil
74491.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
74501.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
74511.51Skamil
74521.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74531.51Skamil		tracee_sees_its_original_parent_getppid);
74541.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74551.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
74561.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
74571.51Skamil		tracee_sees_its_original_parent_procfs_status);
74581.1Skamil
74591.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
74601.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
74611.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
74621.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
74631.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
74641.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
74651.1Skamil
74661.31Skamil	ATF_TP_ADD_TC(tp, fork1);
74671.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
74681.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
74691.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
74701.31Skamil	ATF_TP_ADD_TC(tp, fork5);
74711.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
74721.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
74731.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
74741.31Skamil
74751.109Skamil#if TEST_VFORK_ENABLED
74761.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
74771.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
74781.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
74791.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
74801.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
74811.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
74821.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
74831.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
74841.1Skamil
74851.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_fork);
74861.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_vfork);
74871.109Skamil#endif
74881.108Skamil
74891.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
74901.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
74911.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
74921.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
74931.54Skamil
74941.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
74951.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
74961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
74971.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
74981.54Skamil
74991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
75001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
75011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
75021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
75031.54Skamil
75041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
75051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
75061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
75071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
75081.54Skamil
75091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
75101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
75111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
75121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
75131.54Skamil
75141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
75151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
75161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
75171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
75181.54Skamil
75191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
75201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
75211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
75221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
75231.54Skamil
75241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
75251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
75261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
75271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
75281.54Skamil
75291.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
75301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
75311.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
75321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
75331.54Skamil
75341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
75351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
75361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
75371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
75381.1Skamil
75391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
75401.1Skamil
75411.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i);
75421.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d);
75431.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i);
75441.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d);
75451.101Skamil
75461.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i);
75471.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d);
75481.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i);
75491.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d);
75501.101Skamil
75511.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv);
75521.101Skamil
75531.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i);
75541.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d);
75551.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i);
75561.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d);
75571.115Skamil
75581.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i);
75591.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d);
75601.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i);
75611.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d);
75621.115Skamil
75631.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
75641.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
75651.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
75661.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
75671.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
75681.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
75691.1Skamil
75701.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
75711.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
75721.1Skamil
75731.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
75741.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
75751.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
75761.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
75771.1Skamil
75781.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
75791.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
75801.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
75811.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
75821.2Skamil
75831.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
75841.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
75851.95Skamil
75861.1Skamil	ATF_TP_ADD_TC(tp, kill1);
75871.1Skamil	ATF_TP_ADD_TC(tp, kill2);
75881.75Skamil	ATF_TP_ADD_TC(tp, kill3);
75891.1Skamil
75901.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
75911.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
75921.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
75931.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
75941.77Skamil
75951.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
75961.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
75971.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
75981.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
75991.1Skamil
76001.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
76011.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
76021.79Skamil
76031.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
76041.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
76051.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
76061.1Skamil
76071.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
76081.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
76091.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
76101.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
76111.1Skamil
76121.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
76131.84Skamil
76141.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
76151.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
76161.109Skamil#if TEST_VFORK_ENABLED
76171.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
76181.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
76191.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
76201.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
76211.109Skamil#endif
76221.99Skamil
76231.1Skamil	ATF_TP_ADD_TC(tp, signal9);
76241.1Skamil	ATF_TP_ADD_TC(tp, signal10);
76251.1Skamil
76261.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
76271.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
76281.1Skamil
76291.1Skamil	ATF_TP_ADD_TC(tp, resume1);
76301.1Skamil
76311.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
76321.1Skamil
76331.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
76341.1Skamil
76351.106Skamil	ATF_TP_ADD_TC(tp, clone1);
76361.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone2);
76371.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone3);
76381.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone4);
76391.106Skamil	ATF_TP_ADD_TC(tp, clone5);
76401.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone6);
76411.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone7);
76421.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone8);
76431.106Skamil
76441.106Skamil	ATF_TP_ADD_TC(tp, clone_vm1);
76451.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2);
76461.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3);
76471.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4);
76481.106Skamil	ATF_TP_ADD_TC(tp, clone_vm5);
76491.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6);
76501.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7);
76511.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8);
76521.106Skamil
76531.106Skamil	ATF_TP_ADD_TC(tp, clone_fs1);
76541.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2);
76551.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3);
76561.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4);
76571.106Skamil	ATF_TP_ADD_TC(tp, clone_fs5);
76581.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6);
76591.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7);
76601.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8);
76611.106Skamil
76621.106Skamil	ATF_TP_ADD_TC(tp, clone_files1);
76631.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2);
76641.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3);
76651.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4);
76661.106Skamil	ATF_TP_ADD_TC(tp, clone_files5);
76671.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6);
76681.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7);
76691.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8);
76701.106Skamil
76711.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand1); // XXX
76721.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX
76731.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX
76741.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX
76751.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand5); // XXX
76761.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX
76771.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX
76781.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX
76791.106Skamil
76801.109Skamil#if TEST_VFORK_ENABLED
76811.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork1);
76821.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2);
76831.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3);
76841.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4);
76851.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork5);
76861.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6);
76871.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7);
76881.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8);
76891.109Skamil#endif
76901.106Skamil
76911.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored);
76921.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked);
76931.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored);
76941.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked);
76951.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored);
76961.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked);
76971.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored);
76981.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked);
76991.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX
77001.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX
77011.109Skamil#if TEST_VFORK_ENABLED
77021.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored);
77031.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked);
77041.109Skamil#endif
77051.103Skamil
77061.109Skamil#if TEST_VFORK_ENABLED
77071.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone);
77081.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm);
77091.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs);
77101.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files);
77111.107Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX
77121.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork);
77131.109Skamil#endif
77141.107Skamil
77151.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
77161.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
77171.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
77181.1Skamil
77191.1Skamil	return atf_no_error();
77201.1Skamil}
7721