t_ptrace_wait.c revision 1.130
11.130Smgorny/*	$NetBSD: t_ptrace_wait.c,v 1.130 2019/06/30 21:20:04 mgorny 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.130Smgorny__RCSID("$NetBSD: t_ptrace_wait.c,v 1.130 2019/06/30 21:20:04 mgorny Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.130Smgorny#include <sys/exec_elf.h>
351.39Skamil#include <sys/mman.h>
361.1Skamil#include <sys/ptrace.h>
371.1Skamil#include <sys/resource.h>
381.1Skamil#include <sys/stat.h>
391.1Skamil#include <sys/syscall.h>
401.1Skamil#include <sys/sysctl.h>
411.129Smgorny#include <sys/uio.h>
421.1Skamil#include <sys/wait.h>
431.1Skamil#include <machine/reg.h>
441.1Skamil#include <elf.h>
451.1Skamil#include <err.h>
461.1Skamil#include <errno.h>
471.130Smgorny#include <fcntl.h>
481.1Skamil#include <lwp.h>
491.77Skamil#include <pthread.h>
501.1Skamil#include <sched.h>
511.1Skamil#include <signal.h>
521.124Skamil#include <spawn.h>
531.1Skamil#include <stdint.h>
541.1Skamil#include <stdio.h>
551.1Skamil#include <stdlib.h>
561.1Skamil#include <strings.h>
571.26Skamil#include <time.h>
581.1Skamil#include <unistd.h>
591.1Skamil
601.114Skamil#include <fenv.h>
611.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__
621.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
631.114Skamil#endif
641.114Skamil
651.121Smgorny#if defined(__i386__) || defined(__x86_64__)
661.121Smgorny#include <cpuid.h>
671.121Smgorny#include <x86/cpu_extended_state.h>
681.129Smgorny#include <x86/specialreg.h>
691.121Smgorny#endif
701.121Smgorny
711.130Smgorny#include <libelf.h>
721.130Smgorny#include <gelf.h>
731.130Smgorny
741.1Skamil#include <atf-c.h>
751.1Skamil
761.1Skamil#include "h_macros.h"
771.1Skamil
781.1Skamil#include "t_ptrace_wait.h"
791.1Skamil#include "msg.h"
801.1Skamil
811.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
821.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
831.61Skre	sizeof(msg)) == 0)
841.1Skamil
851.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
861.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
871.61Skre	sizeof(msg)) == 0)
881.1Skamil
891.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
901.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
911.61Skre	sizeof(msg)) == 0)
921.1Skamil
931.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
941.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
951.61Skre	sizeof(msg)) == 0)
961.13Schristos
971.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
981.13Schristos    strerror(errno))
991.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
1001.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
1011.13Schristos
1021.13Schristosstatic int debug = 0;
1031.13Schristos
1041.13Schristos#define DPRINTF(a, ...)	do  \
1051.123Skamil	if (debug) \
1061.123Skamil	printf("%s() %s:%d " a, __func__, __FILE__, __LINE__,  ##__VA_ARGS__); \
1071.13Schristos    while (/*CONSTCOND*/0)
1081.1Skamil
1091.110Skamil#ifndef TEST_VFORK_ENABLED
1101.127Skamil#define TEST_VFORK_ENABLED 1
1111.110Skamil#endif
1121.109Skamil
1131.128Skamil#ifndef TEST_LWP_ENABLED
1141.128Skamil#define TEST_LWP_ENABLED 0
1151.128Skamil#endif
1161.128Skamil
1171.34Skamil/// ----------------------------------------------------------------------------
1181.34Skamil
1191.33Skamilstatic void
1201.33Skamiltraceme_raise(int sigval)
1211.1Skamil{
1221.1Skamil	const int exitval = 5;
1231.1Skamil	pid_t child, wpid;
1241.1Skamil#if defined(TWAIT_HAVE_STATUS)
1251.1Skamil	int status;
1261.1Skamil#endif
1271.1Skamil
1281.45Skamil	struct ptrace_siginfo info;
1291.45Skamil	memset(&info, 0, sizeof(info));
1301.45Skamil
1311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1331.1Skamil	if (child == 0) {
1341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1361.1Skamil
1371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1391.1Skamil
1401.36Skamil		switch (sigval) {
1411.36Skamil		case SIGKILL:
1421.36Skamil			/* NOTREACHED */
1431.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1441.70Smrg			__unreachable();
1451.36Skamil		default:
1461.36Skamil			DPRINTF("Before exiting of the child process\n");
1471.36Skamil			_exit(exitval);
1481.36Skamil		}
1491.1Skamil	}
1501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1511.1Skamil
1521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1541.1Skamil
1551.36Skamil	switch (sigval) {
1561.36Skamil	case SIGKILL:
1571.36Skamil		validate_status_signaled(status, sigval, 0);
1581.36Skamil		break;
1591.36Skamil	default:
1601.36Skamil		validate_status_stopped(status, sigval);
1611.1Skamil
1621.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1631.61Skre			"child\n");
1641.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1651.61Skre			sizeof(info)) != -1);
1661.45Skamil
1671.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1681.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1691.61Skre			"si_errno=%#x\n",
1701.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1711.61Skre			info.psi_siginfo.si_errno);
1721.45Skamil
1731.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1741.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1751.45Skamil
1761.36Skamil		DPRINTF("Before resuming the child process where it left off "
1771.36Skamil		    "and without signal to be sent\n");
1781.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1791.1Skamil
1801.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1811.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1821.61Skre		    child);
1831.36Skamil		break;
1841.36Skamil	}
1851.1Skamil
1861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1881.1Skamil}
1891.1Skamil
1901.61Skre#define TRACEME_RAISE(test, sig)					\
1911.61SkreATF_TC(test);								\
1921.61SkreATF_TC_HEAD(test, tc)							\
1931.61Skre{									\
1941.61Skre	atf_tc_set_md_var(tc, "descr",					\
1951.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1961.61Skre}									\
1971.61Skre									\
1981.61SkreATF_TC_BODY(test, tc)							\
1991.61Skre{									\
2001.61Skre									\
2011.61Skre	traceme_raise(sig);						\
2021.33Skamil}
2031.33Skamil
2041.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
2051.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
2061.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
2071.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
2081.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
2091.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
2101.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
2111.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
2121.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
2131.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
2141.33Skamil
2151.34Skamil/// ----------------------------------------------------------------------------
2161.1Skamil
2171.1Skamilstatic void
2181.87Skamiltraceme_raisesignal_ignored(int sigignored)
2191.87Skamil{
2201.87Skamil	const int exitval = 5;
2211.87Skamil	const int sigval = SIGSTOP;
2221.87Skamil	pid_t child, wpid;
2231.87Skamil	struct sigaction sa;
2241.87Skamil#if defined(TWAIT_HAVE_STATUS)
2251.87Skamil	int status;
2261.87Skamil#endif
2271.87Skamil	struct ptrace_siginfo info;
2281.87Skamil
2291.87Skamil	memset(&info, 0, sizeof(info));
2301.87Skamil
2311.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2321.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2331.87Skamil	if (child == 0) {
2341.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2351.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2361.87Skamil
2371.87Skamil		memset(&sa, 0, sizeof(sa));
2381.87Skamil		sa.sa_handler = SIG_IGN;
2391.87Skamil		sigemptyset(&sa.sa_mask);
2401.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2411.87Skamil
2421.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2431.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2441.87Skamil
2451.87Skamil		DPRINTF("Before raising %s from child\n",
2461.87Skamil		    strsignal(sigignored));
2471.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2481.87Skamil
2491.87Skamil		DPRINTF("Before exiting of the child process\n");
2501.87Skamil		_exit(exitval);
2511.87Skamil	}
2521.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2531.87Skamil
2541.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2551.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2561.87Skamil
2571.87Skamil	validate_status_stopped(status, sigval);
2581.87Skamil
2591.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2601.87Skamil	SYSCALL_REQUIRE(
2611.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2621.87Skamil
2631.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2641.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2651.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2661.87Skamil	    info.psi_siginfo.si_errno);
2671.87Skamil
2681.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2691.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2701.87Skamil
2711.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2721.87Skamil	    "without signal to be sent\n");
2731.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2741.87Skamil
2751.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2761.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2771.87Skamil
2781.87Skamil	validate_status_stopped(status, sigignored);
2791.87Skamil
2801.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2811.87Skamil	SYSCALL_REQUIRE(
2821.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2831.87Skamil
2841.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2851.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2861.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2871.87Skamil	    info.psi_siginfo.si_errno);
2881.87Skamil
2891.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2901.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2911.87Skamil
2921.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2931.87Skamil	    "without signal to be sent\n");
2941.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2951.87Skamil
2961.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2971.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2981.87Skamil
2991.87Skamil	validate_status_exited(status, exitval);
3001.87Skamil
3011.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3021.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3031.87Skamil}
3041.87Skamil
3051.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
3061.87SkamilATF_TC(test);								\
3071.87SkamilATF_TC_HEAD(test, tc)							\
3081.87Skamil{									\
3091.87Skamil	atf_tc_set_md_var(tc, "descr",					\
3101.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
3111.87Skamil	    "does not stop tracer from catching this raised signal");	\
3121.87Skamil}									\
3131.87Skamil									\
3141.87SkamilATF_TC_BODY(test, tc)							\
3151.87Skamil{									\
3161.87Skamil									\
3171.87Skamil	traceme_raisesignal_ignored(sig);				\
3181.87Skamil}
3191.87Skamil
3201.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
3211.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
3221.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
3231.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
3241.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
3251.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
3261.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3271.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3281.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3291.87Skamil
3301.87Skamil/// ----------------------------------------------------------------------------
3311.87Skamil
3321.87Skamilstatic void
3331.86Skamiltraceme_raisesignal_masked(int sigmasked)
3341.86Skamil{
3351.86Skamil	const int exitval = 5;
3361.86Skamil	const int sigval = SIGSTOP;
3371.86Skamil	pid_t child, wpid;
3381.86Skamil#if defined(TWAIT_HAVE_STATUS)
3391.86Skamil	int status;
3401.86Skamil#endif
3411.86Skamil	sigset_t intmask;
3421.86Skamil	struct ptrace_siginfo info;
3431.86Skamil
3441.86Skamil	memset(&info, 0, sizeof(info));
3451.86Skamil
3461.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3471.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3481.86Skamil	if (child == 0) {
3491.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3501.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3511.86Skamil
3521.86Skamil		sigemptyset(&intmask);
3531.86Skamil		sigaddset(&intmask, sigmasked);
3541.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3551.86Skamil
3561.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3571.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3581.86Skamil
3591.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3601.86Skamil		    strsignal(sigmasked));
3611.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3621.86Skamil
3631.86Skamil		DPRINTF("Before exiting of the child process\n");
3641.86Skamil		_exit(exitval);
3651.86Skamil	}
3661.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3671.86Skamil
3681.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3691.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3701.86Skamil
3711.86Skamil	validate_status_stopped(status, sigval);
3721.86Skamil
3731.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3741.86Skamil	SYSCALL_REQUIRE(
3751.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3761.86Skamil
3771.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3781.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3791.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3801.86Skamil	    info.psi_siginfo.si_errno);
3811.86Skamil
3821.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3831.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3841.86Skamil
3851.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3861.86Skamil	    "without signal to be sent\n");
3871.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3881.86Skamil
3891.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3901.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3911.86Skamil
3921.86Skamil	validate_status_exited(status, exitval);
3931.86Skamil
3941.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3951.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3961.86Skamil}
3971.86Skamil
3981.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3991.86SkamilATF_TC(test);								\
4001.86SkamilATF_TC_HEAD(test, tc)							\
4011.86Skamil{									\
4021.86Skamil	atf_tc_set_md_var(tc, "descr",					\
4031.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
4041.86Skamil	    "stops tracer from catching this raised signal");		\
4051.86Skamil}									\
4061.86Skamil									\
4071.86SkamilATF_TC_BODY(test, tc)							\
4081.86Skamil{									\
4091.86Skamil									\
4101.86Skamil	traceme_raisesignal_masked(sig);				\
4111.86Skamil}
4121.86Skamil
4131.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4141.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
4151.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
4161.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
4171.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
4181.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
4191.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
4201.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
4211.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
4221.86Skamil
4231.86Skamil/// ----------------------------------------------------------------------------
4241.86Skamil
4251.86Skamilstatic void
4261.59Skamiltraceme_crash(int sig)
4271.59Skamil{
4281.59Skamil	pid_t child, wpid;
4291.59Skamil#if defined(TWAIT_HAVE_STATUS)
4301.59Skamil	int status;
4311.59Skamil#endif
4321.59Skamil	struct ptrace_siginfo info;
4331.61Skre
4341.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4351.71Skamil	if (sig == SIGILL)
4361.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4371.71Skamil#endif
4381.71Skamil
4391.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
4401.114Skamil		atf_tc_skip("FP exceptions are not supported");
4411.114Skamil
4421.59Skamil	memset(&info, 0, sizeof(info));
4431.59Skamil
4441.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4451.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4461.59Skamil	if (child == 0) {
4471.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4481.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4491.59Skamil
4501.59Skamil		DPRINTF("Before executing a trap\n");
4511.59Skamil		switch (sig) {
4521.59Skamil		case SIGTRAP:
4531.59Skamil			trigger_trap();
4541.59Skamil			break;
4551.59Skamil		case SIGSEGV:
4561.59Skamil			trigger_segv();
4571.59Skamil			break;
4581.59Skamil		case SIGILL:
4591.59Skamil			trigger_ill();
4601.59Skamil			break;
4611.59Skamil		case SIGFPE:
4621.59Skamil			trigger_fpe();
4631.59Skamil			break;
4641.59Skamil		case SIGBUS:
4651.59Skamil			trigger_bus();
4661.59Skamil			break;
4671.59Skamil		default:
4681.59Skamil			/* NOTREACHED */
4691.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4701.59Skamil		}
4711.59Skamil
4721.59Skamil		/* NOTREACHED */
4731.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4741.59Skamil	}
4751.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4761.59Skamil
4771.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4781.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4791.59Skamil
4801.59Skamil	validate_status_stopped(status, sig);
4811.59Skamil
4821.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4831.61Skre	SYSCALL_REQUIRE(
4841.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4851.59Skamil
4861.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4871.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4881.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4891.61Skre	    info.psi_siginfo.si_errno);
4901.59Skamil
4911.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4921.59Skamil	switch (sig) {
4931.59Skamil	case SIGTRAP:
4941.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4951.59Skamil		break;
4961.59Skamil	case SIGSEGV:
4971.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4981.59Skamil		break;
4991.71Skamil	case SIGILL:
5001.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
5011.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
5021.71Skamil		break;
5031.59Skamil	case SIGFPE:
5041.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
5051.59Skamil		break;
5061.59Skamil	case SIGBUS:
5071.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
5081.59Skamil		break;
5091.59Skamil	}
5101.59Skamil
5111.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
5121.59Skamil
5131.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5141.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5151.59Skamil
5161.59Skamil	validate_status_signaled(status, SIGKILL, 0);
5171.59Skamil
5181.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5191.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5201.59Skamil}
5211.59Skamil
5221.61Skre#define TRACEME_CRASH(test, sig)					\
5231.61SkreATF_TC(test);								\
5241.61SkreATF_TC_HEAD(test, tc)							\
5251.61Skre{									\
5261.61Skre	atf_tc_set_md_var(tc, "descr",					\
5271.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
5281.61Skre}									\
5291.61Skre									\
5301.61SkreATF_TC_BODY(test, tc)							\
5311.61Skre{									\
5321.61Skre									\
5331.61Skre	traceme_crash(sig);						\
5341.59Skamil}
5351.59Skamil
5361.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5371.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5381.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5391.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5401.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5411.59Skamil
5421.59Skamil/// ----------------------------------------------------------------------------
5431.59Skamil
5441.59Skamilstatic void
5451.88Skamiltraceme_signalmasked_crash(int sig)
5461.88Skamil{
5471.89Skamil	const int sigval = SIGSTOP;
5481.88Skamil	pid_t child, wpid;
5491.88Skamil#if defined(TWAIT_HAVE_STATUS)
5501.88Skamil	int status;
5511.88Skamil#endif
5521.88Skamil	struct ptrace_siginfo info;
5531.88Skamil	sigset_t intmask;
5541.89Skamil	struct kinfo_proc2 kp;
5551.89Skamil	size_t len = sizeof(kp);
5561.89Skamil
5571.89Skamil	int name[6];
5581.89Skamil	const size_t namelen = __arraycount(name);
5591.89Skamil	ki_sigset_t kp_sigmask;
5601.88Skamil
5611.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5621.88Skamil	if (sig == SIGILL)
5631.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5641.88Skamil#endif
5651.88Skamil
5661.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
5671.114Skamil		atf_tc_skip("FP exceptions are not supported");
5681.114Skamil
5691.88Skamil	memset(&info, 0, sizeof(info));
5701.88Skamil
5711.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5721.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5731.88Skamil	if (child == 0) {
5741.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5751.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5761.88Skamil
5771.88Skamil		sigemptyset(&intmask);
5781.88Skamil		sigaddset(&intmask, sig);
5791.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5801.88Skamil
5811.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5821.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5831.89Skamil
5841.88Skamil		DPRINTF("Before executing a trap\n");
5851.88Skamil		switch (sig) {
5861.88Skamil		case SIGTRAP:
5871.88Skamil			trigger_trap();
5881.88Skamil			break;
5891.88Skamil		case SIGSEGV:
5901.88Skamil			trigger_segv();
5911.88Skamil			break;
5921.88Skamil		case SIGILL:
5931.88Skamil			trigger_ill();
5941.88Skamil			break;
5951.88Skamil		case SIGFPE:
5961.88Skamil			trigger_fpe();
5971.88Skamil			break;
5981.88Skamil		case SIGBUS:
5991.88Skamil			trigger_bus();
6001.88Skamil			break;
6011.88Skamil		default:
6021.88Skamil			/* NOTREACHED */
6031.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
6041.88Skamil		}
6051.88Skamil
6061.88Skamil		/* NOTREACHED */
6071.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
6081.88Skamil	}
6091.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
6101.88Skamil
6111.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6121.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6131.88Skamil
6141.89Skamil	validate_status_stopped(status, sigval);
6151.89Skamil
6161.89Skamil	name[0] = CTL_KERN,
6171.89Skamil	name[1] = KERN_PROC2,
6181.89Skamil	name[2] = KERN_PROC_PID;
6191.89Skamil	name[3] = child;
6201.89Skamil	name[4] = sizeof(kp);
6211.89Skamil	name[5] = 1;
6221.89Skamil
6231.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6241.89Skamil
6251.89Skamil	kp_sigmask = kp.p_sigmask;
6261.89Skamil
6271.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6281.89Skamil	SYSCALL_REQUIRE(
6291.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6301.89Skamil
6311.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6321.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6331.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6341.89Skamil	    info.psi_siginfo.si_errno);
6351.89Skamil
6361.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6371.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6381.89Skamil
6391.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6401.89Skamil	    "without signal to be sent\n");
6411.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6421.89Skamil
6431.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6441.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6451.89Skamil
6461.88Skamil	validate_status_stopped(status, sig);
6471.88Skamil
6481.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6491.88Skamil	SYSCALL_REQUIRE(
6501.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6511.88Skamil
6521.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6531.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6541.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6551.88Skamil	    info.psi_siginfo.si_errno);
6561.88Skamil
6571.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6581.89Skamil
6591.89Skamil	DPRINTF("kp_sigmask="
6601.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6611.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6621.89Skamil	    kp_sigmask.__bits[3]);
6631.89Skamil
6641.89Skamil	DPRINTF("kp.p_sigmask="
6651.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6661.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6671.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6681.89Skamil
6691.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6701.89Skamil
6711.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6721.88Skamil	switch (sig) {
6731.88Skamil	case SIGTRAP:
6741.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6751.88Skamil		break;
6761.88Skamil	case SIGSEGV:
6771.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6781.88Skamil		break;
6791.88Skamil	case SIGILL:
6801.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
6811.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
6821.88Skamil		break;
6831.88Skamil	case SIGFPE:
6841.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6851.88Skamil		break;
6861.88Skamil	case SIGBUS:
6871.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6881.88Skamil		break;
6891.88Skamil	}
6901.88Skamil
6911.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6921.88Skamil
6931.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6941.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6951.88Skamil
6961.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6971.88Skamil
6981.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6991.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
7001.88Skamil}
7011.88Skamil
7021.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
7031.88SkamilATF_TC(test);								\
7041.88SkamilATF_TC_HEAD(test, tc)							\
7051.88Skamil{									\
7061.88Skamil	atf_tc_set_md_var(tc, "descr",					\
7071.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
7081.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
7091.88Skamil}									\
7101.88Skamil									\
7111.88SkamilATF_TC_BODY(test, tc)							\
7121.88Skamil{									\
7131.88Skamil									\
7141.88Skamil	traceme_signalmasked_crash(sig);				\
7151.88Skamil}
7161.88Skamil
7171.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
7181.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
7191.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
7201.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
7211.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
7221.88Skamil
7231.88Skamil/// ----------------------------------------------------------------------------
7241.88Skamil
7251.88Skamilstatic void
7261.88Skamiltraceme_signalignored_crash(int sig)
7271.88Skamil{
7281.90Skamil	const int sigval = SIGSTOP;
7291.88Skamil	pid_t child, wpid;
7301.88Skamil#if defined(TWAIT_HAVE_STATUS)
7311.88Skamil	int status;
7321.88Skamil#endif
7331.88Skamil	struct sigaction sa;
7341.88Skamil	struct ptrace_siginfo info;
7351.90Skamil	struct kinfo_proc2 kp;
7361.90Skamil	size_t len = sizeof(kp);
7371.90Skamil
7381.90Skamil	int name[6];
7391.90Skamil	const size_t namelen = __arraycount(name);
7401.90Skamil	ki_sigset_t kp_sigignore;
7411.88Skamil
7421.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7431.88Skamil	if (sig == SIGILL)
7441.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7451.88Skamil#endif
7461.88Skamil
7471.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
7481.114Skamil		atf_tc_skip("FP exceptions are not supported");
7491.114Skamil
7501.88Skamil	memset(&info, 0, sizeof(info));
7511.88Skamil
7521.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7531.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7541.88Skamil	if (child == 0) {
7551.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7561.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7571.88Skamil
7581.88Skamil		memset(&sa, 0, sizeof(sa));
7591.88Skamil		sa.sa_handler = SIG_IGN;
7601.88Skamil		sigemptyset(&sa.sa_mask);
7611.88Skamil
7621.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7631.88Skamil
7641.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7651.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7661.90Skamil
7671.88Skamil		DPRINTF("Before executing a trap\n");
7681.88Skamil		switch (sig) {
7691.88Skamil		case SIGTRAP:
7701.88Skamil			trigger_trap();
7711.88Skamil			break;
7721.88Skamil		case SIGSEGV:
7731.88Skamil			trigger_segv();
7741.88Skamil			break;
7751.88Skamil		case SIGILL:
7761.88Skamil			trigger_ill();
7771.88Skamil			break;
7781.88Skamil		case SIGFPE:
7791.88Skamil			trigger_fpe();
7801.88Skamil			break;
7811.88Skamil		case SIGBUS:
7821.88Skamil			trigger_bus();
7831.88Skamil			break;
7841.88Skamil		default:
7851.88Skamil			/* NOTREACHED */
7861.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7871.88Skamil		}
7881.88Skamil
7891.88Skamil		/* NOTREACHED */
7901.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7911.88Skamil	}
7921.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7931.88Skamil
7941.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7951.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7961.88Skamil
7971.90Skamil	validate_status_stopped(status, sigval);
7981.90Skamil
7991.90Skamil	name[0] = CTL_KERN,
8001.90Skamil	name[1] = KERN_PROC2,
8011.90Skamil	name[2] = KERN_PROC_PID;
8021.90Skamil	name[3] = child;
8031.90Skamil	name[4] = sizeof(kp);
8041.90Skamil	name[5] = 1;
8051.90Skamil
8061.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8071.90Skamil
8081.90Skamil	kp_sigignore = kp.p_sigignore;
8091.90Skamil
8101.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
8111.90Skamil	SYSCALL_REQUIRE(
8121.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8131.90Skamil
8141.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8151.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8161.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8171.90Skamil	    info.psi_siginfo.si_errno);
8181.90Skamil
8191.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8201.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
8211.90Skamil
8221.90Skamil	DPRINTF("Before resuming the child process where it left off and "
8231.90Skamil	    "without signal to be sent\n");
8241.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8251.90Skamil
8261.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8271.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8281.90Skamil
8291.88Skamil	validate_status_stopped(status, sig);
8301.88Skamil
8311.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
8321.88Skamil	SYSCALL_REQUIRE(
8331.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8341.88Skamil
8351.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8361.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8371.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8381.88Skamil	    info.psi_siginfo.si_errno);
8391.88Skamil
8401.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8411.90Skamil
8421.90Skamil	DPRINTF("kp_sigignore="
8431.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8441.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8451.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8461.90Skamil
8471.90Skamil	DPRINTF("kp.p_sigignore="
8481.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8491.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8501.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8511.90Skamil
8521.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8531.90Skamil
8541.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8551.88Skamil	switch (sig) {
8561.88Skamil	case SIGTRAP:
8571.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8581.88Skamil		break;
8591.88Skamil	case SIGSEGV:
8601.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8611.88Skamil		break;
8621.88Skamil	case SIGILL:
8631.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
8641.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
8651.88Skamil		break;
8661.88Skamil	case SIGFPE:
8671.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8681.88Skamil		break;
8691.88Skamil	case SIGBUS:
8701.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8711.88Skamil		break;
8721.88Skamil	}
8731.88Skamil
8741.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8751.88Skamil
8761.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8771.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8781.88Skamil
8791.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8801.88Skamil
8811.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8821.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8831.88Skamil}
8841.88Skamil
8851.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8861.88SkamilATF_TC(test);								\
8871.88SkamilATF_TC_HEAD(test, tc)							\
8881.88Skamil{									\
8891.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8901.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8911.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8921.88Skamil}									\
8931.88Skamil									\
8941.88SkamilATF_TC_BODY(test, tc)							\
8951.88Skamil{									\
8961.88Skamil									\
8971.88Skamil	traceme_signalignored_crash(sig);				\
8981.88Skamil}
8991.88Skamil
9001.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
9011.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
9021.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
9031.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
9041.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
9051.88Skamil
9061.88Skamil/// ----------------------------------------------------------------------------
9071.88Skamil
9081.88Skamilstatic void
9091.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
9101.1Skamil{
9111.1Skamil	const int exitval = 5;
9121.34Skamil	const int sigval = SIGSTOP;
9131.1Skamil	pid_t child, wpid;
9141.1Skamil	struct sigaction sa;
9151.1Skamil#if defined(TWAIT_HAVE_STATUS)
9161.1Skamil	int status;
9171.1Skamil#endif
9181.61Skre	struct ptrace_siginfo info;
9191.1Skamil
9201.45Skamil	memset(&info, 0, sizeof(info));
9211.45Skamil
9221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
9231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
9241.1Skamil	if (child == 0) {
9251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9271.1Skamil
9281.34Skamil		sa.sa_handler = sah;
9291.1Skamil		sa.sa_flags = SA_SIGINFO;
9301.1Skamil		sigemptyset(&sa.sa_mask);
9311.1Skamil
9321.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
9331.1Skamil
9341.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9351.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9361.1Skamil
9371.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9381.1Skamil
9391.13Schristos		DPRINTF("Before exiting of the child process\n");
9401.1Skamil		_exit(exitval);
9411.1Skamil	}
9421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9431.1Skamil
9441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9461.1Skamil
9471.1Skamil	validate_status_stopped(status, sigval);
9481.1Skamil
9491.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9501.61Skre	SYSCALL_REQUIRE(
9511.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9521.45Skamil
9531.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9541.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9551.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9561.45Skamil	    info.psi_siginfo.si_errno);
9571.45Skamil
9581.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9591.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9601.45Skamil
9611.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9621.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9641.1Skamil
9651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9671.1Skamil
9681.1Skamil	validate_status_exited(status, exitval);
9691.1Skamil
9701.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9721.1Skamil}
9731.1Skamil
9741.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9751.61SkreATF_TC(test);								\
9761.61SkreATF_TC_HEAD(test, tc)							\
9771.61Skre{									\
9781.61Skre	atf_tc_set_md_var(tc, "descr",					\
9791.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9801.61Skre	    "handled correctly and caught by a signal handler");	\
9811.61Skre}									\
9821.61Skre									\
9831.61Skrestatic int test##_caught = 0;						\
9841.61Skre									\
9851.61Skrestatic void								\
9861.61Skretest##_sighandler(int arg)						\
9871.61Skre{									\
9881.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9891.61Skre									\
9901.61Skre	++ test##_caught;						\
9911.61Skre}									\
9921.61Skre									\
9931.61SkreATF_TC_BODY(test, tc)							\
9941.61Skre{									\
9951.61Skre									\
9961.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9971.34Skamil}
9981.34Skamil
9991.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
10001.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
10011.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
10021.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
10031.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
10041.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
10051.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
10061.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
10071.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
10081.34Skamil
10091.34Skamil/// ----------------------------------------------------------------------------
10101.34Skamil
10111.35Skamilstatic void
10121.50Skamiltraceme_sendsignal_masked(int sigsent)
10131.50Skamil{
10141.50Skamil	const int exitval = 5;
10151.50Skamil	const int sigval = SIGSTOP;
10161.50Skamil	pid_t child, wpid;
10171.50Skamil	sigset_t set;
10181.50Skamil#if defined(TWAIT_HAVE_STATUS)
10191.50Skamil	int status;
10201.50Skamil#endif
10211.61Skre	struct ptrace_siginfo info;
10221.50Skamil
10231.50Skamil	memset(&info, 0, sizeof(info));
10241.50Skamil
10251.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10261.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10271.50Skamil	if (child == 0) {
10281.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10291.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10301.50Skamil
10311.50Skamil		sigemptyset(&set);
10321.50Skamil		sigaddset(&set, sigsent);
10331.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
10341.50Skamil
10351.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10361.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10371.50Skamil
10381.50Skamil		_exit(exitval);
10391.50Skamil	}
10401.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10411.50Skamil
10421.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10431.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10441.50Skamil
10451.50Skamil	validate_status_stopped(status, sigval);
10461.50Skamil
10471.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10481.61Skre	SYSCALL_REQUIRE(
10491.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10501.50Skamil
10511.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10521.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10531.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10541.50Skamil	    info.psi_siginfo.si_errno);
10551.50Skamil
10561.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10571.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10581.50Skamil
10591.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10601.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10611.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10621.50Skamil
10631.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10641.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10651.50Skamil
10661.50Skamil	validate_status_exited(status, exitval);
10671.50Skamil
10681.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10691.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10701.50Skamil}
10711.50Skamil
10721.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10731.61SkreATF_TC(test);								\
10741.61SkreATF_TC_HEAD(test, tc)							\
10751.61Skre{									\
10761.61Skre	atf_tc_set_md_var(tc, "descr",					\
10771.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10781.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10791.61Skre}									\
10801.61Skre									\
10811.61SkreATF_TC_BODY(test, tc)							\
10821.61Skre{									\
10831.61Skre									\
10841.61Skre	traceme_sendsignal_masked(sig);					\
10851.50Skamil}
10861.50Skamil
10871.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10881.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10891.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10901.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10911.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10921.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10931.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10941.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10951.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10961.50Skamil
10971.50Skamil/// ----------------------------------------------------------------------------
10981.50Skamil
10991.50Skamilstatic void
11001.50Skamiltraceme_sendsignal_ignored(int sigsent)
11011.50Skamil{
11021.50Skamil	const int exitval = 5;
11031.50Skamil	const int sigval = SIGSTOP;
11041.50Skamil	pid_t child, wpid;
11051.50Skamil	struct sigaction sa;
11061.50Skamil#if defined(TWAIT_HAVE_STATUS)
11071.50Skamil	int status;
11081.50Skamil#endif
11091.61Skre	struct ptrace_siginfo info;
11101.50Skamil
11111.50Skamil	memset(&info, 0, sizeof(info));
11121.50Skamil
11131.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
11141.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
11151.50Skamil	if (child == 0) {
11161.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11171.61Skre
11181.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11191.50Skamil
11201.50Skamil		memset(&sa, 0, sizeof(sa));
11211.50Skamil		sa.sa_handler = SIG_IGN;
11221.50Skamil		sigemptyset(&sa.sa_mask);
11231.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
11241.50Skamil
11251.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11261.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11271.50Skamil
11281.50Skamil		_exit(exitval);
11291.50Skamil	}
11301.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11311.50Skamil
11321.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11331.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11341.50Skamil
11351.50Skamil	validate_status_stopped(status, sigval);
11361.50Skamil
11371.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11381.61Skre	SYSCALL_REQUIRE(
11391.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11401.50Skamil
11411.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11421.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11431.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11441.50Skamil	    info.psi_siginfo.si_errno);
11451.50Skamil
11461.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11471.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11481.50Skamil
11491.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11501.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11511.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11521.50Skamil
11531.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11541.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11551.50Skamil
11561.50Skamil	validate_status_exited(status, exitval);
11571.50Skamil
11581.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11591.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11601.50Skamil}
11611.50Skamil
11621.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11631.61SkreATF_TC(test);								\
11641.61SkreATF_TC_HEAD(test, tc)							\
11651.61Skre{									\
11661.61Skre	atf_tc_set_md_var(tc, "descr",					\
11671.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11681.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11691.61Skre}									\
11701.61Skre									\
11711.61SkreATF_TC_BODY(test, tc)							\
11721.61Skre{									\
11731.61Skre									\
11741.61Skre	traceme_sendsignal_ignored(sig);				\
11751.50Skamil}
11761.50Skamil
11771.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11781.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11791.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11801.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11811.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11821.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11831.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11841.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11851.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11861.50Skamil
11871.50Skamil/// ----------------------------------------------------------------------------
11881.50Skamil
11891.50Skamilstatic void
11901.50Skamiltraceme_sendsignal_simple(int sigsent)
11911.1Skamil{
11921.35Skamil	const int sigval = SIGSTOP;
11931.35Skamil	int exitval = 0;
11941.1Skamil	pid_t child, wpid;
11951.1Skamil#if defined(TWAIT_HAVE_STATUS)
11961.1Skamil	int status;
11971.85Skamil	int expect_core;
11981.85Skamil
11991.85Skamil	switch (sigsent) {
12001.85Skamil	case SIGABRT:
12011.85Skamil	case SIGTRAP:
12021.85Skamil	case SIGBUS:
12031.85Skamil	case SIGILL:
12041.85Skamil	case SIGFPE:
12051.85Skamil	case SIGSEGV:
12061.85Skamil		expect_core = 1;
12071.85Skamil		break;
12081.85Skamil	default:
12091.85Skamil		expect_core = 0;
12101.85Skamil		break;
12111.85Skamil	}
12121.1Skamil#endif
12131.61Skre	struct ptrace_siginfo info;
12141.1Skamil
12151.45Skamil	memset(&info, 0, sizeof(info));
12161.45Skamil
12171.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12181.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12191.1Skamil	if (child == 0) {
12201.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12211.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12221.1Skamil
12231.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12241.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12251.1Skamil
12261.35Skamil		switch (sigsent) {
12271.35Skamil		case SIGCONT:
12281.48Skamil		case SIGSTOP:
12291.35Skamil			_exit(exitval);
12301.35Skamil		default:
12311.35Skamil			/* NOTREACHED */
12321.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
12331.35Skamil		}
12341.1Skamil	}
12351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12361.1Skamil
12371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12391.1Skamil
12401.1Skamil	validate_status_stopped(status, sigval);
12411.1Skamil
12421.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12431.61Skre	SYSCALL_REQUIRE(
12441.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12451.45Skamil
12461.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12471.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12481.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12491.45Skamil	    info.psi_siginfo.si_errno);
12501.45Skamil
12511.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12521.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12531.45Skamil
12541.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12551.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12571.1Skamil
12581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12601.1Skamil
12611.35Skamil	switch (sigsent) {
12621.48Skamil	case SIGSTOP:
12631.48Skamil		validate_status_stopped(status, sigsent);
12641.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12651.61Skre		    "child\n");
12661.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12671.61Skre		    sizeof(info)) != -1);
12681.48Skamil
12691.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12701.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12711.61Skre		    "si_errno=%#x\n",
12721.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12731.61Skre		    info.psi_siginfo.si_errno);
12741.48Skamil
12751.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12761.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12771.48Skamil
12781.48Skamil		DPRINTF("Before resuming the child process where it left off "
12791.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12801.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12811.48Skamil
12821.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12831.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12841.61Skre		    child);
12851.48Skamil		/* FALLTHROUGH */
12861.35Skamil	case SIGCONT:
12871.35Skamil		validate_status_exited(status, exitval);
12881.35Skamil		break;
12891.35Skamil	default:
12901.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12911.35Skamil		break;
12921.35Skamil	}
12931.1Skamil
12941.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12951.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12961.1Skamil}
12971.1Skamil
12981.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12991.61SkreATF_TC(test);								\
13001.61SkreATF_TC_HEAD(test, tc)							\
13011.61Skre{									\
13021.61Skre	atf_tc_set_md_var(tc, "descr",					\
13031.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
13041.61Skre	    "handled correctly in a child without a signal handler");	\
13051.61Skre}									\
13061.61Skre									\
13071.61SkreATF_TC_BODY(test, tc)							\
13081.61Skre{									\
13091.61Skre									\
13101.61Skre	traceme_sendsignal_simple(sig);					\
13111.35Skamil}
13121.35Skamil
13131.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
13141.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
13151.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
13161.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
13171.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
13181.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
13191.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
13201.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
13211.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
13221.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
13231.35Skamil
13241.35Skamil/// ----------------------------------------------------------------------------
13251.35Skamil
13261.37SkamilATF_TC(traceme_pid1_parent);
13271.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
13281.37Skamil{
13291.37Skamil	atf_tc_set_md_var(tc, "descr",
13301.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
13311.37Skamil}
13321.37Skamil
13331.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
13341.37Skamil{
13351.37Skamil	struct msg_fds parent_child;
13361.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13371.37Skamil	pid_t child1, child2, wpid;
13381.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13391.37Skamil#if defined(TWAIT_HAVE_STATUS)
13401.37Skamil	int status;
13411.37Skamil#endif
13421.37Skamil
13431.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13441.37Skamil
13451.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13461.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13471.37Skamil	if (child1 == 0) {
13481.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13491.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13501.37Skamil		if (child2 != 0) {
13511.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13521.61Skre			    getpid(), child2);
13531.37Skamil			_exit(exitval_child1);
13541.37Skamil		}
13551.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13561.37Skamil
13571.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13581.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13591.37Skamil
13601.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13611.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13621.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13631.37Skamil
13641.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13651.37Skamil
13661.37Skamil		_exit(exitval_child2);
13671.37Skamil	}
13681.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13691.37Skamil
13701.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13711.61Skre	TWAIT_REQUIRE_SUCCESS(
13721.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13731.37Skamil
13741.37Skamil	validate_status_exited(status, exitval_child1);
13751.37Skamil
13761.37Skamil	DPRINTF("Notify that child1 is dead\n");
13771.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13781.37Skamil
13791.37Skamil	DPRINTF("Wait for exiting of child2\n");
13801.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13811.37Skamil}
13821.37Skamil
13831.37Skamil/// ----------------------------------------------------------------------------
13841.37Skamil
13851.40Skamilstatic void
13861.40Skamiltraceme_vfork_raise(int sigval)
13871.40Skamil{
13881.46Skamil	const int exitval = 5, exitval_watcher = 10;
13891.46Skamil	pid_t child, parent, watcher, wpid;
13901.46Skamil	int rv;
13911.40Skamil#if defined(TWAIT_HAVE_STATUS)
13921.40Skamil	int status;
13931.85Skamil
13941.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13951.85Skamil	volatile int expect_core;
13961.85Skamil
13971.85Skamil	switch (sigval) {
13981.85Skamil	case SIGABRT:
13991.85Skamil	case SIGTRAP:
14001.85Skamil	case SIGBUS:
14011.85Skamil	case SIGILL:
14021.85Skamil	case SIGFPE:
14031.85Skamil	case SIGSEGV:
14041.85Skamil		expect_core = 1;
14051.85Skamil		break;
14061.85Skamil	default:
14071.85Skamil		expect_core = 0;
14081.85Skamil		break;
14091.85Skamil	}
14101.40Skamil#endif
14111.40Skamil
14121.46Skamil	/*
14131.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
14141.46Skamil	 * the SIGKILL signal to it.
14151.46Skamil	 *
14161.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
14171.46Skamil	 * simpler to reparent this process to initproc and forget about it.
14181.46Skamil	 */
14191.46Skamil	if (sigval == SIGSTOP) {
14201.46Skamil		parent = getpid();
14211.46Skamil
14221.46Skamil		watcher = fork();
14231.46Skamil		ATF_REQUIRE(watcher != 1);
14241.46Skamil		if (watcher == 0) {
14251.46Skamil			/* Double fork(2) trick to reparent to initproc */
14261.46Skamil			watcher = fork();
14271.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
14281.46Skamil			if (watcher != 0)
14291.46Skamil				_exit(exitval_watcher);
14301.46Skamil
14311.46Skamil			child = await_stopped_child(parent);
14321.46Skamil
14331.46Skamil			errno = 0;
14341.46Skamil			rv = kill(child, SIGKILL);
14351.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
14361.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14371.46Skamil
14381.46Skamil			/* This exit value will be collected by initproc */
14391.46Skamil			_exit(0);
14401.46Skamil		}
14411.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14421.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14431.61Skre		    watcher);
14441.46Skamil
14451.46Skamil		validate_status_exited(status, exitval_watcher);
14461.46Skamil
14471.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14481.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14491.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14501.46Skamil	}
14511.46Skamil
14521.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14531.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14541.40Skamil	if (child == 0) {
14551.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14561.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14571.40Skamil
14581.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14591.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14601.40Skamil
14611.40Skamil		switch (sigval) {
14621.46Skamil		case SIGSTOP:
14631.40Skamil		case SIGKILL:
14641.40Skamil		case SIGABRT:
14651.40Skamil		case SIGHUP:
14661.85Skamil		case SIGTRAP:
14671.85Skamil		case SIGBUS:
14681.85Skamil		case SIGILL:
14691.85Skamil		case SIGFPE:
14701.85Skamil		case SIGSEGV:
14711.40Skamil			/* NOTREACHED */
14721.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14731.70Smrg			__unreachable();
14741.40Skamil		default:
14751.40Skamil			DPRINTF("Before exiting of the child process\n");
14761.40Skamil			_exit(exitval);
14771.40Skamil		}
14781.40Skamil	}
14791.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14801.40Skamil
14811.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14821.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14831.40Skamil
14841.40Skamil	switch (sigval) {
14851.40Skamil	case SIGKILL:
14861.40Skamil	case SIGABRT:
14871.40Skamil	case SIGHUP:
14881.85Skamil	case SIGTRAP:
14891.85Skamil	case SIGBUS:
14901.85Skamil	case SIGILL:
14911.85Skamil	case SIGFPE:
14921.85Skamil	case SIGSEGV:
14931.40Skamil		validate_status_signaled(status, sigval, expect_core);
14941.40Skamil		break;
14951.40Skamil	case SIGSTOP:
14961.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14971.46Skamil		break;
14981.40Skamil	case SIGCONT:
14991.47Skamil	case SIGTSTP:
15001.47Skamil	case SIGTTIN:
15011.47Skamil	case SIGTTOU:
15021.40Skamil		validate_status_exited(status, exitval);
15031.40Skamil		break;
15041.40Skamil	default:
15051.40Skamil		/* NOTREACHED */
15061.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
15071.40Skamil		break;
15081.40Skamil	}
15091.40Skamil
15101.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15111.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15121.40Skamil}
15131.40Skamil
15141.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
15151.61SkreATF_TC(test);								\
15161.61SkreATF_TC_HEAD(test, tc)							\
15171.61Skre{									\
15181.61Skre	atf_tc_set_md_var(tc, "descr",					\
15191.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
15201.61Skre	    "vfork(2)ed child");					\
15211.61Skre}									\
15221.61Skre									\
15231.61SkreATF_TC_BODY(test, tc)							\
15241.61Skre{									\
15251.61Skre									\
15261.61Skre	traceme_vfork_raise(sig);					\
15271.40Skamil}
15281.40Skamil
15291.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
15301.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
15311.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
15321.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
15331.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
15341.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
15351.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
15361.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15371.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15381.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15391.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15401.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15411.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15421.40Skamil
15431.40Skamil/// ----------------------------------------------------------------------------
15441.40Skamil
15451.52Skamilstatic void
15461.52Skamiltraceme_vfork_crash(int sig)
15471.41Skamil{
15481.41Skamil	pid_t child, wpid;
15491.41Skamil#if defined(TWAIT_HAVE_STATUS)
15501.41Skamil	int status;
15511.41Skamil#endif
15521.41Skamil
15531.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15541.71Skamil	if (sig == SIGILL)
15551.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15561.71Skamil#endif
15571.71Skamil
15581.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
15591.114Skamil		atf_tc_skip("FP exceptions are not supported");
15601.114Skamil
15611.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15621.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15631.41Skamil	if (child == 0) {
15641.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15651.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15661.41Skamil
15671.52Skamil		DPRINTF("Before executing a trap\n");
15681.52Skamil		switch (sig) {
15691.52Skamil		case SIGTRAP:
15701.52Skamil			trigger_trap();
15711.52Skamil			break;
15721.52Skamil		case SIGSEGV:
15731.52Skamil			trigger_segv();
15741.52Skamil			break;
15751.52Skamil		case SIGILL:
15761.52Skamil			trigger_ill();
15771.52Skamil			break;
15781.52Skamil		case SIGFPE:
15791.52Skamil			trigger_fpe();
15801.52Skamil			break;
15811.52Skamil		case SIGBUS:
15821.52Skamil			trigger_bus();
15831.52Skamil			break;
15841.52Skamil		default:
15851.52Skamil			/* NOTREACHED */
15861.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15871.52Skamil		}
15881.41Skamil
15891.41Skamil		/* NOTREACHED */
15901.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15911.41Skamil	}
15921.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15931.41Skamil
15941.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15951.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15961.41Skamil
15971.52Skamil	validate_status_signaled(status, sig, 1);
15981.41Skamil
15991.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16001.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16011.41Skamil}
16021.41Skamil
16031.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
16041.61SkreATF_TC(test);								\
16051.61SkreATF_TC_HEAD(test, tc)							\
16061.61Skre{									\
16071.61Skre	atf_tc_set_md_var(tc, "descr",					\
16081.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16091.61Skre	    "vfork(2)ed child");					\
16101.61Skre}									\
16111.61Skre									\
16121.61SkreATF_TC_BODY(test, tc)							\
16131.61Skre{									\
16141.61Skre									\
16151.61Skre	traceme_vfork_crash(sig);					\
16161.52Skamil}
16171.52Skamil
16181.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
16191.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
16201.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
16211.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
16221.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
16231.52Skamil
16241.41Skamil/// ----------------------------------------------------------------------------
16251.41Skamil
16261.92Skamilstatic void
16271.92Skamiltraceme_vfork_signalmasked_crash(int sig)
16281.92Skamil{
16291.92Skamil	pid_t child, wpid;
16301.92Skamil#if defined(TWAIT_HAVE_STATUS)
16311.92Skamil	int status;
16321.92Skamil#endif
16331.92Skamil	sigset_t intmask;
16341.92Skamil
16351.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16361.92Skamil	if (sig == SIGILL)
16371.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16381.92Skamil#endif
16391.92Skamil
16401.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
16411.114Skamil		atf_tc_skip("FP exceptions are not supported");
16421.114Skamil
16431.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16441.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16451.92Skamil	if (child == 0) {
16461.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16471.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16481.92Skamil
16491.92Skamil		sigemptyset(&intmask);
16501.92Skamil		sigaddset(&intmask, sig);
16511.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16521.92Skamil
16531.92Skamil		DPRINTF("Before executing a trap\n");
16541.92Skamil		switch (sig) {
16551.92Skamil		case SIGTRAP:
16561.92Skamil			trigger_trap();
16571.92Skamil			break;
16581.92Skamil		case SIGSEGV:
16591.92Skamil			trigger_segv();
16601.92Skamil			break;
16611.92Skamil		case SIGILL:
16621.92Skamil			trigger_ill();
16631.92Skamil			break;
16641.92Skamil		case SIGFPE:
16651.92Skamil			trigger_fpe();
16661.92Skamil			break;
16671.92Skamil		case SIGBUS:
16681.92Skamil			trigger_bus();
16691.92Skamil			break;
16701.92Skamil		default:
16711.92Skamil			/* NOTREACHED */
16721.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16731.92Skamil		}
16741.92Skamil
16751.92Skamil		/* NOTREACHED */
16761.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16771.92Skamil	}
16781.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16791.92Skamil
16801.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16811.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16821.92Skamil
16831.92Skamil	validate_status_signaled(status, sig, 1);
16841.92Skamil
16851.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16861.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16871.92Skamil}
16881.92Skamil
16891.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16901.92SkamilATF_TC(test);								\
16911.92SkamilATF_TC_HEAD(test, tc)							\
16921.92Skamil{									\
16931.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16941.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16951.92Skamil	    "vfork(2)ed child with a masked signal");			\
16961.92Skamil}									\
16971.92Skamil									\
16981.92SkamilATF_TC_BODY(test, tc)							\
16991.92Skamil{									\
17001.92Skamil									\
17011.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
17021.92Skamil}
17031.92Skamil
17041.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
17051.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
17061.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
17071.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
17081.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
17091.92Skamil
17101.92Skamil/// ----------------------------------------------------------------------------
17111.92Skamil
17121.92Skamilstatic void
17131.92Skamiltraceme_vfork_signalignored_crash(int sig)
17141.92Skamil{
17151.92Skamil	pid_t child, wpid;
17161.92Skamil#if defined(TWAIT_HAVE_STATUS)
17171.92Skamil	int status;
17181.92Skamil#endif
17191.92Skamil	struct sigaction sa;
17201.92Skamil
17211.92Skamil#ifndef PTRACE_ILLEGAL_ASM
17221.92Skamil	if (sig == SIGILL)
17231.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
17241.92Skamil#endif
17251.92Skamil
17261.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
17271.114Skamil		atf_tc_skip("FP exceptions are not supported");
17281.114Skamil
17291.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17301.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17311.92Skamil	if (child == 0) {
17321.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17331.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17341.92Skamil
17351.92Skamil		memset(&sa, 0, sizeof(sa));
17361.92Skamil		sa.sa_handler = SIG_IGN;
17371.92Skamil		sigemptyset(&sa.sa_mask);
17381.92Skamil
17391.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
17401.92Skamil
17411.92Skamil		DPRINTF("Before executing a trap\n");
17421.92Skamil		switch (sig) {
17431.92Skamil		case SIGTRAP:
17441.92Skamil			trigger_trap();
17451.92Skamil			break;
17461.92Skamil		case SIGSEGV:
17471.92Skamil			trigger_segv();
17481.92Skamil			break;
17491.92Skamil		case SIGILL:
17501.92Skamil			trigger_ill();
17511.92Skamil			break;
17521.92Skamil		case SIGFPE:
17531.92Skamil			trigger_fpe();
17541.92Skamil			break;
17551.92Skamil		case SIGBUS:
17561.92Skamil			trigger_bus();
17571.92Skamil			break;
17581.92Skamil		default:
17591.92Skamil			/* NOTREACHED */
17601.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17611.92Skamil		}
17621.92Skamil
17631.92Skamil		/* NOTREACHED */
17641.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17651.92Skamil	}
17661.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17671.92Skamil
17681.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17691.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17701.92Skamil
17711.92Skamil	validate_status_signaled(status, sig, 1);
17721.92Skamil
17731.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17741.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17751.92Skamil}
17761.92Skamil
17771.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17781.92SkamilATF_TC(test);								\
17791.92SkamilATF_TC_HEAD(test, tc)							\
17801.92Skamil{									\
17811.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17821.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17831.92Skamil	    "vfork(2)ed child with ignored signal");			\
17841.92Skamil}									\
17851.92Skamil									\
17861.92SkamilATF_TC_BODY(test, tc)							\
17871.92Skamil{									\
17881.92Skamil									\
17891.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17901.92Skamil}
17911.92Skamil
17921.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17931.92Skamil    SIGTRAP)
17941.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17951.92Skamil    SIGSEGV)
17961.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17971.92Skamil    SIGILL)
17981.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17991.92Skamil    SIGFPE)
18001.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
18011.92Skamil    SIGBUS)
18021.92Skamil
18031.92Skamil/// ----------------------------------------------------------------------------
18041.92Skamil
18051.96Skamilstatic void
18061.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
18071.43Skamil{
18081.43Skamil	const int sigval = SIGTRAP;
18091.43Skamil	pid_t child, wpid;
18101.43Skamil#if defined(TWAIT_HAVE_STATUS)
18111.43Skamil	int status;
18121.43Skamil#endif
18131.96Skamil	struct sigaction sa;
18141.61Skre	struct ptrace_siginfo info;
18151.96Skamil	sigset_t intmask;
18161.96Skamil	struct kinfo_proc2 kp;
18171.96Skamil	size_t len = sizeof(kp);
18181.96Skamil
18191.96Skamil	int name[6];
18201.96Skamil	const size_t namelen = __arraycount(name);
18211.96Skamil	ki_sigset_t kp_sigmask;
18221.96Skamil	ki_sigset_t kp_sigignore;
18231.43Skamil
18241.43Skamil	memset(&info, 0, sizeof(info));
18251.43Skamil
18261.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
18271.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
18281.43Skamil	if (child == 0) {
18291.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18301.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18311.43Skamil
18321.96Skamil		if (masked) {
18331.96Skamil			sigemptyset(&intmask);
18341.96Skamil			sigaddset(&intmask, sigval);
18351.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
18361.96Skamil		}
18371.96Skamil
18381.96Skamil		if (ignored) {
18391.96Skamil			memset(&sa, 0, sizeof(sa));
18401.96Skamil			sa.sa_handler = SIG_IGN;
18411.96Skamil			sigemptyset(&sa.sa_mask);
18421.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
18431.96Skamil		}
18441.96Skamil
18451.43Skamil		DPRINTF("Before calling execve(2) from child\n");
18461.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
18471.43Skamil
18481.43Skamil		/* NOTREACHED */
18491.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18501.43Skamil	}
18511.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18521.43Skamil
18531.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18541.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18551.43Skamil
18561.43Skamil	validate_status_stopped(status, sigval);
18571.43Skamil
18581.96Skamil	name[0] = CTL_KERN,
18591.96Skamil	name[1] = KERN_PROC2,
18601.96Skamil	name[2] = KERN_PROC_PID;
18611.96Skamil	name[3] = getpid();
18621.96Skamil	name[4] = sizeof(kp);
18631.96Skamil	name[5] = 1;
18641.96Skamil
18651.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18661.96Skamil
18671.96Skamil	if (masked)
18681.96Skamil		kp_sigmask = kp.p_sigmask;
18691.96Skamil
18701.96Skamil	if (ignored)
18711.96Skamil		kp_sigignore = kp.p_sigignore;
18721.96Skamil
18731.96Skamil	name[3] = getpid();
18741.96Skamil
18751.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18761.96Skamil
18771.96Skamil	if (masked) {
18781.96Skamil		DPRINTF("kp_sigmask="
18791.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18801.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18811.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18821.96Skamil
18831.96Skamil	        DPRINTF("kp.p_sigmask="
18841.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18851.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18861.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18871.96Skamil
18881.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18891.96Skamil		    sizeof(kp_sigmask)));
18901.96Skamil	}
18911.96Skamil
18921.96Skamil	if (ignored) {
18931.96Skamil		DPRINTF("kp_sigignore="
18941.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18951.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18961.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18971.96Skamil
18981.96Skamil	        DPRINTF("kp.p_sigignore="
18991.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
19001.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
19011.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
19021.96Skamil
19031.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
19041.96Skamil		    sizeof(kp_sigignore)));
19051.96Skamil	}
19061.96Skamil
19071.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
19081.61Skre	SYSCALL_REQUIRE(
19091.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
19101.43Skamil
19111.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
19121.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
19131.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
19141.43Skamil	    info.psi_siginfo.si_errno);
19151.43Skamil
19161.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
19171.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
19181.43Skamil
19191.43Skamil	DPRINTF("Before resuming the child process where it left off and "
19201.43Skamil	    "without signal to be sent\n");
19211.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19221.43Skamil
19231.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19241.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19251.43Skamil
19261.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19271.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19281.43Skamil}
19291.43Skamil
19301.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
19311.96SkamilATF_TC(test);								\
19321.96SkamilATF_TC_HEAD(test, tc)							\
19331.96Skamil{									\
19341.96Skamil	atf_tc_set_md_var(tc, "descr",					\
19351.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
19361.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
19371.96Skamil	    masked ? " with ignored signal" : "");			\
19381.96Skamil}									\
19391.96Skamil									\
19401.96SkamilATF_TC_BODY(test, tc)							\
19411.96Skamil{									\
19421.96Skamil									\
19431.96Skamil	traceme_vfork_exec(masked, ignored);				\
19441.96Skamil}
19451.96Skamil
19461.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
19471.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19481.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19491.96Skamil
19501.43Skamil/// ----------------------------------------------------------------------------
19511.43Skamil
19521.1Skamil#if defined(TWAIT_HAVE_PID)
19531.51Skamilstatic void
19541.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19551.59Skamil{
19561.94Skamil	const int sigval = SIGSTOP;
19571.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19581.59Skamil	const int exitval = 10;
19591.59Skamil	pid_t tracee, tracer, wpid;
19601.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19611.59Skamil#if defined(TWAIT_HAVE_STATUS)
19621.59Skamil	int status;
19631.59Skamil#endif
19641.94Skamil	struct sigaction sa;
19651.59Skamil	struct ptrace_siginfo info;
19661.94Skamil	sigset_t intmask;
19671.94Skamil	struct kinfo_proc2 kp;
19681.94Skamil	size_t len = sizeof(kp);
19691.94Skamil
19701.94Skamil	int name[6];
19711.94Skamil	const size_t namelen = __arraycount(name);
19721.94Skamil	ki_sigset_t kp_sigmask;
19731.94Skamil	ki_sigset_t kp_sigignore;
19741.61Skre
19751.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19761.71Skamil	if (sig == SIGILL)
19771.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19781.71Skamil#endif
19791.71Skamil
19801.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
19811.114Skamil		atf_tc_skip("FP exceptions are not supported");
19821.114Skamil
19831.59Skamil	memset(&info, 0, sizeof(info));
19841.59Skamil
19851.59Skamil	DPRINTF("Spawn tracee\n");
19861.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19871.59Skamil	tracee = atf_utils_fork();
19881.59Skamil	if (tracee == 0) {
19891.59Skamil		// Wait for parent to let us crash
19901.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19911.61Skre
19921.94Skamil		if (masked) {
19931.94Skamil			sigemptyset(&intmask);
19941.94Skamil			sigaddset(&intmask, sig);
19951.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19961.94Skamil		}
19971.94Skamil
19981.94Skamil		if (ignored) {
19991.94Skamil			memset(&sa, 0, sizeof(sa));
20001.94Skamil			sa.sa_handler = SIG_IGN;
20011.94Skamil			sigemptyset(&sa.sa_mask);
20021.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
20031.94Skamil		}
20041.94Skamil
20051.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20061.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20071.94Skamil
20081.59Skamil		DPRINTF("Before executing a trap\n");
20091.59Skamil		switch (sig) {
20101.59Skamil		case SIGTRAP:
20111.59Skamil			trigger_trap();
20121.59Skamil			break;
20131.59Skamil		case SIGSEGV:
20141.59Skamil			trigger_segv();
20151.59Skamil			break;
20161.59Skamil		case SIGILL:
20171.59Skamil			trigger_ill();
20181.59Skamil			break;
20191.59Skamil		case SIGFPE:
20201.59Skamil			trigger_fpe();
20211.59Skamil			break;
20221.59Skamil		case SIGBUS:
20231.59Skamil			trigger_bus();
20241.59Skamil			break;
20251.59Skamil		default:
20261.59Skamil			/* NOTREACHED */
20271.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
20281.59Skamil		}
20291.59Skamil
20301.59Skamil		/* NOTREACHED */
20311.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
20321.59Skamil	}
20331.59Skamil
20341.59Skamil	DPRINTF("Spawn debugger\n");
20351.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
20361.59Skamil	tracer = atf_utils_fork();
20371.59Skamil	if (tracer == 0) {
20381.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
20391.59Skamil		tracer = atf_utils_fork();
20401.59Skamil		if (tracer != 0)
20411.61Skre			_exit(exitval);
20421.59Skamil
20431.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
20441.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
20451.59Skamil
20461.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
20471.59Skamil		FORKEE_REQUIRE_SUCCESS(
20481.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20491.59Skamil
20501.59Skamil		forkee_status_stopped(status, SIGSTOP);
20511.59Skamil
20521.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20531.94Skamil		    "traced process\n");
20541.94Skamil		SYSCALL_REQUIRE(
20551.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20561.94Skamil
20571.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20581.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20591.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20601.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20611.94Skamil
20621.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20631.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20641.94Skamil
20651.59Skamil		/* Resume tracee with PT_CONTINUE */
20661.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20671.59Skamil
20681.59Skamil		/* Inform parent that tracer has attached to tracee */
20691.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20701.59Skamil
20711.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20721.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20731.59Skamil
20741.59Skamil		/* Wait for tracee and assert that it exited */
20751.59Skamil		FORKEE_REQUIRE_SUCCESS(
20761.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20771.59Skamil
20781.94Skamil		forkee_status_stopped(status, sigval);
20791.94Skamil
20801.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20811.94Skamil		    "traced process\n");
20821.94Skamil		SYSCALL_REQUIRE(
20831.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20841.94Skamil
20851.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20861.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20871.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20881.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20891.94Skamil
20901.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20911.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20921.94Skamil
20931.94Skamil		name[0] = CTL_KERN,
20941.94Skamil		name[1] = KERN_PROC2,
20951.94Skamil		name[2] = KERN_PROC_PID;
20961.94Skamil		name[3] = tracee;
20971.94Skamil		name[4] = sizeof(kp);
20981.94Skamil		name[5] = 1;
20991.94Skamil
21001.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
21011.94Skamil
21021.94Skamil		if (masked)
21031.94Skamil			kp_sigmask = kp.p_sigmask;
21041.94Skamil
21051.94Skamil		if (ignored)
21061.94Skamil			kp_sigignore = kp.p_sigignore;
21071.94Skamil
21081.94Skamil		/* Resume tracee with PT_CONTINUE */
21091.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
21101.94Skamil
21111.94Skamil		/* Wait for tracee and assert that it exited */
21121.94Skamil		FORKEE_REQUIRE_SUCCESS(
21131.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21141.94Skamil
21151.93Skamil		forkee_status_stopped(status, sig);
21161.59Skamil
21171.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
21181.61Skre		    "traced process\n");
21191.61Skre		SYSCALL_REQUIRE(
21201.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
21211.59Skamil
21221.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
21231.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
21241.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
21251.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
21261.59Skamil
21271.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
21281.94Skamil
21291.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
21301.94Skamil
21311.94Skamil		if (masked) {
21321.94Skamil			DPRINTF("kp_sigmask="
21331.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21341.94Skamil			    PRIx32 "\n",
21351.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
21361.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
21371.94Skamil
21381.94Skamil			DPRINTF("kp.p_sigmask="
21391.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21401.94Skamil			    PRIx32 "\n",
21411.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
21421.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
21431.94Skamil
21441.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
21451.94Skamil			    sizeof(kp_sigmask)));
21461.94Skamil		}
21471.94Skamil
21481.94Skamil		if (ignored) {
21491.94Skamil			DPRINTF("kp_sigignore="
21501.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21511.94Skamil			    PRIx32 "\n",
21521.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21531.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21541.94Skamil
21551.94Skamil			DPRINTF("kp.p_sigignore="
21561.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21571.94Skamil			    PRIx32 "\n",
21581.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21591.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21601.94Skamil
21611.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21621.94Skamil			    sizeof(kp_sigignore)));
21631.94Skamil		}
21641.94Skamil
21651.59Skamil		switch (sig) {
21661.59Skamil		case SIGTRAP:
21671.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21681.59Skamil			break;
21691.59Skamil		case SIGSEGV:
21701.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21711.59Skamil			break;
21721.71Skamil		case SIGILL:
21731.113Skamil			FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC &&
21741.112Skamil			            info.psi_siginfo.si_code <= ILL_BADSTK);
21751.71Skamil			break;
21761.59Skamil		case SIGFPE:
21771.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21781.59Skamil			break;
21791.59Skamil		case SIGBUS:
21801.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21811.59Skamil			break;
21821.59Skamil		}
21831.59Skamil
21841.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21851.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21861.93Skamil		FORKEE_REQUIRE_SUCCESS(
21871.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21881.59Skamil
21891.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21901.59Skamil
21911.71Skamil		/* Inform parent that tracer is exiting normally */
21921.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21931.71Skamil
21941.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21951.59Skamil		_exit(0 /* collect by initproc */);
21961.59Skamil	}
21971.59Skamil
21981.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21991.59Skamil	    "calling %s()\n", TWAIT_FNAME);
22001.59Skamil	TWAIT_REQUIRE_SUCCESS(
22011.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
22021.59Skamil
22031.59Skamil	validate_status_exited(status, exitval);
22041.59Skamil
22051.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
22061.59Skamil	    TWAIT_FNAME);
22071.59Skamil	TWAIT_REQUIRE_SUCCESS(
22081.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
22091.59Skamil
22101.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
22111.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
22121.59Skamil
22131.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
22141.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
22151.59Skamil
22161.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
22171.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
22181.59Skamil
22191.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
22201.59Skamil	    TWAIT_FNAME);
22211.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22221.59Skamil
22231.59Skamil	validate_status_signaled(status, SIGKILL, 0);
22241.59Skamil
22251.71Skamil	DPRINTF("Await normal exit of tracer\n");
22261.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
22271.71Skamil
22281.59Skamil	msg_close(&parent_tracer);
22291.59Skamil	msg_close(&parent_tracee);
22301.59Skamil}
22311.59Skamil
22321.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
22331.61SkreATF_TC(test);								\
22341.61SkreATF_TC_HEAD(test, tc)							\
22351.61Skre{									\
22361.61Skre	atf_tc_set_md_var(tc, "descr",					\
22371.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22381.94Skamil	    "the debuggee");						\
22391.61Skre}									\
22401.61Skre									\
22411.61SkreATF_TC_BODY(test, tc)							\
22421.61Skre{									\
22431.61Skre									\
22441.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
22451.59Skamil}
22461.59Skamil
22471.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
22481.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
22491.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
22501.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
22511.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22521.94Skamil
22531.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22541.94SkamilATF_TC(test);								\
22551.94SkamilATF_TC_HEAD(test, tc)							\
22561.94Skamil{									\
22571.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22581.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22591.94Skamil	    "the debuggee with masked signal");				\
22601.94Skamil}									\
22611.94Skamil									\
22621.94SkamilATF_TC_BODY(test, tc)							\
22631.94Skamil{									\
22641.94Skamil									\
22651.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22661.94Skamil}
22671.94Skamil
22681.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22691.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22701.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22711.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22721.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22731.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22741.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22751.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22761.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22771.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22781.94Skamil
22791.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22801.94SkamilATF_TC(test);								\
22811.94SkamilATF_TC_HEAD(test, tc)							\
22821.94Skamil{									\
22831.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22841.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22851.94Skamil	    "the debuggee with signal ignored");			\
22861.94Skamil}									\
22871.94Skamil									\
22881.94SkamilATF_TC_BODY(test, tc)							\
22891.94Skamil{									\
22901.94Skamil									\
22911.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22921.94Skamil}
22931.94Skamil
22941.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22951.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22961.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22971.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22981.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22991.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
23001.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
23011.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
23021.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
23031.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
23041.59Skamil#endif
23051.59Skamil
23061.59Skamil/// ----------------------------------------------------------------------------
23071.59Skamil
23081.59Skamil#if defined(TWAIT_HAVE_PID)
23091.59Skamilstatic void
23101.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
23111.67Skamil                                             bool stopped)
23121.1Skamil{
23131.51Skamil	/*
23141.51Skamil	 * notimeout - disable timeout in await zombie function
23151.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
23161.67Skamil	 * stopped - attach to a stopped process
23171.51Skamil	 */
23181.1Skamil
23191.1Skamil	struct msg_fds parent_tracee, parent_tracer;
23201.1Skamil	const int exitval_tracee = 5;
23211.1Skamil	const int exitval_tracer = 10;
23221.1Skamil	pid_t tracee, tracer, wpid;
23231.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
23241.1Skamil#if defined(TWAIT_HAVE_STATUS)
23251.1Skamil	int status;
23261.1Skamil#endif
23271.1Skamil
23281.67Skamil	/*
23291.67Skamil	 * Only a subset of options are supported.
23301.67Skamil	 */
23311.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
23321.67Skamil	            (!notimeout && unrelated && !stopped) ||
23331.67Skamil	            (notimeout && !unrelated && !stopped) ||
23341.67Skamil	            (!notimeout && unrelated && stopped));
23351.67Skamil
23361.13Schristos	DPRINTF("Spawn tracee\n");
23371.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
23381.1Skamil	tracee = atf_utils_fork();
23391.1Skamil	if (tracee == 0) {
23401.67Skamil		if (stopped) {
23411.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
23421.67Skamil			raise(SIGSTOP);
23431.67Skamil		}
23441.67Skamil
23451.1Skamil		// Wait for parent to let us exit
23461.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
23471.1Skamil		_exit(exitval_tracee);
23481.1Skamil	}
23491.1Skamil
23501.13Schristos	DPRINTF("Spawn debugger\n");
23511.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23521.1Skamil	tracer = atf_utils_fork();
23531.1Skamil	if (tracer == 0) {
23541.51Skamil		if(unrelated) {
23551.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23561.51Skamil			tracer = atf_utils_fork();
23571.51Skamil			if (tracer != 0)
23581.51Skamil				_exit(exitval_tracer);
23591.51Skamil		}
23601.51Skamil
23611.67Skamil		if (stopped) {
23621.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23631.67Skamil			await_stopped(tracee);
23641.67Skamil		}
23651.67Skamil
23661.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23671.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23681.1Skamil
23691.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23701.1Skamil		FORKEE_REQUIRE_SUCCESS(
23711.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23721.1Skamil
23731.1Skamil		forkee_status_stopped(status, SIGSTOP);
23741.1Skamil
23751.1Skamil		/* Resume tracee with PT_CONTINUE */
23761.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23771.1Skamil
23781.1Skamil		/* Inform parent that tracer has attached to tracee */
23791.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23801.1Skamil
23811.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23821.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23831.1Skamil
23841.1Skamil		/* Wait for tracee and assert that it exited */
23851.1Skamil		FORKEE_REQUIRE_SUCCESS(
23861.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23871.1Skamil
23881.1Skamil		forkee_status_exited(status, exitval_tracee);
23891.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23901.1Skamil
23911.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23921.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23931.51Skamil	}
23941.51Skamil
23951.51Skamil	if (unrelated) {
23961.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23971.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23981.51Skamil		TWAIT_REQUIRE_SUCCESS(
23991.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
24001.51Skamil
24011.51Skamil		validate_status_exited(status, exitval_tracer);
24021.51Skamil
24031.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
24041.51Skamil		    TWAIT_FNAME);
24051.51Skamil		TWAIT_REQUIRE_SUCCESS(
24061.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
24071.1Skamil	}
24081.1Skamil
24091.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
24101.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
24111.1Skamil
24121.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
24131.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
24141.1Skamil
24151.13Schristos	DPRINTF("Detect that tracee is zombie\n");
24161.51Skamil	if (notimeout)
24171.26Skamil		await_zombie_raw(tracee, 0);
24181.26Skamil	else
24191.26Skamil		await_zombie(tracee);
24201.1Skamil
24211.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
24221.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
24231.1Skamil	    TWAIT_FNAME);
24241.1Skamil	TWAIT_REQUIRE_SUCCESS(
24251.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
24261.1Skamil
24271.51Skamil	if (unrelated) {
24281.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
24291.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
24301.51Skamil	} else {
24311.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
24321.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
24331.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
24341.59Skamil			"%s()\n", TWAIT_FNAME);
24351.51Skamil
24361.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
24371.59Skamil			"tracee\n");
24381.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
24391.51Skamil		    tracer);
24401.1Skamil
24411.51Skamil		validate_status_exited(status, exitval_tracer);
24421.51Skamil	}
24431.1Skamil
24441.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
24451.1Skamil	    TWAIT_FNAME);
24461.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
24471.1Skamil
24481.1Skamil	validate_status_exited(status, exitval_tracee);
24491.1Skamil
24501.1Skamil	msg_close(&parent_tracer);
24511.1Skamil	msg_close(&parent_tracee);
24521.1Skamil}
24531.26Skamil
24541.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24551.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24561.51Skamil{
24571.51Skamil	atf_tc_set_md_var(tc, "descr",
24581.51Skamil	    "Assert that tracer sees process termination before the parent");
24591.51Skamil}
24601.51Skamil
24611.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24621.26Skamil{
24631.26Skamil
24641.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24651.26Skamil}
24661.26Skamil
24671.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24681.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24691.1Skamil{
24701.1Skamil	atf_tc_set_md_var(tc, "descr",
24711.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24721.51Skamil	    "process and no other error is reported");
24731.1Skamil}
24741.1Skamil
24751.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24761.1Skamil{
24771.51Skamil	time_t start, end;
24781.51Skamil	double diff;
24791.51Skamil	unsigned long N = 0;
24801.1Skamil
24811.51Skamil	/*
24821.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24831.51Skamil	 * This test body isn't specific to this race, however it's just good
24841.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24851.51Skamil	 */
24861.1Skamil
24871.51Skamil	start = time(NULL);
24881.51Skamil	while (true) {
24891.51Skamil		DPRINTF("Step: %lu\n", N);
24901.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24911.67Skamil		                                             false);
24921.51Skamil		end = time(NULL);
24931.51Skamil		diff = difftime(end, start);
24941.51Skamil		if (diff >= 5.0)
24951.51Skamil			break;
24961.51Skamil		++N;
24971.1Skamil	}
24981.51Skamil	DPRINTF("Iterations: %lu\n", N);
24991.51Skamil}
25001.1Skamil
25011.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
25021.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
25031.51Skamil{
25041.51Skamil	atf_tc_set_md_var(tc, "descr",
25051.51Skamil	    "Assert that tracer sees process termination before the parent");
25061.51Skamil}
25071.1Skamil
25081.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
25091.51Skamil{
25101.1Skamil
25111.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
25121.67Skamil}
25131.67Skamil
25141.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
25151.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
25161.67Skamil{
25171.67Skamil	atf_tc_set_md_var(tc, "descr",
25181.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
25191.67Skamil}
25201.67Skamil
25211.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
25221.67Skamil{
25231.67Skamil
25241.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
25251.1Skamil}
25261.1Skamil#endif
25271.1Skamil
25281.51Skamil/// ----------------------------------------------------------------------------
25291.51Skamil
25301.66Skamilstatic void
25311.66Skamilparent_attach_to_its_child(bool stopped)
25321.1Skamil{
25331.1Skamil	struct msg_fds parent_tracee;
25341.1Skamil	const int exitval_tracee = 5;
25351.1Skamil	pid_t tracee, wpid;
25361.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25371.1Skamil#if defined(TWAIT_HAVE_STATUS)
25381.1Skamil	int status;
25391.1Skamil#endif
25401.1Skamil
25411.13Schristos	DPRINTF("Spawn tracee\n");
25421.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25431.1Skamil	tracee = atf_utils_fork();
25441.1Skamil	if (tracee == 0) {
25451.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25461.13Schristos		DPRINTF("Parent should now attach to tracee\n");
25471.1Skamil
25481.66Skamil		if (stopped) {
25491.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
25501.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
25511.66Skamil		}
25521.66Skamil
25531.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25541.1Skamil		/* Wait for message from the parent */
25551.1Skamil		_exit(exitval_tracee);
25561.1Skamil	}
25571.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25581.57Skamil
25591.66Skamil	if (stopped) {
25601.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25611.66Skamil		await_stopped(tracee);
25621.66Skamil	}
25631.66Skamil
25641.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25661.1Skamil
25671.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25681.1Skamil	    TWAIT_FNAME);
25691.1Skamil	TWAIT_REQUIRE_SUCCESS(
25701.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25711.1Skamil
25721.1Skamil	validate_status_stopped(status, SIGSTOP);
25731.1Skamil
25741.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25761.1Skamil
25771.13Schristos	DPRINTF("Let the tracee exit now\n");
25781.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25791.1Skamil
25801.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25811.1Skamil	TWAIT_REQUIRE_SUCCESS(
25821.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25831.1Skamil
25841.1Skamil	validate_status_exited(status, exitval_tracee);
25851.1Skamil
25861.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25881.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25891.1Skamil
25901.1Skamil	msg_close(&parent_tracee);
25911.1Skamil}
25921.1Skamil
25931.66SkamilATF_TC(parent_attach_to_its_child);
25941.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25951.66Skamil{
25961.66Skamil	atf_tc_set_md_var(tc, "descr",
25971.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25981.66Skamil}
25991.66Skamil
26001.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
26011.66Skamil{
26021.66Skamil
26031.66Skamil	parent_attach_to_its_child(false);
26041.66Skamil}
26051.66Skamil
26061.66SkamilATF_TC(parent_attach_to_its_stopped_child);
26071.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
26081.66Skamil{
26091.66Skamil	atf_tc_set_md_var(tc, "descr",
26101.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
26111.66Skamil}
26121.66Skamil
26131.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
26141.66Skamil{
26151.66Skamil
26161.66Skamil	parent_attach_to_its_child(true);
26171.66Skamil}
26181.66Skamil
26191.51Skamil/// ----------------------------------------------------------------------------
26201.51Skamil
26211.65Skamilstatic void
26221.65Skamilchild_attach_to_its_parent(bool stopped)
26231.1Skamil{
26241.1Skamil	struct msg_fds parent_tracee;
26251.1Skamil	const int exitval_tracer = 5;
26261.1Skamil	pid_t tracer, wpid;
26271.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
26281.1Skamil#if defined(TWAIT_HAVE_STATUS)
26291.1Skamil	int status;
26301.1Skamil#endif
26311.1Skamil
26321.13Schristos	DPRINTF("Spawn tracer\n");
26331.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
26341.1Skamil	tracer = atf_utils_fork();
26351.1Skamil	if (tracer == 0) {
26361.1Skamil		/* Wait for message from the parent */
26371.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
26381.1Skamil
26391.65Skamil		if (stopped) {
26401.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
26411.65Skamil			        getppid());
26421.65Skamil			await_stopped(getppid());
26431.65Skamil		}
26441.65Skamil
26451.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
26461.1Skamil		    getppid());
26471.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
26481.1Skamil
26491.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
26501.1Skamil		    TWAIT_FNAME);
26511.1Skamil		FORKEE_REQUIRE_SUCCESS(
26521.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26531.1Skamil
26541.1Skamil		forkee_status_stopped(status, SIGSTOP);
26551.1Skamil
26561.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26571.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26581.1Skamil		    != -1);
26591.1Skamil
26601.1Skamil		/* Tell parent we are ready */
26611.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26621.1Skamil
26631.1Skamil		_exit(exitval_tracer);
26641.1Skamil	}
26651.1Skamil
26661.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26671.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26681.65Skamil
26691.65Skamil	if (stopped) {
26701.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26711.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26721.65Skamil	}
26731.65Skamil
26741.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26751.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26761.1Skamil
26771.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26781.1Skamil	TWAIT_REQUIRE_SUCCESS(
26791.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26801.1Skamil
26811.1Skamil	validate_status_exited(status, exitval_tracer);
26821.1Skamil
26831.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26851.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26861.1Skamil
26871.1Skamil	msg_close(&parent_tracee);
26881.1Skamil}
26891.1Skamil
26901.65SkamilATF_TC(child_attach_to_its_parent);
26911.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26921.65Skamil{
26931.65Skamil	atf_tc_set_md_var(tc, "descr",
26941.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26951.65Skamil}
26961.65Skamil
26971.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26981.65Skamil{
26991.65Skamil
27001.65Skamil	child_attach_to_its_parent(false);
27011.65Skamil}
27021.65Skamil
27031.65SkamilATF_TC(child_attach_to_its_stopped_parent);
27041.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
27051.65Skamil{
27061.65Skamil	atf_tc_set_md_var(tc, "descr",
27071.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
27081.65Skamil}
27091.65Skamil
27101.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
27111.65Skamil{
27121.65Skamil	/*
27131.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
27141.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
27151.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
27161.65Skamil	 *
27171.65Skamil	 * As a workaround spawn this test as a subprocess.
27181.65Skamil	 */
27191.65Skamil
27201.65Skamil	const int exitval = 15;
27211.65Skamil	pid_t child, wpid;
27221.65Skamil#if defined(TWAIT_HAVE_STATUS)
27231.65Skamil	int status;
27241.65Skamil#endif
27251.65Skamil
27261.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
27271.65Skamil	if (child == 0) {
27281.65Skamil		child_attach_to_its_parent(true);
27291.65Skamil		_exit(exitval);
27301.65Skamil	} else {
27311.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27321.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27331.65Skamil
27341.65Skamil		validate_status_exited(status, exitval);
27351.65Skamil
27361.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
27371.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27381.65Skamil	}
27391.65Skamil}
27401.65Skamil
27411.51Skamil/// ----------------------------------------------------------------------------
27421.51Skamil
27431.1Skamil#if defined(TWAIT_HAVE_PID)
27441.1Skamil
27451.51Skamilenum tracee_sees_its_original_parent_type {
27461.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
27471.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
27481.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
27491.51Skamil};
27501.51Skamil
27511.51Skamilstatic void
27521.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27531.1Skamil{
27541.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27551.1Skamil	const int exitval_tracee = 5;
27561.1Skamil	const int exitval_tracer = 10;
27571.1Skamil	pid_t parent, tracee, tracer, wpid;
27581.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27591.1Skamil#if defined(TWAIT_HAVE_STATUS)
27601.1Skamil	int status;
27611.1Skamil#endif
27621.51Skamil	/* sysctl(3) - kinfo_proc2 */
27631.51Skamil	int name[CTL_MAXNAME];
27641.51Skamil	struct kinfo_proc2 kp;
27651.51Skamil	size_t len = sizeof(kp);
27661.51Skamil	unsigned int namelen;
27671.51Skamil
27681.51Skamil	/* procfs - status  */
27691.51Skamil	FILE *fp;
27701.51Skamil	struct stat st;
27711.51Skamil	const char *fname = "/proc/curproc/status";
27721.51Skamil	char s_executable[MAXPATHLEN];
27731.51Skamil	int s_pid, s_ppid;
27741.51Skamil	int rv;
27751.51Skamil
27761.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27771.61Skre		SYSCALL_REQUIRE(
27781.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27791.61Skre		if (rv != 0)
27801.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27811.51Skamil	}
27821.1Skamil
27831.13Schristos	DPRINTF("Spawn tracee\n");
27841.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27851.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27861.1Skamil	tracee = atf_utils_fork();
27871.1Skamil	if (tracee == 0) {
27881.1Skamil		parent = getppid();
27891.1Skamil
27901.1Skamil		/* Emit message to the parent */
27911.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27921.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27931.1Skamil
27941.51Skamil		switch (type) {
27951.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27961.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27971.51Skamil			break;
27981.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27991.51Skamil			namelen = 0;
28001.51Skamil			name[namelen++] = CTL_KERN;
28011.51Skamil			name[namelen++] = KERN_PROC2;
28021.51Skamil			name[namelen++] = KERN_PROC_PID;
28031.51Skamil			name[namelen++] = getpid();
28041.51Skamil			name[namelen++] = len;
28051.51Skamil			name[namelen++] = 1;
28061.51Skamil
28071.61Skre			FORKEE_ASSERT_EQ(
28081.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
28091.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
28101.51Skamil			break;
28111.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
28121.51Skamil			/*
28131.51Skamil			 * Format:
28141.51Skamil			 *  EXECUTABLE PID PPID ...
28151.51Skamil			 */
28161.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
28171.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
28181.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
28191.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
28201.51Skamil			break;
28211.51Skamil		}
28221.1Skamil
28231.1Skamil		_exit(exitval_tracee);
28241.1Skamil	}
28251.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
28261.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
28271.1Skamil
28281.13Schristos	DPRINTF("Spawn debugger\n");
28291.1Skamil	tracer = atf_utils_fork();
28301.1Skamil	if (tracer == 0) {
28311.1Skamil		/* No IPC to communicate with the child */
28321.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
28331.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
28341.1Skamil
28351.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
28361.1Skamil		FORKEE_REQUIRE_SUCCESS(
28371.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28381.1Skamil
28391.1Skamil		forkee_status_stopped(status, SIGSTOP);
28401.1Skamil
28411.1Skamil		/* Resume tracee with PT_CONTINUE */
28421.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
28431.1Skamil
28441.1Skamil		/* Inform parent that tracer has attached to tracee */
28451.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
28461.1Skamil
28471.1Skamil		/* Wait for parent to tell use that tracee should have exited */
28481.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
28491.1Skamil
28501.1Skamil		/* Wait for tracee and assert that it exited */
28511.1Skamil		FORKEE_REQUIRE_SUCCESS(
28521.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28531.1Skamil
28541.1Skamil		forkee_status_exited(status, exitval_tracee);
28551.1Skamil
28561.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28571.1Skamil		_exit(exitval_tracer);
28581.1Skamil	}
28591.1Skamil
28601.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28611.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28621.1Skamil
28631.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28641.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28651.1Skamil
28661.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28671.1Skamil	await_zombie(tracee);
28681.1Skamil
28691.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28701.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28711.1Skamil	TWAIT_REQUIRE_SUCCESS(
28721.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28731.1Skamil
28741.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28751.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28761.1Skamil
28771.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28791.1Skamil	    tracer);
28801.1Skamil
28811.1Skamil	validate_status_exited(status, exitval_tracer);
28821.1Skamil
28831.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28841.1Skamil	    TWAIT_FNAME);
28851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28861.1Skamil	    tracee);
28871.1Skamil
28881.1Skamil	validate_status_exited(status, exitval_tracee);
28891.1Skamil
28901.1Skamil	msg_close(&parent_tracer);
28911.1Skamil	msg_close(&parent_tracee);
28921.1Skamil}
28931.1Skamil
28941.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28951.61SkreATF_TC(test);								\
28961.61SkreATF_TC_HEAD(test, tc)							\
28971.61Skre{									\
28981.61Skre	atf_tc_set_md_var(tc, "descr",					\
28991.61Skre	    "Assert that tracee sees its original parent when being traced " \
29001.61Skre	    "(check " descr ")");					\
29011.61Skre}									\
29021.61Skre									\
29031.61SkreATF_TC_BODY(test, tc)							\
29041.61Skre{									\
29051.61Skre									\
29061.61Skre	tracee_sees_its_original_parent(type);				\
29071.1Skamil}
29081.1Skamil
29091.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29101.51Skamil	tracee_sees_its_original_parent_getppid,
29111.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
29121.51Skamil	"getppid(2)");
29131.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29141.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
29151.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
29161.51Skamil	"sysctl(3) and kinfo_proc2");
29171.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29181.51Skamil	tracee_sees_its_original_parent_procfs_status,
29191.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
29201.51Skamil	"the status file in procfs");
29211.1Skamil#endif
29221.1Skamil
29231.51Skamil/// ----------------------------------------------------------------------------
29241.1Skamil
29251.53Skamilstatic void
29261.53Skamileventmask_preserved(int event)
29271.1Skamil{
29281.1Skamil	const int exitval = 5;
29291.1Skamil	const int sigval = SIGSTOP;
29301.1Skamil	pid_t child, wpid;
29311.1Skamil#if defined(TWAIT_HAVE_STATUS)
29321.1Skamil	int status;
29331.1Skamil#endif
29341.1Skamil	ptrace_event_t set_event, get_event;
29351.1Skamil	const int len = sizeof(ptrace_event_t);
29361.1Skamil
29371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29391.1Skamil	if (child == 0) {
29401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29421.1Skamil
29431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29451.1Skamil
29461.13Schristos		DPRINTF("Before exiting of the child process\n");
29471.1Skamil		_exit(exitval);
29481.1Skamil	}
29491.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29501.1Skamil
29511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29531.1Skamil
29541.1Skamil	validate_status_stopped(status, sigval);
29551.1Skamil
29561.53Skamil	set_event.pe_set_event = event;
29571.61Skre	SYSCALL_REQUIRE(
29581.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29591.61Skre	SYSCALL_REQUIRE(
29601.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29611.125Skamil	DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event,
29621.125Skamil	    get_event.pe_set_event);
29631.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29641.1Skamil
29651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29661.1Skamil	    "without signal to be sent\n");
29671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29681.1Skamil
29691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29711.1Skamil
29721.1Skamil	validate_status_exited(status, exitval);
29731.1Skamil
29741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29751.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29761.1Skamil}
29771.1Skamil
29781.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29791.61SkreATF_TC(test);								\
29801.61SkreATF_TC_HEAD(test, tc)							\
29811.61Skre{									\
29821.61Skre	atf_tc_set_md_var(tc, "descr",					\
29831.61Skre	    "Verify that eventmask " #event " is preserved");		\
29841.61Skre}									\
29851.61Skre									\
29861.61SkreATF_TC_BODY(test, tc)							\
29871.61Skre{									\
29881.61Skre									\
29891.61Skre	eventmask_preserved(event);					\
29901.1Skamil}
29911.1Skamil
29921.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29931.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29941.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29951.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29961.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29971.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29981.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN)
29991.1Skamil
30001.53Skamil/// ----------------------------------------------------------------------------
30011.1Skamil
30021.28Skamilstatic void
30031.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork,
30041.105Skamil    bool trackvforkdone)
30051.1Skamil{
30061.1Skamil	const int exitval = 5;
30071.125Skamil	const int exitval2 = 0; /* This matched exit status from /bin/echo */
30081.1Skamil	const int sigval = SIGSTOP;
30091.31Skamil	pid_t child, child2 = 0, wpid;
30101.1Skamil#if defined(TWAIT_HAVE_STATUS)
30111.1Skamil	int status;
30121.1Skamil#endif
30131.1Skamil	ptrace_state_t state;
30141.1Skamil	const int slen = sizeof(state);
30151.1Skamil	ptrace_event_t event;
30161.1Skamil	const int elen = sizeof(event);
30171.1Skamil
30181.124Skamil	char * const arg[] = { __UNCONST("/bin/echo"), NULL };
30191.124Skamil
30201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30221.1Skamil	if (child == 0) {
30231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30251.1Skamil
30261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30281.1Skamil
30291.125Skamil		if (strcmp(fn, "spawn") == 0) {
30301.124Skamil			FORKEE_ASSERT_EQ(posix_spawn(&child2,
30311.124Skamil			    arg[0], NULL, NULL, arg, NULL), 0);
30321.125Skamil		} else {
30331.125Skamil			if (strcmp(fn, "fork") == 0) {
30341.125Skamil				FORKEE_ASSERT((child2 = fork()) != -1);
30351.125Skamil			} else if (strcmp(fn, "vfork") == 0) {
30361.125Skamil				FORKEE_ASSERT((child2 = vfork()) != -1);
30371.125Skamil			}
30381.1Skamil
30391.124Skamil			if (child2 == 0)
30401.124Skamil				_exit(exitval2);
30411.124Skamil		}
30421.1Skamil		FORKEE_REQUIRE_SUCCESS
30431.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30441.1Skamil
30451.1Skamil		forkee_status_exited(status, exitval2);
30461.1Skamil
30471.13Schristos		DPRINTF("Before exiting of the child process\n");
30481.1Skamil		_exit(exitval);
30491.1Skamil	}
30501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30511.1Skamil
30521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30541.1Skamil
30551.1Skamil	validate_status_stopped(status, sigval);
30561.1Skamil
30571.125Skamil	DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n",
30581.125Skamil	    trackspawn ? "|PTRACE_POSIX_SPAWN" : "",
30591.61Skre	    trackfork ? "|PTRACE_FORK" : "",
30601.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
30611.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
30621.30Skamil	event.pe_set_event = 0;
30631.125Skamil	if (trackspawn)
30641.125Skamil		event.pe_set_event |= PTRACE_POSIX_SPAWN;
30651.30Skamil	if (trackfork)
30661.30Skamil		event.pe_set_event |= PTRACE_FORK;
30671.30Skamil	if (trackvfork)
30681.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30691.30Skamil	if (trackvforkdone)
30701.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30721.1Skamil
30731.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30741.1Skamil	    "without signal to be sent\n");
30751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30761.1Skamil
30771.29Skamil#if defined(TWAIT_HAVE_PID)
30781.125Skamil	if ((trackspawn && strcmp(fn, "spawn") == 0) ||
30791.125Skamil	    (trackfork && strcmp(fn, "fork") == 0) ||
30801.125Skamil	    (trackvfork && strcmp(fn, "vfork") == 0)) {
30811.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30821.61Skre		    child);
30831.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30841.61Skre		    child);
30851.1Skamil
30861.29Skamil		validate_status_stopped(status, SIGTRAP);
30871.1Skamil
30881.61Skre		SYSCALL_REQUIRE(
30891.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30901.125Skamil		if (trackspawn && strcmp(fn, "spawn") == 0) {
30911.125Skamil			ATF_REQUIRE_EQ(
30921.125Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
30931.125Skamil			       PTRACE_POSIX_SPAWN);
30941.125Skamil		}
30951.125Skamil		if (trackfork && strcmp(fn, "fork") == 0) {
30961.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30971.30Skamil			       PTRACE_FORK);
30981.30Skamil		}
30991.125Skamil		if (trackvfork && strcmp(fn, "vfork") == 0) {
31001.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
31011.30Skamil			       PTRACE_VFORK);
31021.30Skamil		}
31031.29Skamil
31041.29Skamil		child2 = state.pe_other_pid;
31051.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
31061.29Skamil
31071.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
31081.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
31091.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
31101.29Skamil		    child2);
31111.1Skamil
31121.29Skamil		validate_status_stopped(status, SIGTRAP);
31131.1Skamil
31141.61Skre		SYSCALL_REQUIRE(
31151.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
31161.125Skamil		if (trackspawn && strcmp(fn, "spawn") == 0) {
31171.125Skamil			ATF_REQUIRE_EQ(
31181.125Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
31191.125Skamil			       PTRACE_POSIX_SPAWN);
31201.125Skamil		}
31211.125Skamil		if (trackfork && strcmp(fn, "fork") == 0) {
31221.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
31231.30Skamil			       PTRACE_FORK);
31241.30Skamil		}
31251.125Skamil		if (trackvfork && strcmp(fn, "vfork") == 0) {
31261.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
31271.30Skamil			       PTRACE_VFORK);
31281.30Skamil		}
31291.30Skamil
31301.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
31311.29Skamil
31321.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
31331.29Skamil		    "and without signal to be sent\n");
31341.61Skre		SYSCALL_REQUIRE(
31351.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
31361.29Skamil
31371.29Skamil		DPRINTF("Before resuming the child process where it left off "
31381.61Skre		    "and without signal to be sent\n");
31391.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31401.30Skamil	}
31411.30Skamil#endif
31421.30Skamil
31431.125Skamil	if (trackvforkdone && strcmp(fn, "vfork") == 0) {
31441.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
31451.61Skre		    child);
31461.61Skre		TWAIT_REQUIRE_SUCCESS(
31471.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
31481.30Skamil
31491.30Skamil		validate_status_stopped(status, SIGTRAP);
31501.30Skamil
31511.61Skre		SYSCALL_REQUIRE(
31521.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
31531.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
31541.30Skamil
31551.30Skamil		child2 = state.pe_other_pid;
31561.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
31571.61Skre		    child2);
31581.30Skamil
31591.30Skamil		DPRINTF("Before resuming the child process where it left off "
31601.61Skre		    "and without signal to be sent\n");
31611.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31621.30Skamil	}
31631.29Skamil
31641.30Skamil#if defined(TWAIT_HAVE_PID)
31651.125Skamil	if ((trackspawn && strcmp(fn, "spawn") == 0) ||
31661.125Skamil	    (trackfork && strcmp(fn, "fork") == 0) ||
31671.125Skamil	    (trackvfork && strcmp(fn, "vfork") == 0)) {
31681.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
31691.61Skre		    "\n", TWAIT_FNAME);
31701.61Skre		TWAIT_REQUIRE_SUCCESS(
31711.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
31721.29Skamil
31731.29Skamil		validate_status_exited(status, exitval2);
31741.29Skamil
31751.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
31761.61Skre		    "process\n", TWAIT_FNAME);
31771.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
31781.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
31791.29Skamil	}
31801.29Skamil#endif
31811.1Skamil
31821.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31831.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31851.1Skamil
31861.1Skamil	validate_status_stopped(status, SIGCHLD);
31871.1Skamil
31881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31891.1Skamil	    "without signal to be sent\n");
31901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31911.1Skamil
31921.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31931.1Skamil	    TWAIT_FNAME);
31941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31951.1Skamil
31961.1Skamil	validate_status_exited(status, exitval);
31971.1Skamil
31981.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31991.1Skamil	    TWAIT_FNAME);
32001.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32011.1Skamil}
32021.28Skamil
32031.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone)		\
32041.61SkreATF_TC(name);								\
32051.61SkreATF_TC_HEAD(name, tc)							\
32061.61Skre{									\
32071.125Skamil	atf_tc_set_md_var(tc, "descr", "Verify " fun "() "		\
32081.125Skamil	    "called with 0%s%s%s%s in EVENT_MASK",			\
32091.126Skamil	    tspawn ? "|PTRACE_POSIX_SPAWN" : "",			\
32101.105Skamil	    tfork ? "|PTRACE_FORK" : "",				\
32111.105Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
32121.105Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
32131.61Skre}									\
32141.61Skre									\
32151.61SkreATF_TC_BODY(name, tc)							\
32161.61Skre{									\
32171.61Skre									\
32181.125Skamil	fork_body(fun, tspawn, tfork, tvfork, tvforkdone);		\
32191.32Skamil}
32201.32Skamil
32211.125SkamilFORK_TEST(fork1, "fork", false, false, false, false)
32221.31Skamil#if defined(TWAIT_HAVE_PID)
32231.125SkamilFORK_TEST(fork2, "fork", false, true, false, false)
32241.125SkamilFORK_TEST(fork3, "fork", false, false, true, false)
32251.125SkamilFORK_TEST(fork4, "fork", false, true, true, false)
32261.31Skamil#endif
32271.125SkamilFORK_TEST(fork5, "fork", false, false, false, true)
32281.31Skamil#if defined(TWAIT_HAVE_PID)
32291.125SkamilFORK_TEST(fork6, "fork", false, true, false, true)
32301.125SkamilFORK_TEST(fork7, "fork", false, false, true, true)
32311.125SkamilFORK_TEST(fork8, "fork", false, true, true, true)
32321.125Skamil#endif
32331.125SkamilFORK_TEST(fork9, "fork", true, false, false, false)
32341.125Skamil#if defined(TWAIT_HAVE_PID)
32351.125SkamilFORK_TEST(fork10, "fork", true, true, false, false)
32361.125SkamilFORK_TEST(fork11, "fork", true, false, true, false)
32371.125SkamilFORK_TEST(fork12, "fork", true, true, true, false)
32381.125Skamil#endif
32391.125SkamilFORK_TEST(fork13, "fork", true, false, false, true)
32401.125Skamil#if defined(TWAIT_HAVE_PID)
32411.125SkamilFORK_TEST(fork14, "fork", true, true, false, true)
32421.125SkamilFORK_TEST(fork15, "fork", true, false, true, true)
32431.125SkamilFORK_TEST(fork16, "fork", true, true, true, true)
32441.31Skamil#endif
32451.1Skamil
32461.110Skamil#if TEST_VFORK_ENABLED
32471.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false)
32481.31Skamil#if defined(TWAIT_HAVE_PID)
32491.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false)
32501.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false)
32511.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false)
32521.31Skamil#endif
32531.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true)
32541.31Skamil#if defined(TWAIT_HAVE_PID)
32551.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true)
32561.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true)
32571.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true)
32581.31Skamil#endif
32591.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false)
32601.125Skamil#if defined(TWAIT_HAVE_PID)
32611.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false)
32621.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false)
32631.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false)
32641.110Skamil#endif
32651.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true)
32661.124Skamil#if defined(TWAIT_HAVE_PID)
32671.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true)
32681.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true)
32691.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true)
32701.124Skamil#endif
32711.125Skamil#endif
32721.125Skamil
32731.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false)
32741.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false)
32751.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false)
32761.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false)
32771.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true)
32781.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true)
32791.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true)
32801.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true)
32811.124Skamil#if defined(TWAIT_HAVE_PID)
32821.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false)
32831.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false)
32841.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false)
32851.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false)
32861.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true)
32871.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true)
32881.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true)
32891.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true)
32901.124Skamil#endif
32911.124Skamil
32921.54Skamil/// ----------------------------------------------------------------------------
32931.31Skamil
32941.116Skamil#if defined(TWAIT_HAVE_PID)
32951.116Skamilstatic void
32961.126Skamilfork_detach_forker_body(const char *fn, bool kill_process)
32971.116Skamil{
32981.116Skamil	const int exitval = 5;
32991.126Skamil	const int exitval2 = 0; /* Matches exit value from /bin/echo */
33001.116Skamil	const int sigval = SIGSTOP;
33011.116Skamil	pid_t child, child2 = 0, wpid;
33021.116Skamil#if defined(TWAIT_HAVE_STATUS)
33031.116Skamil	int status;
33041.116Skamil#endif
33051.116Skamil	ptrace_state_t state;
33061.116Skamil	const int slen = sizeof(state);
33071.116Skamil	ptrace_event_t event;
33081.116Skamil	const int elen = sizeof(event);
33091.116Skamil
33101.116Skamil	int op;
33111.116Skamil
33121.126Skamil	char * const arg[] = { __UNCONST("/bin/echo"), NULL };
33131.116Skamil
33141.116Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
33151.116Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
33161.116Skamil	if (child == 0) {
33171.116Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33181.116Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33191.116Skamil
33201.116Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33211.116Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33221.116Skamil
33231.126Skamil		if (strcmp(fn, "spawn") == 0) {
33241.126Skamil			FORKEE_ASSERT_EQ(posix_spawn(&child2,
33251.126Skamil			    arg[0], NULL, NULL, arg, NULL), 0);
33261.126Skamil		} else  {
33271.126Skamil			if (strcmp(fn, "fork") == 0) {
33281.126Skamil				FORKEE_ASSERT((child2 = fork()) != -1);
33291.126Skamil			} else {
33301.126Skamil				FORKEE_ASSERT((child2 = vfork()) != -1);
33311.126Skamil			}
33321.116Skamil
33331.126Skamil			if (child2 == 0)
33341.126Skamil				_exit(exitval2);
33351.126Skamil		}
33361.116Skamil
33371.116Skamil		FORKEE_REQUIRE_SUCCESS
33381.116Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
33391.116Skamil
33401.116Skamil		forkee_status_exited(status, exitval2);
33411.116Skamil
33421.116Skamil		DPRINTF("Before exiting of the child process\n");
33431.116Skamil		_exit(exitval);
33441.116Skamil	}
33451.116Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33461.116Skamil
33471.116Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33481.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33491.116Skamil
33501.116Skamil	validate_status_stopped(status, sigval);
33511.116Skamil
33521.116Skamil	DPRINTF("Set EVENT_MASK for the child %d\n", child);
33531.126Skamil	event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK
33541.126Skamil		| PTRACE_VFORK_DONE;
33551.116Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
33561.116Skamil
33571.116Skamil	DPRINTF("Before resuming the child process where it left off and "
33581.116Skamil	    "without signal to be sent\n");
33591.116Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33601.116Skamil
33611.116Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
33621.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33631.116Skamil
33641.116Skamil	validate_status_stopped(status, SIGTRAP);
33651.116Skamil
33661.116Skamil	SYSCALL_REQUIRE(
33671.116Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
33681.126Skamil
33691.126Skamil	if (strcmp(fn, "spawn") == 0)
33701.126Skamil		op = PTRACE_POSIX_SPAWN;
33711.126Skamil	else if (strcmp(fn, "fork") == 0)
33721.126Skamil		op = PTRACE_FORK;
33731.126Skamil	else
33741.126Skamil		op = PTRACE_VFORK;
33751.126Skamil
33761.116Skamil	ATF_REQUIRE_EQ(state.pe_report_event & op, op);
33771.116Skamil
33781.116Skamil	child2 = state.pe_other_pid;
33791.116Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
33801.116Skamil
33811.126Skamil	if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 ||
33821.126Skamil	    strcmp(fn, "vfork") == 0)
33831.116Skamil		op = kill_process ? PT_KILL : PT_DETACH;
33841.116Skamil	else
33851.116Skamil		op = PT_CONTINUE;
33861.116Skamil	SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1);
33871.116Skamil
33881.116Skamil	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
33891.116Skamil	    TWAIT_FNAME, child2, child);
33901.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
33911.116Skamil
33921.116Skamil	validate_status_stopped(status, SIGTRAP);
33931.116Skamil
33941.116Skamil	SYSCALL_REQUIRE(
33951.116Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
33961.126Skamil	if (strcmp(fn, "spawn") == 0)
33971.126Skamil		op = PTRACE_POSIX_SPAWN;
33981.126Skamil	else if (strcmp(fn, "fork") == 0)
33991.126Skamil		op = PTRACE_FORK;
34001.126Skamil	else
34011.126Skamil		op = PTRACE_VFORK;
34021.126Skamil
34031.116Skamil	ATF_REQUIRE_EQ(state.pe_report_event & op, op);
34041.116Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
34051.116Skamil
34061.116Skamil	DPRINTF("Before resuming the forkee process where it left off "
34071.116Skamil	    "and without signal to be sent\n");
34081.116Skamil 	SYSCALL_REQUIRE(
34091.116Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
34101.116Skamil
34111.126Skamil	if (strcmp(fn, "vforkdone") == 0) {
34121.116Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
34131.116Skamil		    child);
34141.116Skamil		TWAIT_REQUIRE_SUCCESS(
34151.116Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
34161.116Skamil
34171.116Skamil		validate_status_stopped(status, SIGTRAP);
34181.116Skamil
34191.116Skamil		SYSCALL_REQUIRE(
34201.116Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
34211.116Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
34221.116Skamil
34231.116Skamil		child2 = state.pe_other_pid;
34241.116Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
34251.116Skamil		    child2);
34261.116Skamil
34271.116Skamil		op = kill_process ? PT_KILL : PT_DETACH;
34281.116Skamil		DPRINTF("Before resuming the child process where it left off "
34291.116Skamil		    "and without signal to be sent\n");
34301.116Skamil		SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1);
34311.116Skamil	}
34321.116Skamil
34331.116Skamil	DPRINTF("Before calling %s() for the forkee - expected exited\n",
34341.116Skamil	    TWAIT_FNAME);
34351.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
34361.116Skamil
34371.116Skamil	validate_status_exited(status, exitval2);
34381.116Skamil
34391.116Skamil	DPRINTF("Before calling %s() for the forkee - expected no process\n",
34401.116Skamil	    TWAIT_FNAME);
34411.116Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0));
34421.116Skamil
34431.116Skamil	DPRINTF("Before calling %s() for the forkee - expected exited\n",
34441.116Skamil	    TWAIT_FNAME);
34451.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34461.116Skamil
34471.116Skamil	if (kill_process) {
34481.116Skamil		validate_status_signaled(status, SIGKILL, 0);
34491.116Skamil	} else {
34501.116Skamil		validate_status_exited(status, exitval);
34511.116Skamil	}
34521.116Skamil
34531.116Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
34541.116Skamil	    TWAIT_FNAME);
34551.116Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34561.116Skamil}
34571.116Skamil
34581.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess)				\
34591.116SkamilATF_TC(name);								\
34601.116SkamilATF_TC_HEAD(name, tc)							\
34611.116Skamil{									\
34621.126Skamil	atf_tc_set_md_var(tc, "descr", "Verify %s " event,		\
34631.126Skamil	    kprocess ? "killed" : "detached");				\
34641.116Skamil}									\
34651.116Skamil									\
34661.116SkamilATF_TC_BODY(name, tc)							\
34671.116Skamil{									\
34681.116Skamil									\
34691.126Skamil	fork_detach_forker_body(event, kprocess);			\
34701.116Skamil}
34711.116Skamil
34721.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false)
34731.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false)
34741.116Skamil#if TEST_VFORK_ENABLED
34751.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false)
34761.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false)
34771.116Skamil#endif
34781.126Skamil
34791.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true)
34801.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true)
34811.116Skamil#if TEST_VFORK_ENABLED
34821.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true)
34831.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true)
34841.116Skamil#endif
34851.116Skamil#endif
34861.116Skamil
34871.116Skamil/// ----------------------------------------------------------------------------
34881.116Skamil
34891.110Skamil#if TEST_VFORK_ENABLED
34901.108Skamilstatic void
34911.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void))
34921.108Skamil{
34931.108Skamil	const int exitval = 5;
34941.108Skamil	const int exitval2 = 15;
34951.108Skamil	pid_t child, child2 = 0, wpid;
34961.108Skamil#if defined(TWAIT_HAVE_STATUS)
34971.108Skamil	int status;
34981.108Skamil#endif
34991.108Skamil
35001.108Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
35011.108Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
35021.108Skamil	if (child == 0) {
35031.108Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35041.108Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35051.108Skamil
35061.108Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
35071.108Skamil
35081.108Skamil		if (child2 == 0)
35091.108Skamil			_exit(exitval2);
35101.108Skamil
35111.108Skamil		FORKEE_REQUIRE_SUCCESS
35121.108Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
35131.108Skamil
35141.108Skamil		forkee_status_exited(status, exitval2);
35151.108Skamil
35161.108Skamil		DPRINTF("Before exiting of the child process\n");
35171.108Skamil		_exit(exitval);
35181.108Skamil	}
35191.108Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35201.108Skamil
35211.108Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
35221.108Skamil	    TWAIT_FNAME);
35231.108Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35241.108Skamil
35251.108Skamil	validate_status_exited(status, exitval);
35261.108Skamil
35271.108Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
35281.108Skamil	    TWAIT_FNAME);
35291.108Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35301.108Skamil}
35311.108Skamil
35321.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun)				\
35331.108SkamilATF_TC(name);								\
35341.108SkamilATF_TC_HEAD(name, tc)							\
35351.108Skamil{									\
35361.108Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
35371.108Skamil	    "called from vfork(2)ed child");				\
35381.108Skamil}									\
35391.108Skamil									\
35401.108SkamilATF_TC_BODY(name, tc)							\
35411.108Skamil{									\
35421.108Skamil									\
35431.108Skamil	traceme_vfork_fork_body(fun);					\
35441.108Skamil}
35451.108Skamil
35461.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork)
35471.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork)
35481.110Skamil#endif
35491.108Skamil
35501.108Skamil/// ----------------------------------------------------------------------------
35511.108Skamil
35521.54Skamilenum bytes_transfer_type {
35531.54Skamil	BYTES_TRANSFER_DATA,
35541.54Skamil	BYTES_TRANSFER_DATAIO,
35551.54Skamil	BYTES_TRANSFER_TEXT,
35561.54Skamil	BYTES_TRANSFER_TEXTIO,
35571.54Skamil	BYTES_TRANSFER_AUXV
35581.54Skamil};
35591.31Skamil
35601.54Skamilstatic int __used
35611.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
35621.54Skamil{
35631.54Skamil	int e, f, g, h;
35641.1Skamil
35651.54Skamil	a *= 4;
35661.54Skamil	b += 3;
35671.54Skamil	c -= 2;
35681.54Skamil	d /= 1;
35691.1Skamil
35701.54Skamil	e = strtol("10", NULL, 10);
35711.54Skamil	f = strtol("20", NULL, 10);
35721.54Skamil	g = strtol("30", NULL, 10);
35731.54Skamil	h = strtol("40", NULL, 10);
35741.1Skamil
35751.54Skamil	return (a + b * c - d) + (e * f - g / h);
35761.1Skamil}
35771.1Skamil
35781.54Skamilstatic void
35791.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
35801.1Skamil{
35811.1Skamil	const int exitval = 5;
35821.1Skamil	const int sigval = SIGSTOP;
35831.1Skamil	pid_t child, wpid;
35841.54Skamil	bool skip = false;
35851.1Skamil
35861.54Skamil	int lookup_me = 0;
35871.54Skamil	uint8_t lookup_me8 = 0;
35881.54Skamil	uint16_t lookup_me16 = 0;
35891.54Skamil	uint32_t lookup_me32 = 0;
35901.54Skamil	uint64_t lookup_me64 = 0;
35911.1Skamil
35921.54Skamil	int magic = 0x13579246;
35931.54Skamil	uint8_t magic8 = 0xab;
35941.54Skamil	uint16_t magic16 = 0x1234;
35951.54Skamil	uint32_t magic32 = 0x98765432;
35961.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
35971.1Skamil
35981.54Skamil	struct ptrace_io_desc io;
35991.1Skamil#if defined(TWAIT_HAVE_STATUS)
36001.1Skamil	int status;
36011.1Skamil#endif
36021.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
36031.60Skre	AuxInfo ai[513], *aip;
36041.55Schristos
36051.55Schristos	ATF_REQUIRE(size < sizeof(ai));
36061.1Skamil
36071.54Skamil	/* Prepare variables for .TEXT transfers */
36081.54Skamil	switch (type) {
36091.54Skamil	case BYTES_TRANSFER_TEXT:
36101.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
36111.54Skamil		break;
36121.54Skamil	case BYTES_TRANSFER_TEXTIO:
36131.54Skamil		switch (size) {
36141.54Skamil		case 8:
36151.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
36161.54Skamil			break;
36171.54Skamil		case 16:
36181.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
36191.54Skamil			break;
36201.54Skamil		case 32:
36211.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
36221.54Skamil			break;
36231.54Skamil		case 64:
36241.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
36251.54Skamil			break;
36261.54Skamil		}
36271.54Skamil		break;
36281.54Skamil	default:
36291.54Skamil		break;
36301.54Skamil	}
36311.1Skamil
36321.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
36331.54Skamil	switch (type) {
36341.54Skamil	case BYTES_TRANSFER_TEXTIO:
36351.54Skamil	case BYTES_TRANSFER_DATAIO:
36361.54Skamil		io.piod_op = operation;
36371.54Skamil		switch (size) {
36381.54Skamil		case 8:
36391.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36401.54Skamil			               (void *)bytes_transfer_dummy :
36411.54Skamil			               &lookup_me8;
36421.54Skamil			io.piod_addr = &lookup_me8;
36431.54Skamil			io.piod_len = sizeof(lookup_me8);
36441.54Skamil			break;
36451.54Skamil		case 16:
36461.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36471.54Skamil			               (void *)bytes_transfer_dummy :
36481.54Skamil			               &lookup_me16;
36491.54Skamil			io.piod_addr = &lookup_me16;
36501.54Skamil			io.piod_len = sizeof(lookup_me16);
36511.54Skamil			break;
36521.54Skamil		case 32:
36531.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36541.54Skamil			               (void *)bytes_transfer_dummy :
36551.54Skamil			               &lookup_me32;
36561.54Skamil			io.piod_addr = &lookup_me32;
36571.54Skamil			io.piod_len = sizeof(lookup_me32);
36581.54Skamil			break;
36591.54Skamil		case 64:
36601.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
36611.54Skamil			               (void *)bytes_transfer_dummy :
36621.54Skamil			               &lookup_me64;
36631.54Skamil			io.piod_addr = &lookup_me64;
36641.54Skamil			io.piod_len = sizeof(lookup_me64);
36651.54Skamil			break;
36661.54Skamil		default:
36671.54Skamil			break;
36681.54Skamil		}
36691.54Skamil		break;
36701.54Skamil	case BYTES_TRANSFER_AUXV:
36711.54Skamil		io.piod_op = operation;
36721.54Skamil		io.piod_offs = 0;
36731.54Skamil		io.piod_addr = ai;
36741.54Skamil		io.piod_len = size;
36751.54Skamil		break;
36761.54Skamil	default:
36771.54Skamil		break;
36781.1Skamil	}
36791.1Skamil
36801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36821.1Skamil	if (child == 0) {
36831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36851.1Skamil
36861.54Skamil		switch (type) {
36871.54Skamil		case BYTES_TRANSFER_DATA:
36881.54Skamil			switch (operation) {
36891.54Skamil			case PT_READ_D:
36901.54Skamil			case PT_READ_I:
36911.54Skamil				lookup_me = magic;
36921.54Skamil				break;
36931.54Skamil			default:
36941.54Skamil				break;
36951.54Skamil			}
36961.54Skamil			break;
36971.54Skamil		case BYTES_TRANSFER_DATAIO:
36981.54Skamil			switch (operation) {
36991.54Skamil			case PIOD_READ_D:
37001.54Skamil			case PIOD_READ_I:
37011.54Skamil				switch (size) {
37021.54Skamil				case 8:
37031.54Skamil					lookup_me8 = magic8;
37041.54Skamil					break;
37051.54Skamil				case 16:
37061.54Skamil					lookup_me16 = magic16;
37071.54Skamil					break;
37081.54Skamil				case 32:
37091.54Skamil					lookup_me32 = magic32;
37101.54Skamil					break;
37111.54Skamil				case 64:
37121.54Skamil					lookup_me64 = magic64;
37131.54Skamil					break;
37141.54Skamil				default:
37151.54Skamil					break;
37161.54Skamil				}
37171.54Skamil				break;
37181.54Skamil			default:
37191.54Skamil				break;
37201.54Skamil			}
37211.54Skamil		default:
37221.54Skamil			break;
37231.54Skamil		}
37241.54Skamil
37251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37271.1Skamil
37281.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
37291.54Skamil		switch (type) {
37301.54Skamil		case BYTES_TRANSFER_DATA:
37311.54Skamil			switch (operation) {
37321.54Skamil			case PT_WRITE_D:
37331.54Skamil			case PT_WRITE_I:
37341.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
37351.54Skamil				break;
37361.54Skamil			default:
37371.54Skamil				break;
37381.54Skamil			}
37391.54Skamil			break;
37401.54Skamil		case BYTES_TRANSFER_DATAIO:
37411.54Skamil			switch (operation) {
37421.54Skamil			case PIOD_WRITE_D:
37431.54Skamil			case PIOD_WRITE_I:
37441.54Skamil				switch (size) {
37451.54Skamil				case 8:
37461.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
37471.54Skamil					break;
37481.54Skamil				case 16:
37491.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
37501.54Skamil					break;
37511.54Skamil				case 32:
37521.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
37531.54Skamil					break;
37541.54Skamil				case 64:
37551.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
37561.54Skamil					break;
37571.54Skamil				default:
37581.54Skamil					break;
37591.54Skamil				}
37601.54Skamil				break;
37611.54Skamil			default:
37621.54Skamil				break;
37631.54Skamil			}
37641.54Skamil			break;
37651.54Skamil		case BYTES_TRANSFER_TEXT:
37661.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
37671.54Skamil			                     sizeof(magic)) == 0);
37681.54Skamil			break;
37691.54Skamil		case BYTES_TRANSFER_TEXTIO:
37701.54Skamil			switch (size) {
37711.54Skamil			case 8:
37721.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
37731.54Skamil				                     bytes_transfer_dummy,
37741.54Skamil				                     sizeof(magic8)) == 0);
37751.54Skamil				break;
37761.54Skamil			case 16:
37771.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
37781.54Skamil				                     bytes_transfer_dummy,
37791.54Skamil				                     sizeof(magic16)) == 0);
37801.54Skamil				break;
37811.54Skamil			case 32:
37821.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
37831.54Skamil				                     bytes_transfer_dummy,
37841.54Skamil				                     sizeof(magic32)) == 0);
37851.54Skamil				break;
37861.54Skamil			case 64:
37871.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
37881.54Skamil				                     bytes_transfer_dummy,
37891.54Skamil				                     sizeof(magic64)) == 0);
37901.54Skamil				break;
37911.54Skamil			}
37921.54Skamil			break;
37931.54Skamil		default:
37941.54Skamil			break;
37951.54Skamil		}
37961.54Skamil
37971.13Schristos		DPRINTF("Before exiting of the child process\n");
37981.1Skamil		_exit(exitval);
37991.1Skamil	}
38001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38011.1Skamil
38021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38041.1Skamil
38051.1Skamil	validate_status_stopped(status, sigval);
38061.1Skamil
38071.54Skamil	/* Check PaX MPROTECT */
38081.54Skamil	if (!can_we_write_to_text(child)) {
38091.54Skamil		switch (type) {
38101.54Skamil		case BYTES_TRANSFER_TEXTIO:
38111.54Skamil			switch (operation) {
38121.54Skamil			case PIOD_WRITE_D:
38131.54Skamil			case PIOD_WRITE_I:
38141.54Skamil				skip = true;
38151.54Skamil				break;
38161.54Skamil			default:
38171.54Skamil				break;
38181.54Skamil			}
38191.54Skamil			break;
38201.54Skamil		case BYTES_TRANSFER_TEXT:
38211.54Skamil			switch (operation) {
38221.54Skamil			case PT_WRITE_D:
38231.54Skamil			case PT_WRITE_I:
38241.54Skamil				skip = true;
38251.54Skamil				break;
38261.54Skamil			default:
38271.54Skamil				break;
38281.54Skamil			}
38291.54Skamil			break;
38301.54Skamil		default:
38311.54Skamil			break;
38321.54Skamil		}
38331.54Skamil	}
38341.1Skamil
38351.54Skamil	/* Bailout cleanly killing the child process */
38361.54Skamil	if (skip) {
38371.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
38381.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38391.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
38401.54Skamil		                      child);
38411.1Skamil
38421.54Skamil		validate_status_signaled(status, SIGKILL, 0);
38431.1Skamil
38441.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
38451.54Skamil	}
38461.1Skamil
38471.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
38481.54Skamil	       "parent=%d\n", child, getpid());
38491.1Skamil
38501.54Skamil	switch (type) {
38511.54Skamil	case BYTES_TRANSFER_TEXTIO:
38521.54Skamil	case BYTES_TRANSFER_DATAIO:
38531.54Skamil	case BYTES_TRANSFER_AUXV:
38541.54Skamil		switch (operation) {
38551.54Skamil		case PIOD_WRITE_D:
38561.54Skamil		case PIOD_WRITE_I:
38571.54Skamil			switch (size) {
38581.54Skamil			case 8:
38591.54Skamil				lookup_me8 = magic8;
38601.54Skamil				break;
38611.54Skamil			case 16:
38621.54Skamil				lookup_me16 = magic16;
38631.54Skamil				break;
38641.54Skamil			case 32:
38651.54Skamil				lookup_me32 = magic32;
38661.54Skamil				break;
38671.54Skamil			case 64:
38681.54Skamil				lookup_me64 = magic64;
38691.54Skamil				break;
38701.54Skamil			default:
38711.54Skamil				break;
38721.54Skamil			}
38731.54Skamil			break;
38741.54Skamil		default:
38751.54Skamil			break;
38761.54Skamil		}
38771.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
38781.54Skamil		switch (operation) {
38791.54Skamil		case PIOD_READ_D:
38801.54Skamil		case PIOD_READ_I:
38811.54Skamil			switch (size) {
38821.54Skamil			case 8:
38831.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
38841.54Skamil				break;
38851.54Skamil			case 16:
38861.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
38871.54Skamil				break;
38881.54Skamil			case 32:
38891.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
38901.54Skamil				break;
38911.54Skamil			case 64:
38921.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
38931.54Skamil				break;
38941.54Skamil			default:
38951.54Skamil				break;
38961.54Skamil			}
38971.54Skamil			break;
38981.54Skamil		case PIOD_READ_AUXV:
38991.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
39001.54Skamil			        io.piod_len);
39011.54Skamil			ATF_REQUIRE(io.piod_len > 0);
39021.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
39031.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
39041.54Skamil				    (long long int)aip->a_type,
39051.54Skamil				    (long long int)aip->a_v);
39061.54Skamil			break;
39071.54Skamil		default:
39081.54Skamil			break;
39091.54Skamil		}
39101.54Skamil		break;
39111.54Skamil	case BYTES_TRANSFER_TEXT:
39121.54Skamil		switch (operation) {
39131.54Skamil		case PT_READ_D:
39141.54Skamil		case PT_READ_I:
39151.54Skamil			errno = 0;
39161.54Skamil			lookup_me = ptrace(operation, child,
39171.54Skamil			                   bytes_transfer_dummy, 0);
39181.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
39191.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
39201.54Skamil			break;
39211.54Skamil		case PT_WRITE_D:
39221.54Skamil		case PT_WRITE_I:
39231.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
39241.54Skamil			                       bytes_transfer_dummy, magic)
39251.54Skamil			                != -1);
39261.54Skamil			break;
39271.54Skamil		default:
39281.54Skamil			break;
39291.54Skamil		}
39301.54Skamil		break;
39311.54Skamil	case BYTES_TRANSFER_DATA:
39321.54Skamil		switch (operation) {
39331.54Skamil		case PT_READ_D:
39341.54Skamil		case PT_READ_I:
39351.54Skamil			errno = 0;
39361.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
39371.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
39381.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
39391.54Skamil			break;
39401.54Skamil		case PT_WRITE_D:
39411.54Skamil		case PT_WRITE_I:
39421.54Skamil			lookup_me = magic;
39431.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
39441.54Skamil			                       magic) != -1);
39451.54Skamil			break;
39461.54Skamil		default:
39471.54Skamil			break;
39481.54Skamil		}
39491.54Skamil		break;
39501.54Skamil	default:
39511.54Skamil		break;
39521.54Skamil	}
39531.1Skamil
39541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39551.1Skamil	    "without signal to be sent\n");
39561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39571.1Skamil
39581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39601.1Skamil
39611.1Skamil	validate_status_exited(status, exitval);
39621.1Skamil
39631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39651.1Skamil}
39661.1Skamil
39671.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
39681.61SkreATF_TC(test);								\
39691.61SkreATF_TC_HEAD(test, tc)							\
39701.61Skre{									\
39711.61Skre	atf_tc_set_md_var(tc, "descr",					\
39721.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
39731.61Skre	    " of type " #type);						\
39741.61Skre}									\
39751.61Skre									\
39761.61SkreATF_TC_BODY(test, tc)							\
39771.61Skre{									\
39781.61Skre									\
39791.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
39801.1Skamil}
39811.1Skamil
39821.54Skamil// DATA
39831.1Skamil
39841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
39851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
39861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
39871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
39881.54Skamil
39891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
39901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
39911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
39921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
39931.54Skamil
39941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
39951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
39961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
39971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
39981.54Skamil
39991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
40001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
40011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
40021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
40031.54Skamil
40041.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
40051.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
40061.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
40071.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
40081.54Skamil
40091.54Skamil// TEXT
40101.54Skamil
40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
40131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
40141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
40151.54Skamil
40161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
40171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
40181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
40191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
40201.54Skamil
40211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
40221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
40231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
40241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
40251.54Skamil
40261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
40271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
40281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
40291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
40301.54Skamil
40311.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
40321.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
40331.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
40341.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
40351.1Skamil
40361.54Skamil// AUXV
40371.1Skamil
40381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
40391.1Skamil
40401.54Skamil/// ----------------------------------------------------------------------------
40411.1Skamil
40421.101Skamilstatic void
40431.101Skamilbytes_transfer_alignment(const char *operation)
40441.101Skamil{
40451.101Skamil	const int exitval = 5;
40461.101Skamil	const int sigval = SIGSTOP;
40471.101Skamil	pid_t child, wpid;
40481.101Skamil#if defined(TWAIT_HAVE_STATUS)
40491.101Skamil	int status;
40501.101Skamil#endif
40511.101Skamil	char *buffer;
40521.101Skamil	int vector;
40531.101Skamil	size_t len;
40541.101Skamil	size_t i;
40551.101Skamil	int op;
40561.101Skamil
40571.101Skamil	struct ptrace_io_desc io;
40581.101Skamil	struct ptrace_siginfo info;
40591.101Skamil
40601.101Skamil	memset(&io, 0, sizeof(io));
40611.101Skamil	memset(&info, 0, sizeof(info));
40621.101Skamil
40631.101Skamil	/* Testing misaligned byte transfer crossing page boundaries */
40641.101Skamil	len = sysconf(_SC_PAGESIZE) * 2;
40651.101Skamil	buffer = malloc(len);
40661.101Skamil	ATF_REQUIRE(buffer != NULL);
40671.101Skamil
40681.101Skamil	/* Initialize the buffer with random data */
40691.101Skamil	for (i = 0; i < len; i++)
40701.101Skamil		buffer[i] = i & 0xff;
40711.101Skamil
40721.101Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
40731.101Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
40741.101Skamil	if (child == 0) {
40751.101Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40761.101Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40771.101Skamil
40781.101Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40791.101Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40801.101Skamil
40811.101Skamil		DPRINTF("Before exiting of the child process\n");
40821.101Skamil		_exit(exitval);
40831.101Skamil	}
40841.101Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40851.101Skamil
40861.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40871.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40881.101Skamil
40891.101Skamil	validate_status_stopped(status, sigval);
40901.101Skamil
40911.101Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40921.101Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
40931.101Skamil		!= -1);
40941.101Skamil
40951.101Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
40961.101Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
40971.101Skamil		"si_errno=%#x\n",
40981.101Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
40991.101Skamil		info.psi_siginfo.si_errno);
41001.101Skamil
41011.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
41021.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
41031.101Skamil
41041.101Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
41051.101Skamil	    strcmp(operation, "PT_READ_D") == 0) {
41061.101Skamil		if (strcmp(operation, "PT_READ_I"))
41071.101Skamil			op = PT_READ_I;
41081.101Skamil		else
41091.101Skamil			op = PT_READ_D;
41101.101Skamil
41111.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41121.101Skamil			errno = 0;
41131.101Skamil			vector = ptrace(op, child, buffer + i, 0);
41141.101Skamil			ATF_REQUIRE_EQ(errno, 0);
41151.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
41161.101Skamil		}
41171.101Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
41181.101Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
41191.101Skamil		if (strcmp(operation, "PT_WRITE_I"))
41201.101Skamil			op = PT_WRITE_I;
41211.101Skamil		else
41221.101Skamil			op = PT_WRITE_D;
41231.101Skamil
41241.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41251.101Skamil			memcpy(&vector, buffer + i, sizeof(int));
41261.101Skamil			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
41271.101Skamil			    != -1);
41281.101Skamil		}
41291.101Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
41301.101Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
41311.101Skamil		if (strcmp(operation, "PIOD_READ_I"))
41321.101Skamil			op = PIOD_READ_I;
41331.101Skamil		else
41341.101Skamil			op = PIOD_READ_D;
41351.101Skamil
41361.101Skamil		io.piod_op = op;
41371.101Skamil		io.piod_addr = &vector;
41381.101Skamil		io.piod_len = sizeof(int);
41391.101Skamil
41401.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41411.101Skamil			io.piod_offs = buffer + i;
41421.101Skamil
41431.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
41441.101Skamil			                != -1);
41451.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
41461.101Skamil		}
41471.101Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
41481.101Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
41491.101Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
41501.101Skamil			op = PIOD_WRITE_I;
41511.101Skamil		else
41521.101Skamil			op = PIOD_WRITE_D;
41531.101Skamil
41541.101Skamil		io.piod_op = op;
41551.101Skamil		io.piod_addr = &vector;
41561.101Skamil		io.piod_len = sizeof(int);
41571.101Skamil
41581.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
41591.101Skamil			io.piod_offs = buffer + i;
41601.101Skamil
41611.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
41621.101Skamil			                != -1);
41631.101Skamil		}
41641.101Skamil	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
41651.101Skamil		io.piod_op = PIOD_READ_AUXV;
41661.101Skamil		io.piod_addr = &vector;
41671.101Skamil		io.piod_len = sizeof(int);
41681.101Skamil
41691.101Skamil		errno = 0;
41701.101Skamil		i = 0;
41711.101Skamil		/* Read the whole AUXV vector, it has no clear length */
41721.120Skamil		while (io.piod_len > 0) {
41731.101Skamil			io.piod_offs = (void *)(intptr_t)i;
41741.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
41751.120Skamil			                != -1 || (io.piod_len == 0 && i > 0));
41761.101Skamil			++i;
41771.101Skamil		}
41781.101Skamil	}
41791.101Skamil
41801.101Skamil	DPRINTF("Before resuming the child process where it left off "
41811.101Skamil	    "and without signal to be sent\n");
41821.101Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41831.101Skamil
41841.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41851.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
41861.101Skamil	    child);
41871.101Skamil
41881.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41891.101Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41901.101Skamil}
41911.101Skamil
41921.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
41931.101SkamilATF_TC(test);								\
41941.101SkamilATF_TC_HEAD(test, tc)							\
41951.101Skamil{									\
41961.101Skamil	atf_tc_set_md_var(tc, "descr",					\
41971.101Skamil	    "Verify bytes transfer for potentially misaligned "		\
41981.101Skamil	    "operation " operation);					\
41991.101Skamil}									\
42001.101Skamil									\
42011.101SkamilATF_TC_BODY(test, tc)							\
42021.101Skamil{									\
42031.101Skamil									\
42041.101Skamil	bytes_transfer_alignment(operation);				\
42051.101Skamil}
42061.101Skamil
42071.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
42081.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
42091.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
42101.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
42111.101Skamil
42121.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
42131.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
42141.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
42151.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
42161.101Skamil
42171.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
42181.101Skamil
42191.101Skamil/// ----------------------------------------------------------------------------
42201.101Skamil
42211.115Skamilstatic void
42221.115Skamilbytes_transfer_eof(const char *operation)
42231.115Skamil{
42241.115Skamil	const int exitval = 5;
42251.115Skamil	const int sigval = SIGSTOP;
42261.115Skamil	pid_t child, wpid;
42271.115Skamil#if defined(TWAIT_HAVE_STATUS)
42281.115Skamil	int status;
42291.115Skamil#endif
42301.115Skamil	FILE *fp;
42311.115Skamil	char *p;
42321.115Skamil	int vector;
42331.115Skamil	int op;
42341.115Skamil
42351.115Skamil	struct ptrace_io_desc io;
42361.115Skamil	struct ptrace_siginfo info;
42371.115Skamil
42381.115Skamil	memset(&io, 0, sizeof(io));
42391.115Skamil	memset(&info, 0, sizeof(info));
42401.115Skamil
42411.115Skamil	vector = 0;
42421.115Skamil
42431.115Skamil	fp = tmpfile();
42441.115Skamil	ATF_REQUIRE(fp != NULL);
42451.115Skamil
42461.115Skamil	p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
42471.115Skamil	ATF_REQUIRE(p != MAP_FAILED);
42481.115Skamil
42491.115Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
42501.115Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
42511.115Skamil	if (child == 0) {
42521.115Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42531.115Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42541.115Skamil
42551.115Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42561.115Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42571.115Skamil
42581.115Skamil		DPRINTF("Before exiting of the child process\n");
42591.115Skamil		_exit(exitval);
42601.115Skamil	}
42611.115Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42621.115Skamil
42631.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42641.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42651.115Skamil
42661.115Skamil	validate_status_stopped(status, sigval);
42671.115Skamil
42681.115Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
42691.115Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
42701.115Skamil		!= -1);
42711.115Skamil
42721.115Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
42731.115Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
42741.115Skamil		"si_errno=%#x\n",
42751.115Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
42761.115Skamil		info.psi_siginfo.si_errno);
42771.115Skamil
42781.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
42791.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
42801.115Skamil
42811.115Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
42821.115Skamil	    strcmp(operation, "PT_READ_D") == 0) {
42831.115Skamil		if (strcmp(operation, "PT_READ_I"))
42841.115Skamil			op = PT_READ_I;
42851.115Skamil		else
42861.115Skamil			op = PT_READ_D;
42871.115Skamil
42881.115Skamil		errno = 0;
42891.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1);
42901.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42911.115Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
42921.115Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
42931.115Skamil		if (strcmp(operation, "PT_WRITE_I"))
42941.115Skamil			op = PT_WRITE_I;
42951.115Skamil		else
42961.115Skamil			op = PT_WRITE_D;
42971.115Skamil
42981.115Skamil		errno = 0;
42991.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1);
43001.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
43011.115Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
43021.115Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
43031.115Skamil		if (strcmp(operation, "PIOD_READ_I"))
43041.115Skamil			op = PIOD_READ_I;
43051.115Skamil		else
43061.115Skamil			op = PIOD_READ_D;
43071.115Skamil
43081.115Skamil		io.piod_op = op;
43091.115Skamil		io.piod_addr = &vector;
43101.115Skamil		io.piod_len = sizeof(int);
43111.115Skamil		io.piod_offs = p;
43121.115Skamil
43131.115Skamil		errno = 0;
43141.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
43151.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
43161.115Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
43171.115Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
43181.115Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
43191.115Skamil			op = PIOD_WRITE_I;
43201.115Skamil		else
43211.115Skamil			op = PIOD_WRITE_D;
43221.115Skamil
43231.115Skamil		io.piod_op = op;
43241.115Skamil		io.piod_addr = &vector;
43251.115Skamil		io.piod_len = sizeof(int);
43261.115Skamil		io.piod_offs = p;
43271.115Skamil
43281.115Skamil		errno = 0;
43291.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
43301.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
43311.115Skamil	}
43321.115Skamil
43331.115Skamil	DPRINTF("Before resuming the child process where it left off "
43341.115Skamil	    "and without signal to be sent\n");
43351.115Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43361.115Skamil
43371.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43381.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
43391.115Skamil	    child);
43401.115Skamil
43411.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43421.115Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43431.115Skamil}
43441.115Skamil
43451.115Skamil#define BYTES_TRANSFER_EOF(test, operation)				\
43461.115SkamilATF_TC(test);								\
43471.115SkamilATF_TC_HEAD(test, tc)							\
43481.115Skamil{									\
43491.115Skamil	atf_tc_set_md_var(tc, "descr",					\
43501.115Skamil	    "Verify bytes EOF byte transfer for the " operation		\
43511.115Skamil	    " operation");						\
43521.115Skamil}									\
43531.115Skamil									\
43541.115SkamilATF_TC_BODY(test, tc)							\
43551.115Skamil{									\
43561.115Skamil									\
43571.115Skamil	bytes_transfer_eof(operation);					\
43581.115Skamil}
43591.115Skamil
43601.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I")
43611.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D")
43621.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I")
43631.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D")
43641.115Skamil
43651.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I")
43661.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D")
43671.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I")
43681.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D")
43691.115Skamil
43701.115Skamil/// ----------------------------------------------------------------------------
43711.115Skamil
43721.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
43731.72Skamilstatic void
43741.72Skamilaccess_regs(const char *regset, const char *aux)
43751.1Skamil{
43761.1Skamil	const int exitval = 5;
43771.1Skamil	const int sigval = SIGSTOP;
43781.1Skamil	pid_t child, wpid;
43791.1Skamil#if defined(TWAIT_HAVE_STATUS)
43801.1Skamil	int status;
43811.1Skamil#endif
43821.72Skamil#if defined(HAVE_GPREGS)
43831.72Skamil	struct reg gpr;
43841.76Sscole	register_t rgstr;
43851.1Skamil#endif
43861.72Skamil#if defined(HAVE_FPREGS)
43871.72Skamil	struct fpreg fpr;
43881.1Skamil#endif
43891.76Sscole
43901.72Skamil#if !defined(HAVE_GPREGS)
43911.72Skamil	if (strcmp(regset, "regs") == 0)
43921.72Skamil		atf_tc_fail("Impossible test scenario!");
43931.1Skamil#endif
43941.1Skamil
43951.72Skamil#if !defined(HAVE_FPREGS)
43961.72Skamil	if (strcmp(regset, "fpregs") == 0)
43971.72Skamil		atf_tc_fail("Impossible test scenario!");
43981.1Skamil#endif
43991.1Skamil
44001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44021.1Skamil	if (child == 0) {
44031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44051.1Skamil
44061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44081.1Skamil
44091.13Schristos		DPRINTF("Before exiting of the child process\n");
44101.1Skamil		_exit(exitval);
44111.1Skamil	}
44121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44131.1Skamil
44141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44161.1Skamil
44171.1Skamil	validate_status_stopped(status, sigval);
44181.1Skamil
44191.1Skamil#if defined(HAVE_GPREGS)
44201.72Skamil	if (strcmp(regset, "regs") == 0) {
44211.72Skamil		DPRINTF("Call GETREGS for the child process\n");
44221.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
44231.72Skamil
44241.72Skamil		if (strcmp(aux, "none") == 0) {
44251.72Skamil			DPRINTF("Retrieved registers\n");
44261.72Skamil		} else if (strcmp(aux, "pc") == 0) {
44271.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
44281.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44291.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
44301.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
44311.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
44321.72Skamil		} else if (strcmp(aux, "sp") == 0) {
44331.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
44341.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44351.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
44361.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
44371.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
44381.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
44391.72Skamil			DPRINTF("Call SETREGS for the child process\n");
44401.72Skamil			SYSCALL_REQUIRE(
44411.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
44421.72Skamil		}
44431.72Skamil	}
44441.1Skamil#endif
44451.1Skamil
44461.72Skamil#if defined(HAVE_FPREGS)
44471.72Skamil	if (strcmp(regset, "fpregs") == 0) {
44481.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
44491.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
44501.72Skamil
44511.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
44521.72Skamil			DPRINTF("Retrieved FP registers\n");
44531.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
44541.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
44551.72Skamil			SYSCALL_REQUIRE(
44561.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
44571.72Skamil		}
44581.1Skamil	}
44591.1Skamil#endif
44601.1Skamil
44611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44621.1Skamil	    "without signal to be sent\n");
44631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44641.1Skamil
44651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44671.1Skamil
44681.1Skamil	validate_status_exited(status, exitval);
44691.1Skamil
44701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44721.1Skamil}
44731.1Skamil
44741.72Skamil#define ACCESS_REGS(test, regset, aux)					\
44751.72SkamilATF_TC(test);								\
44761.72SkamilATF_TC_HEAD(test, tc)							\
44771.72Skamil{									\
44781.72Skamil        atf_tc_set_md_var(tc, "descr",					\
44791.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
44801.72Skamil}									\
44811.72Skamil									\
44821.72SkamilATF_TC_BODY(test, tc)							\
44831.72Skamil{									\
44841.72Skamil									\
44851.72Skamil        access_regs(regset, aux);					\
44861.1Skamil}
44871.1Skamil#endif
44881.1Skamil
44891.72Skamil#if defined(HAVE_GPREGS)
44901.72SkamilACCESS_REGS(access_regs1, "regs", "none")
44911.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
44921.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
44931.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
44941.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
44951.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
44961.1Skamil#endif
44971.1Skamil#if defined(HAVE_FPREGS)
44981.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
44991.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
45001.1Skamil#endif
45011.1Skamil
45021.72Skamil/// ----------------------------------------------------------------------------
45031.1Skamil
45041.1Skamil#if defined(PT_STEP)
45051.1Skamilstatic void
45061.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
45071.1Skamil{
45081.1Skamil	const int exitval = 5;
45091.1Skamil	const int sigval = SIGSTOP;
45101.1Skamil	pid_t child, wpid;
45111.1Skamil#if defined(TWAIT_HAVE_STATUS)
45121.1Skamil	int status;
45131.1Skamil#endif
45141.1Skamil	int happy;
45151.95Skamil	struct sigaction sa;
45161.81Skamil	struct ptrace_siginfo info;
45171.95Skamil	sigset_t intmask;
45181.95Skamil	struct kinfo_proc2 kp;
45191.95Skamil	size_t len = sizeof(kp);
45201.95Skamil
45211.95Skamil	int name[6];
45221.95Skamil	const size_t namelen = __arraycount(name);
45231.95Skamil	ki_sigset_t kp_sigmask;
45241.95Skamil	ki_sigset_t kp_sigignore;
45251.1Skamil
45261.1Skamil#if defined(__arm__)
45271.1Skamil	/* PT_STEP not supported on arm 32-bit */
45281.1Skamil	atf_tc_expect_fail("PR kern/52119");
45291.1Skamil#endif
45301.1Skamil
45311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45331.1Skamil	if (child == 0) {
45341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45361.1Skamil
45371.95Skamil		if (masked) {
45381.95Skamil			sigemptyset(&intmask);
45391.95Skamil			sigaddset(&intmask, SIGTRAP);
45401.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
45411.95Skamil		}
45421.95Skamil
45431.95Skamil		if (ignored) {
45441.95Skamil			memset(&sa, 0, sizeof(sa));
45451.95Skamil			sa.sa_handler = SIG_IGN;
45461.95Skamil			sigemptyset(&sa.sa_mask);
45471.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
45481.95Skamil		}
45491.95Skamil
45501.1Skamil		happy = check_happy(999);
45511.1Skamil
45521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45541.1Skamil
45551.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
45561.1Skamil
45571.13Schristos		DPRINTF("Before exiting of the child process\n");
45581.1Skamil		_exit(exitval);
45591.1Skamil	}
45601.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45611.1Skamil
45621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45641.1Skamil
45651.1Skamil	validate_status_stopped(status, sigval);
45661.1Skamil
45671.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45681.81Skamil	SYSCALL_REQUIRE(
45691.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45701.81Skamil
45711.81Skamil	DPRINTF("Before checking siginfo_t\n");
45721.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
45731.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
45741.81Skamil
45751.95Skamil	name[0] = CTL_KERN,
45761.95Skamil	name[1] = KERN_PROC2,
45771.95Skamil	name[2] = KERN_PROC_PID;
45781.95Skamil	name[3] = child;
45791.95Skamil	name[4] = sizeof(kp);
45801.95Skamil	name[5] = 1;
45811.95Skamil
45821.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
45831.95Skamil
45841.95Skamil	if (masked)
45851.95Skamil		kp_sigmask = kp.p_sigmask;
45861.95Skamil
45871.95Skamil	if (ignored)
45881.95Skamil		kp_sigignore = kp.p_sigignore;
45891.95Skamil
45901.1Skamil	while (N --> 0) {
45911.2Skamil		if (setstep) {
45921.13Schristos			DPRINTF("Before resuming the child process where it "
45931.2Skamil			    "left off and without signal to be sent (use "
45941.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
45951.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
45961.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
45971.2Skamil			    != -1);
45981.2Skamil		} else {
45991.13Schristos			DPRINTF("Before resuming the child process where it "
46001.2Skamil			    "left off and without signal to be sent (use "
46011.2Skamil			    "PT_STEP)\n");
46021.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
46031.2Skamil			    != -1);
46041.2Skamil		}
46051.1Skamil
46061.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46071.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
46081.1Skamil		    child);
46091.1Skamil
46101.1Skamil		validate_status_stopped(status, SIGTRAP);
46111.2Skamil
46121.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
46131.81Skamil		SYSCALL_REQUIRE(
46141.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
46151.81Skamil
46161.81Skamil		DPRINTF("Before checking siginfo_t\n");
46171.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
46181.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
46191.81Skamil
46201.2Skamil		if (setstep) {
46211.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
46221.2Skamil		}
46231.95Skamil
46241.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
46251.95Skamil
46261.95Skamil		if (masked) {
46271.95Skamil			DPRINTF("kp_sigmask="
46281.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46291.95Skamil			    PRIx32 "\n",
46301.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
46311.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
46321.95Skamil
46331.95Skamil			DPRINTF("kp.p_sigmask="
46341.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46351.95Skamil			    PRIx32 "\n",
46361.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
46371.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
46381.95Skamil
46391.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
46401.95Skamil			    sizeof(kp_sigmask)));
46411.95Skamil		}
46421.95Skamil
46431.95Skamil		if (ignored) {
46441.95Skamil			DPRINTF("kp_sigignore="
46451.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46461.95Skamil			    PRIx32 "\n",
46471.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
46481.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
46491.95Skamil
46501.95Skamil			DPRINTF("kp.p_sigignore="
46511.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
46521.95Skamil			    PRIx32 "\n",
46531.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
46541.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
46551.95Skamil
46561.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
46571.95Skamil			    sizeof(kp_sigignore)));
46581.95Skamil		}
46591.1Skamil	}
46601.1Skamil
46611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46621.1Skamil	    "without signal to be sent\n");
46631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46641.1Skamil
46651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46671.1Skamil
46681.1Skamil	validate_status_exited(status, exitval);
46691.1Skamil
46701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46721.1Skamil}
46731.1Skamil
46741.73Skamil#define PTRACE_STEP(test, N, setstep)					\
46751.73SkamilATF_TC(test);								\
46761.73SkamilATF_TC_HEAD(test, tc)							\
46771.73Skamil{									\
46781.73Skamil        atf_tc_set_md_var(tc, "descr",					\
46791.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
46801.73Skamil}									\
46811.73Skamil									\
46821.73SkamilATF_TC_BODY(test, tc)							\
46831.73Skamil{									\
46841.73Skamil									\
46851.95Skamil        ptrace_step(N, setstep, false, false);				\
46861.1Skamil}
46871.1Skamil
46881.73SkamilPTRACE_STEP(step1, 1, 0)
46891.73SkamilPTRACE_STEP(step2, 2, 0)
46901.73SkamilPTRACE_STEP(step3, 3, 0)
46911.73SkamilPTRACE_STEP(step4, 4, 0)
46921.73SkamilPTRACE_STEP(setstep1, 1, 1)
46931.73SkamilPTRACE_STEP(setstep2, 2, 1)
46941.73SkamilPTRACE_STEP(setstep3, 3, 1)
46951.73SkamilPTRACE_STEP(setstep4, 4, 1)
46961.95Skamil
46971.95SkamilATF_TC(step_signalmasked);
46981.95SkamilATF_TC_HEAD(step_signalmasked, tc)
46991.95Skamil{
47001.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
47011.95Skamil}
47021.95Skamil
47031.95SkamilATF_TC_BODY(step_signalmasked, tc)
47041.95Skamil{
47051.95Skamil
47061.95Skamil	ptrace_step(1, 0, true, false);
47071.95Skamil}
47081.95Skamil
47091.95SkamilATF_TC(step_signalignored);
47101.95SkamilATF_TC_HEAD(step_signalignored, tc)
47111.95Skamil{
47121.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
47131.95Skamil}
47141.95Skamil
47151.95SkamilATF_TC_BODY(step_signalignored, tc)
47161.95Skamil{
47171.95Skamil
47181.95Skamil	ptrace_step(1, 0, false, true);
47191.95Skamil}
47201.1Skamil#endif
47211.1Skamil
47221.73Skamil/// ----------------------------------------------------------------------------
47231.1Skamil
47241.75Skamilstatic void
47251.75Skamilptrace_kill(const char *type)
47261.1Skamil{
47271.75Skamil	const int sigval = SIGSTOP;
47281.1Skamil	pid_t child, wpid;
47291.1Skamil#if defined(TWAIT_HAVE_STATUS)
47301.1Skamil	int status;
47311.1Skamil#endif
47321.1Skamil
47331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47351.1Skamil	if (child == 0) {
47361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47381.1Skamil
47391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47411.1Skamil
47421.1Skamil		/* NOTREACHED */
47431.1Skamil		FORKEE_ASSERTX(0 &&
47441.1Skamil		    "Child should be terminated by a signal from its parent");
47451.1Skamil	}
47461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47471.1Skamil
47481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47501.1Skamil
47511.1Skamil	validate_status_stopped(status, sigval);
47521.1Skamil
47531.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
47541.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
47551.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
47561.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
47571.75Skamil		kill(child, SIGKILL);
47581.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
47591.75Skamil		setpgid(child, 0);
47601.75Skamil		killpg(getpgid(child), SIGKILL);
47611.75Skamil	}
47621.1Skamil
47631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47651.1Skamil
47661.75Skamil	validate_status_signaled(status, SIGKILL, 0);
47671.1Skamil
47681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47701.1Skamil}
47711.1Skamil
47721.75Skamil#define PTRACE_KILL(test, type)						\
47731.75SkamilATF_TC(test);								\
47741.75SkamilATF_TC_HEAD(test, tc)							\
47751.75Skamil{									\
47761.75Skamil        atf_tc_set_md_var(tc, "descr",					\
47771.75Skamil            "Verify killing the child with " type);			\
47781.75Skamil}									\
47791.75Skamil									\
47801.75SkamilATF_TC_BODY(test, tc)							\
47811.75Skamil{									\
47821.75Skamil									\
47831.75Skamil        ptrace_kill(type);						\
47841.1Skamil}
47851.1Skamil
47861.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
47871.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
47881.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
47891.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
47901.1Skamil
47911.75Skamil/// ----------------------------------------------------------------------------
47921.1Skamil
47931.77Skamilstatic void
47941.77Skamiltraceme_lwpinfo(const int threads)
47951.1Skamil{
47961.1Skamil	const int sigval = SIGSTOP;
47971.77Skamil	const int sigval2 = SIGINT;
47981.1Skamil	pid_t child, wpid;
47991.1Skamil#if defined(TWAIT_HAVE_STATUS)
48001.1Skamil	int status;
48011.1Skamil#endif
48021.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
48031.77Skamil	struct ptrace_siginfo info;
48041.77Skamil
48051.77Skamil	/* Maximum number of supported threads in this test */
48061.77Skamil	pthread_t t[3];
48071.77Skamil	int n, rv;
48081.77Skamil
48091.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
48101.1Skamil
48111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48131.1Skamil	if (child == 0) {
48141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48161.1Skamil
48171.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48181.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48191.1Skamil
48201.77Skamil		for (n = 0; n < threads; n++) {
48211.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
48221.77Skamil			FORKEE_ASSERT(rv == 0);
48231.77Skamil		}
48241.77Skamil
48251.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
48261.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
48271.77Skamil
48281.77Skamil		/* NOTREACHED */
48291.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
48301.1Skamil	}
48311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48321.1Skamil
48331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48351.1Skamil
48361.1Skamil	validate_status_stopped(status, sigval);
48371.1Skamil
48381.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
48391.77Skamil	SYSCALL_REQUIRE(
48401.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48411.77Skamil
48421.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48431.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48441.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48451.77Skamil	    info.psi_siginfo.si_errno);
48461.77Skamil
48471.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
48481.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
48491.77Skamil
48501.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48511.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48521.1Skamil
48531.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
48541.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
48551.1Skamil
48561.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
48571.77Skamil	    lwp.pl_lwpid);
48581.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
48591.1Skamil
48601.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48611.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48621.1Skamil
48631.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
48641.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
48651.1Skamil
48661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48671.1Skamil	    "without signal to be sent\n");
48681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48691.1Skamil
48701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48721.1Skamil
48731.77Skamil	validate_status_stopped(status, sigval2);
48741.77Skamil
48751.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
48761.77Skamil	SYSCALL_REQUIRE(
48771.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48781.77Skamil
48791.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48801.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48811.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48821.77Skamil	    info.psi_siginfo.si_errno);
48831.77Skamil
48841.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
48851.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
48861.77Skamil
48871.77Skamil	memset(&lwp, 0, sizeof(lwp));
48881.77Skamil
48891.77Skamil	for (n = 0; n <= threads; n++) {
48901.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48911.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48921.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
48931.77Skamil
48941.77Skamil		DPRINTF("Assert that the thread exists\n");
48951.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
48961.77Skamil
48971.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
48981.77Skamil		    lwp.pl_lwpid);
48991.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
49001.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
49011.77Skamil	}
49021.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
49031.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
49041.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
49051.77Skamil
49061.77Skamil	DPRINTF("Assert that there are no more threads\n");
49071.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
49081.77Skamil
49091.77Skamil	DPRINTF("Before resuming the child process where it left off and "
49101.77Skamil	    "without signal to be sent\n");
49111.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
49121.77Skamil
49131.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49141.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49151.77Skamil
49161.77Skamil	validate_status_signaled(status, SIGKILL, 0);
49171.1Skamil
49181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49191.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49201.1Skamil}
49211.1Skamil
49221.77Skamil#define TRACEME_LWPINFO(test, threads)					\
49231.77SkamilATF_TC(test);								\
49241.77SkamilATF_TC_HEAD(test, tc)							\
49251.77Skamil{									\
49261.77Skamil	atf_tc_set_md_var(tc, "descr",					\
49271.77Skamil	    "Verify LWPINFO with the child with " #threads		\
49281.77Skamil	    " spawned extra threads");					\
49291.77Skamil}									\
49301.77Skamil									\
49311.77SkamilATF_TC_BODY(test, tc)							\
49321.77Skamil{									\
49331.77Skamil									\
49341.77Skamil	traceme_lwpinfo(threads);					\
49351.1Skamil}
49361.1Skamil
49371.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
49381.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
49391.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
49401.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
49411.77Skamil
49421.77Skamil/// ----------------------------------------------------------------------------
49431.77Skamil
49441.77Skamil#if defined(TWAIT_HAVE_PID)
49451.77Skamilstatic void
49461.77Skamilattach_lwpinfo(const int threads)
49471.1Skamil{
49481.77Skamil	const int sigval = SIGINT;
49491.1Skamil	struct msg_fds parent_tracee, parent_tracer;
49501.1Skamil	const int exitval_tracer = 10;
49511.1Skamil	pid_t tracee, tracer, wpid;
49521.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
49531.1Skamil#if defined(TWAIT_HAVE_STATUS)
49541.1Skamil	int status;
49551.1Skamil#endif
49561.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
49571.77Skamil	struct ptrace_siginfo info;
49581.77Skamil
49591.77Skamil	/* Maximum number of supported threads in this test */
49601.77Skamil	pthread_t t[3];
49611.77Skamil	int n, rv;
49621.1Skamil
49631.13Schristos	DPRINTF("Spawn tracee\n");
49641.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
49651.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
49661.1Skamil	tracee = atf_utils_fork();
49671.1Skamil	if (tracee == 0) {
49681.1Skamil		/* Wait for message from the parent */
49691.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
49701.1Skamil
49711.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
49721.77Skamil
49731.77Skamil		for (n = 0; n < threads; n++) {
49741.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
49751.77Skamil			FORKEE_ASSERT(rv == 0);
49761.77Skamil		}
49771.77Skamil
49781.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
49791.77Skamil
49801.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49811.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49821.77Skamil
49831.77Skamil		/* NOTREACHED */
49841.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
49851.1Skamil	}
49861.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
49871.1Skamil
49881.13Schristos	DPRINTF("Spawn debugger\n");
49891.1Skamil	tracer = atf_utils_fork();
49901.1Skamil	if (tracer == 0) {
49911.1Skamil		/* No IPC to communicate with the child */
49921.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
49931.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
49941.1Skamil
49951.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
49961.1Skamil		FORKEE_REQUIRE_SUCCESS(
49971.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
49981.1Skamil
49991.1Skamil		forkee_status_stopped(status, SIGSTOP);
50001.1Skamil
50011.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
50021.77Skamil		    "tracee");
50031.77Skamil		FORKEE_ASSERT(
50041.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
50051.77Skamil
50061.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50071.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50081.77Skamil		    "si_errno=%#x\n",
50091.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50101.77Skamil		    info.psi_siginfo.si_errno);
50111.77Skamil
50121.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
50131.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
50141.77Skamil
50151.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
50161.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
50171.1Skamil		    != -1);
50181.1Skamil
50191.13Schristos		DPRINTF("Assert that there exists a thread\n");
50201.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
50211.1Skamil
50221.13Schristos		DPRINTF("Assert that lwp thread %d received event "
50231.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
50241.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
50251.1Skamil
50261.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50271.77Skamil		    "tracee\n");
50281.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
50291.1Skamil		    != -1);
50301.1Skamil
50311.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
50321.77Skamil		    "tracee\n");
50331.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
50341.1Skamil
50351.1Skamil		/* Resume tracee with PT_CONTINUE */
50361.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
50371.1Skamil
50381.1Skamil		/* Inform parent that tracer has attached to tracee */
50391.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
50401.77Skamil
50411.1Skamil		/* Wait for parent */
50421.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
50431.1Skamil
50441.77Skamil		/* Wait for tracee and assert that it raised a signal */
50451.77Skamil		FORKEE_REQUIRE_SUCCESS(
50461.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
50471.77Skamil
50481.77Skamil		forkee_status_stopped(status, SIGINT);
50491.77Skamil
50501.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
50511.77Skamil		    "child");
50521.77Skamil		FORKEE_ASSERT(
50531.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
50541.77Skamil
50551.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50561.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50571.77Skamil		    "si_errno=%#x\n",
50581.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50591.77Skamil		    info.psi_siginfo.si_errno);
50601.77Skamil
50611.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
50621.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
50631.77Skamil
50641.77Skamil		memset(&lwp, 0, sizeof(lwp));
50651.77Skamil
50661.77Skamil		for (n = 0; n <= threads; n++) {
50671.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50681.77Skamil			    "child\n");
50691.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
50701.77Skamil			    sizeof(lwp)) != -1);
50711.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
50721.77Skamil
50731.77Skamil			DPRINTF("Assert that the thread exists\n");
50741.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
50751.77Skamil
50761.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
50771.77Skamil			    "event\n", lwp.pl_lwpid);
50781.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
50791.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
50801.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
50811.77Skamil		}
50821.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
50831.77Skamil		    "tracee\n");
50841.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
50851.77Skamil		    != -1);
50861.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
50871.77Skamil
50881.77Skamil		DPRINTF("Assert that there are no more threads\n");
50891.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
50901.77Skamil
50911.77Skamil		DPRINTF("Before resuming the child process where it left off "
50921.77Skamil		    "and without signal to be sent\n");
50931.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
50941.77Skamil		    != -1);
50951.77Skamil
50961.1Skamil		/* Wait for tracee and assert that it exited */
50971.1Skamil		FORKEE_REQUIRE_SUCCESS(
50981.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
50991.1Skamil
51001.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
51011.1Skamil
51021.13Schristos		DPRINTF("Before exiting of the tracer process\n");
51031.1Skamil		_exit(exitval_tracer);
51041.1Skamil	}
51051.1Skamil
51061.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
51071.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
51081.1Skamil
51091.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
51101.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
51111.77Skamil
51121.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
51131.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
51141.1Skamil
51151.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
51161.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
51171.1Skamil
51181.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
51191.1Skamil	    TWAIT_FNAME);
51201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
51211.1Skamil	    tracer);
51221.1Skamil
51231.1Skamil	validate_status_exited(status, exitval_tracer);
51241.1Skamil
51251.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
51261.1Skamil	    TWAIT_FNAME);
51271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
51281.1Skamil	    tracee);
51291.1Skamil
51301.77Skamil	validate_status_signaled(status, SIGKILL, 0);
51311.1Skamil
51321.1Skamil	msg_close(&parent_tracer);
51331.1Skamil	msg_close(&parent_tracee);
51341.1Skamil}
51351.77Skamil
51361.77Skamil#define ATTACH_LWPINFO(test, threads)					\
51371.77SkamilATF_TC(test);								\
51381.77SkamilATF_TC_HEAD(test, tc)							\
51391.77Skamil{									\
51401.77Skamil	atf_tc_set_md_var(tc, "descr",					\
51411.77Skamil	    "Verify LWPINFO with the child with " #threads		\
51421.77Skamil	    " spawned extra threads (tracer is not the original "	\
51431.77Skamil	    "parent)");							\
51441.77Skamil}									\
51451.77Skamil									\
51461.77SkamilATF_TC_BODY(test, tc)							\
51471.77Skamil{									\
51481.77Skamil									\
51491.77Skamil	attach_lwpinfo(threads);					\
51501.77Skamil}
51511.77Skamil
51521.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
51531.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
51541.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
51551.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
51561.1Skamil#endif
51571.1Skamil
51581.77Skamil/// ----------------------------------------------------------------------------
51591.77Skamil
51601.1Skamilstatic void
51611.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
51621.1Skamil{
51631.1Skamil	const int exitval = 5;
51641.1Skamil	const int sigval = SIGINT;
51651.1Skamil	const int sigfaked = SIGTRAP;
51661.1Skamil	const int sicodefaked = TRAP_BRKPT;
51671.1Skamil	pid_t child, wpid;
51681.1Skamil	struct sigaction sa;
51691.1Skamil#if defined(TWAIT_HAVE_STATUS)
51701.1Skamil	int status;
51711.1Skamil#endif
51721.1Skamil	struct ptrace_siginfo info;
51731.1Skamil	memset(&info, 0, sizeof(info));
51741.1Skamil
51751.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51761.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51771.1Skamil	if (child == 0) {
51781.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51791.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51801.1Skamil
51811.79Skamil		sa.sa_sigaction = sah;
51821.1Skamil		sa.sa_flags = SA_SIGINFO;
51831.1Skamil		sigemptyset(&sa.sa_mask);
51841.1Skamil
51851.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
51861.79Skamil		    != -1);
51871.1Skamil
51881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51901.1Skamil
51911.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
51921.1Skamil
51931.13Schristos		DPRINTF("Before exiting of the child process\n");
51941.1Skamil		_exit(exitval);
51951.1Skamil	}
51961.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51971.1Skamil
51981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52001.1Skamil
52011.1Skamil	validate_status_stopped(status, sigval);
52021.1Skamil
52031.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52041.61Skre	SYSCALL_REQUIRE(
52051.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52061.1Skamil
52071.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
52081.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
52091.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
52101.1Skamil	    info.psi_siginfo.si_errno);
52111.1Skamil
52121.79Skamil	if (faked) {
52131.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
52141.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
52151.79Skamil		info.psi_siginfo.si_signo = sigfaked;
52161.79Skamil		info.psi_siginfo.si_code = sicodefaked;
52171.79Skamil	}
52181.1Skamil
52191.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
52201.61Skre	SYSCALL_REQUIRE(
52211.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
52221.1Skamil
52231.79Skamil	if (faked) {
52241.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
52251.79Skamil		    "child\n");
52261.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
52271.79Skamil		    sizeof(info)) != -1);
52281.1Skamil
52291.79Skamil		DPRINTF("Before checking siginfo_t\n");
52301.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
52311.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
52321.79Skamil	}
52331.1Skamil
52341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52351.1Skamil	    "without signal to be sent\n");
52361.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
52371.79Skamil	    faked ? sigfaked : sigval) != -1);
52381.1Skamil
52391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52411.1Skamil
52421.1Skamil	validate_status_exited(status, exitval);
52431.1Skamil
52441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52461.1Skamil}
52471.1Skamil
52481.79Skamil#define PTRACE_SIGINFO(test, faked)					\
52491.79SkamilATF_TC(test);								\
52501.79SkamilATF_TC_HEAD(test, tc)							\
52511.79Skamil{									\
52521.79Skamil	atf_tc_set_md_var(tc, "descr",					\
52531.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
52541.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
52551.79Skamil}									\
52561.79Skamil									\
52571.79Skamilstatic int test##_caught = 0;						\
52581.79Skamil									\
52591.79Skamilstatic void								\
52601.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
52611.79Skamil{									\
52621.79Skamil	if (faked) {							\
52631.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
52641.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
52651.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
52661.79Skamil	} else {							\
52671.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
52681.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
52691.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
52701.79Skamil	}								\
52711.79Skamil									\
52721.79Skamil	++ test##_caught;						\
52731.79Skamil}									\
52741.79Skamil									\
52751.79SkamilATF_TC_BODY(test, tc)							\
52761.79Skamil{									\
52771.79Skamil									\
52781.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
52791.79Skamil}
52801.79Skamil
52811.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
52821.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
52831.79Skamil
52841.79Skamil/// ----------------------------------------------------------------------------
52851.79Skamil
52861.97Skamilstatic void
52871.97Skamiltraceme_exec(bool masked, bool ignored)
52881.1Skamil{
52891.1Skamil	const int sigval = SIGTRAP;
52901.1Skamil	pid_t child, wpid;
52911.1Skamil#if defined(TWAIT_HAVE_STATUS)
52921.1Skamil	int status;
52931.1Skamil#endif
52941.97Skamil	struct sigaction sa;
52951.97Skamil	struct ptrace_siginfo info;
52961.97Skamil	sigset_t intmask;
52971.97Skamil	struct kinfo_proc2 kp;
52981.97Skamil	size_t len = sizeof(kp);
52991.97Skamil
53001.97Skamil	int name[6];
53011.97Skamil	const size_t namelen = __arraycount(name);
53021.97Skamil	ki_sigset_t kp_sigmask;
53031.97Skamil	ki_sigset_t kp_sigignore;
53041.1Skamil
53051.1Skamil	memset(&info, 0, sizeof(info));
53061.1Skamil
53071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53091.1Skamil	if (child == 0) {
53101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53121.1Skamil
53131.97Skamil		if (masked) {
53141.97Skamil			sigemptyset(&intmask);
53151.97Skamil			sigaddset(&intmask, sigval);
53161.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
53171.97Skamil		}
53181.97Skamil
53191.97Skamil		if (ignored) {
53201.97Skamil			memset(&sa, 0, sizeof(sa));
53211.97Skamil			sa.sa_handler = SIG_IGN;
53221.97Skamil			sigemptyset(&sa.sa_mask);
53231.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
53241.97Skamil		}
53251.97Skamil
53261.13Schristos		DPRINTF("Before calling execve(2) from child\n");
53271.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
53281.1Skamil
53291.1Skamil		FORKEE_ASSERT(0 && "Not reached");
53301.1Skamil	}
53311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53321.1Skamil
53331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53351.1Skamil
53361.1Skamil	validate_status_stopped(status, sigval);
53371.1Skamil
53381.97Skamil	name[0] = CTL_KERN,
53391.97Skamil	name[1] = KERN_PROC2,
53401.97Skamil	name[2] = KERN_PROC_PID;
53411.97Skamil	name[3] = getpid();
53421.97Skamil	name[4] = sizeof(kp);
53431.97Skamil	name[5] = 1;
53441.97Skamil
53451.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53461.97Skamil
53471.97Skamil	if (masked)
53481.97Skamil		kp_sigmask = kp.p_sigmask;
53491.97Skamil
53501.97Skamil	if (ignored)
53511.97Skamil		kp_sigignore = kp.p_sigignore;
53521.97Skamil
53531.97Skamil	name[3] = getpid();
53541.97Skamil
53551.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53561.97Skamil
53571.97Skamil	if (masked) {
53581.97Skamil		DPRINTF("kp_sigmask="
53591.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53601.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
53611.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
53621.97Skamil
53631.97Skamil		DPRINTF("kp.p_sigmask="
53641.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53651.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
53661.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
53671.97Skamil
53681.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
53691.97Skamil		    sizeof(kp_sigmask)));
53701.97Skamil	}
53711.97Skamil
53721.97Skamil	if (ignored) {
53731.97Skamil		DPRINTF("kp_sigignore="
53741.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53751.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
53761.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
53771.97Skamil
53781.97Skamil		DPRINTF("kp.p_sigignore="
53791.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
53801.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
53811.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
53821.97Skamil
53831.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
53841.97Skamil		    sizeof(kp_sigignore)));
53851.97Skamil	}
53861.97Skamil
53871.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53881.61Skre	SYSCALL_REQUIRE(
53891.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53901.1Skamil
53911.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
53921.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
53931.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
53941.1Skamil	    info.psi_siginfo.si_errno);
53951.1Skamil
53961.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
53971.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
53981.1Skamil
53991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54001.1Skamil	    "without signal to be sent\n");
54011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
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.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54081.1Skamil}
54091.1Skamil
54101.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
54111.97SkamilATF_TC(test);								\
54121.97SkamilATF_TC_HEAD(test, tc)							\
54131.97Skamil{									\
54141.97Skamil       atf_tc_set_md_var(tc, "descr",					\
54151.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
54161.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
54171.97Skamil           masked ? " with ignored signal" : "");			\
54181.97Skamil}									\
54191.97Skamil									\
54201.97SkamilATF_TC_BODY(test, tc)							\
54211.97Skamil{									\
54221.97Skamil									\
54231.97Skamil       traceme_exec(masked, ignored);					\
54241.97Skamil}
54251.97Skamil
54261.97SkamilTRACEME_EXEC(traceme_exec, false, false)
54271.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
54281.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
54291.97Skamil
54301.82Skamil/// ----------------------------------------------------------------------------
54311.82Skamil
54321.83Skamilstatic volatile int done;
54331.1Skamil
54341.83Skamilstatic void *
54351.83Skamiltrace_threads_cb(void *arg __unused)
54361.1Skamil{
54371.1Skamil
54381.83Skamil	done++;
54391.83Skamil
54401.83Skamil	while (done < 3)
54411.83Skamil		continue;
54421.83Skamil
54431.83Skamil	return NULL;
54441.1Skamil}
54451.1Skamil
54461.83Skamilstatic void
54471.83Skamiltrace_threads(bool trace_create, bool trace_exit)
54481.1Skamil{
54491.1Skamil	const int sigval = SIGSTOP;
54501.1Skamil	pid_t child, wpid;
54511.1Skamil#if defined(TWAIT_HAVE_STATUS)
54521.1Skamil	int status;
54531.1Skamil#endif
54541.1Skamil	ptrace_state_t state;
54551.1Skamil	const int slen = sizeof(state);
54561.1Skamil	ptrace_event_t event;
54571.1Skamil	const int elen = sizeof(event);
54581.83Skamil	struct ptrace_siginfo info;
54591.83Skamil
54601.83Skamil	pthread_t t[3];
54611.83Skamil	int rv;
54621.83Skamil	size_t n;
54631.1Skamil	lwpid_t lid;
54641.83Skamil
54651.83Skamil	/* Track created and exited threads */
54661.83Skamil	bool traced_lwps[__arraycount(t)];
54671.83Skamil
54681.128Skamil#if !TEST_LWP_ENABLED
54691.120Skamil	if (trace_create || trace_exit)
54701.119Skamil		atf_tc_skip("PR kern/51995");
54711.128Skamil#endif
54721.1Skamil
54731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54751.1Skamil	if (child == 0) {
54761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54781.1Skamil
54791.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54801.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54811.1Skamil
54821.83Skamil		for (n = 0; n < __arraycount(t); n++) {
54831.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
54841.83Skamil			    NULL);
54851.83Skamil			FORKEE_ASSERT(rv == 0);
54861.83Skamil		}
54871.1Skamil
54881.83Skamil		for (n = 0; n < __arraycount(t); n++) {
54891.83Skamil			rv = pthread_join(t[n], NULL);
54901.83Skamil			FORKEE_ASSERT(rv == 0);
54911.83Skamil		}
54921.1Skamil
54931.83Skamil		/*
54941.83Skamil		 * There is race between _exit() and pthread_join() detaching
54951.83Skamil		 * a thread. For simplicity kill the process after detecting
54961.83Skamil		 * LWP events.
54971.83Skamil		 */
54981.83Skamil		while (true)
54991.83Skamil			continue;
55001.1Skamil
55011.83Skamil		FORKEE_ASSERT(0 && "Not reached");
55021.1Skamil	}
55031.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55041.1Skamil
55051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55071.1Skamil
55081.1Skamil	validate_status_stopped(status, sigval);
55091.1Skamil
55101.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55111.83Skamil	SYSCALL_REQUIRE(
55121.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55131.1Skamil
55141.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
55151.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
55161.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
55171.83Skamil	    info.psi_siginfo.si_errno);
55181.1Skamil
55191.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
55201.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
55211.1Skamil
55221.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
55231.83Skamil	memset(&event, 0, sizeof(event));
55241.83Skamil	if (trace_create)
55251.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
55261.83Skamil	if (trace_exit)
55271.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
55281.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
55291.1Skamil
55301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55311.1Skamil	    "without signal to be sent\n");
55321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55331.1Skamil
55341.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
55351.1Skamil
55361.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
55371.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
55381.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
55391.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
55401.83Skamil		    child);
55411.1Skamil
55421.83Skamil		validate_status_stopped(status, SIGTRAP);
55431.1Skamil
55441.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
55451.83Skamil		    "child\n");
55461.83Skamil		SYSCALL_REQUIRE(
55471.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55481.1Skamil
55491.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
55501.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
55511.83Skamil		    "si_errno=%#x\n",
55521.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
55531.83Skamil		    info.psi_siginfo.si_errno);
55541.1Skamil
55551.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55561.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
55571.1Skamil
55581.83Skamil		SYSCALL_REQUIRE(
55591.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55601.1Skamil
55611.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
55621.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
55631.1Skamil
55641.83Skamil		lid = state.pe_lwp;
55651.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
55661.1Skamil
55671.83Skamil		traced_lwps[lid - 1] = true;
55681.1Skamil
55691.83Skamil		DPRINTF("Before resuming the child process where it left off "
55701.83Skamil		    "and without signal to be sent\n");
55711.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55721.83Skamil	}
55731.1Skamil
55741.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
55751.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
55761.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
55771.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
55781.83Skamil		    child);
55791.1Skamil
55801.83Skamil		validate_status_stopped(status, SIGTRAP);
55811.1Skamil
55821.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
55831.83Skamil		    "child\n");
55841.83Skamil		SYSCALL_REQUIRE(
55851.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55861.1Skamil
55871.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
55881.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
55891.83Skamil		    "si_errno=%#x\n",
55901.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
55911.83Skamil		    info.psi_siginfo.si_errno);
55921.1Skamil
55931.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55941.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
55951.1Skamil
55961.83Skamil		SYSCALL_REQUIRE(
55971.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55981.1Skamil
55991.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
56001.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
56011.1Skamil
56021.83Skamil		lid = state.pe_lwp;
56031.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
56041.1Skamil
56051.83Skamil		if (trace_create) {
56061.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
56071.83Skamil			traced_lwps[lid - 1] = false;
56081.83Skamil		}
56091.1Skamil
56101.83Skamil		DPRINTF("Before resuming the child process where it left off "
56111.83Skamil		    "and without signal to be sent\n");
56121.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56131.83Skamil	}
56141.1Skamil
56151.83Skamil	kill(child, SIGKILL);
56161.1Skamil
56171.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
56181.1Skamil	    TWAIT_FNAME);
56191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56201.1Skamil
56211.83Skamil	validate_status_signaled(status, SIGKILL, 0);
56221.1Skamil
56231.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
56241.1Skamil	    TWAIT_FNAME);
56251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56261.1Skamil}
56271.1Skamil
56281.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
56291.83SkamilATF_TC(test);								\
56301.83SkamilATF_TC_HEAD(test, tc)							\
56311.83Skamil{									\
56321.83Skamil        atf_tc_set_md_var(tc, "descr",					\
56331.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
56341.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
56351.83Skamil	    trace_exit ? "" : "out");					\
56361.83Skamil}									\
56371.83Skamil									\
56381.83SkamilATF_TC_BODY(test, tc)							\
56391.83Skamil{									\
56401.83Skamil									\
56411.83Skamil        trace_threads(trace_create, trace_exit);			\
56421.83Skamil}
56431.83Skamil
56441.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false)
56451.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true)
56461.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false)
56471.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true)
56481.83Skamil
56491.83Skamil/// ----------------------------------------------------------------------------
56501.83Skamil
56511.84SkamilATF_TC(signal_mask_unrelated);
56521.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
56531.1Skamil{
56541.1Skamil	atf_tc_set_md_var(tc, "descr",
56551.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
56561.1Skamil	    "from catching other signals");
56571.1Skamil}
56581.1Skamil
56591.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
56601.1Skamil{
56611.1Skamil	const int exitval = 5;
56621.1Skamil	const int sigval = SIGSTOP;
56631.1Skamil	const int sigmasked = SIGTRAP;
56641.1Skamil	const int signotmasked = SIGINT;
56651.1Skamil	pid_t child, wpid;
56661.1Skamil#if defined(TWAIT_HAVE_STATUS)
56671.1Skamil	int status;
56681.1Skamil#endif
56691.1Skamil	sigset_t intmask;
56701.1Skamil
56711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56731.1Skamil	if (child == 0) {
56741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56761.1Skamil
56771.1Skamil		sigemptyset(&intmask);
56781.1Skamil		sigaddset(&intmask, sigmasked);
56791.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56801.1Skamil
56811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56831.1Skamil
56841.13Schristos		DPRINTF("Before raising %s from child\n",
56851.1Skamil		    strsignal(signotmasked));
56861.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
56871.1Skamil
56881.13Schristos		DPRINTF("Before exiting of the child process\n");
56891.1Skamil		_exit(exitval);
56901.1Skamil	}
56911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56921.1Skamil
56931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56951.1Skamil
56961.1Skamil	validate_status_stopped(status, sigval);
56971.1Skamil
56981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56991.1Skamil	    "without signal to be sent\n");
57001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57011.1Skamil
57021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57041.1Skamil
57051.1Skamil	validate_status_stopped(status, signotmasked);
57061.1Skamil
57071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57081.1Skamil	    "without signal to be sent\n");
57091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57101.1Skamil
57111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57131.1Skamil
57141.1Skamil	validate_status_exited(status, exitval);
57151.1Skamil
57161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57181.1Skamil}
57191.1Skamil
57201.84Skamil/// ----------------------------------------------------------------------------
57211.84Skamil
57221.1Skamil#if defined(TWAIT_HAVE_PID)
57231.99Skamilstatic void
57241.126Skamilfork2_body(const char *fn, bool masked, bool ignored)
57251.1Skamil{
57261.1Skamil	const int exitval = 5;
57271.126Skamil	const int exitval2 = 0; /* Match exit status from /bin/echo */
57281.1Skamil	const int sigval = SIGSTOP;
57291.99Skamil	pid_t child, child2 = 0, wpid;
57301.1Skamil#if defined(TWAIT_HAVE_STATUS)
57311.1Skamil	int status;
57321.1Skamil#endif
57331.1Skamil	ptrace_state_t state;
57341.1Skamil	const int slen = sizeof(state);
57351.1Skamil	ptrace_event_t event;
57361.1Skamil	const int elen = sizeof(event);
57371.99Skamil	struct sigaction sa;
57381.99Skamil	struct ptrace_siginfo info;
57391.99Skamil	sigset_t intmask;
57401.99Skamil	struct kinfo_proc2 kp;
57411.99Skamil	size_t len = sizeof(kp);
57421.99Skamil
57431.99Skamil	int name[6];
57441.99Skamil	const size_t namelen = __arraycount(name);
57451.99Skamil	ki_sigset_t kp_sigmask;
57461.99Skamil	ki_sigset_t kp_sigignore;
57471.1Skamil
57481.126Skamil	char * const arg[] = { __UNCONST("/bin/echo"), NULL };
57491.14Schristos
57501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57521.1Skamil	if (child == 0) {
57531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57551.1Skamil
57561.99Skamil		if (masked) {
57571.99Skamil			sigemptyset(&intmask);
57581.99Skamil			sigaddset(&intmask, SIGTRAP);
57591.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
57601.99Skamil		}
57611.99Skamil
57621.99Skamil		if (ignored) {
57631.99Skamil			memset(&sa, 0, sizeof(sa));
57641.99Skamil			sa.sa_handler = SIG_IGN;
57651.99Skamil			sigemptyset(&sa.sa_mask);
57661.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
57671.99Skamil		}
57681.1Skamil
57691.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57701.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57711.1Skamil
57721.126Skamil		if (strcmp(fn, "spawn") == 0) {
57731.126Skamil			FORKEE_ASSERT_EQ(posix_spawn(&child2,
57741.126Skamil			    arg[0], NULL, NULL, arg, NULL), 0);
57751.126Skamil		} else  {
57761.126Skamil			if (strcmp(fn, "fork") == 0) {
57771.126Skamil				FORKEE_ASSERT((child2 = fork()) != -1);
57781.126Skamil			} else {
57791.126Skamil				FORKEE_ASSERT((child2 = vfork()) != -1);
57801.126Skamil			}
57811.126Skamil			if (child2 == 0)
57821.126Skamil				_exit(exitval2);
57831.126Skamil		}
57841.1Skamil
57851.1Skamil		FORKEE_REQUIRE_SUCCESS
57861.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
57871.1Skamil
57881.1Skamil		forkee_status_exited(status, exitval2);
57891.1Skamil
57901.13Schristos		DPRINTF("Before exiting of the child process\n");
57911.1Skamil		_exit(exitval);
57921.1Skamil	}
57931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57941.1Skamil
57951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57971.1Skamil
57981.1Skamil	validate_status_stopped(status, sigval);
57991.1Skamil
58001.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
58011.99Skamil	SYSCALL_REQUIRE(
58021.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
58031.99Skamil
58041.99Skamil	DPRINTF("Before checking siginfo_t\n");
58051.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
58061.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
58071.1Skamil
58081.99Skamil	name[0] = CTL_KERN,
58091.99Skamil	name[1] = KERN_PROC2,
58101.99Skamil	name[2] = KERN_PROC_PID;
58111.99Skamil	name[3] = child;
58121.99Skamil	name[4] = sizeof(kp);
58131.99Skamil	name[5] = 1;
58141.1Skamil
58151.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
58161.1Skamil
58171.99Skamil	if (masked)
58181.99Skamil		kp_sigmask = kp.p_sigmask;
58191.1Skamil
58201.99Skamil	if (ignored)
58211.99Skamil		kp_sigignore = kp.p_sigignore;
58221.1Skamil
58231.126Skamil	DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n",
58241.126Skamil	    strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "",
58251.126Skamil	    strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "",
58261.126Skamil	    strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "",
58271.126Skamil	    strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child);
58281.99Skamil	event.pe_set_event = 0;
58291.126Skamil	if (strcmp(fn, "spawn") == 0)
58301.126Skamil		event.pe_set_event |= PTRACE_POSIX_SPAWN;
58311.126Skamil	if (strcmp(fn, "fork") == 0)
58321.99Skamil		event.pe_set_event |= PTRACE_FORK;
58331.126Skamil	if (strcmp(fn, "vfork") == 0)
58341.99Skamil		event.pe_set_event |= PTRACE_VFORK;
58351.126Skamil	if (strcmp(fn, "vforkdone") == 0)
58361.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
58371.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
58381.1Skamil
58391.99Skamil	DPRINTF("Before resuming the child process where it left off and "
58401.99Skamil	    "without signal to be sent\n");
58411.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58421.1Skamil
58431.126Skamil	if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 ||
58441.126Skamil	    strcmp(fn, "vfork") == 0) {
58451.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
58461.99Skamil		    child);
58471.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
58481.99Skamil		    child);
58491.1Skamil
58501.99Skamil		validate_status_stopped(status, SIGTRAP);
58511.1Skamil
58521.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
58531.1Skamil
58541.99Skamil		if (masked) {
58551.99Skamil			DPRINTF("kp_sigmask="
58561.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58571.99Skamil			    PRIx32 "\n",
58581.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
58591.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
58601.1Skamil
58611.99Skamil			DPRINTF("kp.p_sigmask="
58621.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58631.99Skamil			    PRIx32 "\n",
58641.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
58651.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
58661.1Skamil
58671.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
58681.99Skamil			    sizeof(kp_sigmask)));
58691.99Skamil		}
58701.1Skamil
58711.99Skamil		if (ignored) {
58721.99Skamil			DPRINTF("kp_sigignore="
58731.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58741.99Skamil			    PRIx32 "\n",
58751.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
58761.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
58771.1Skamil
58781.99Skamil			DPRINTF("kp.p_sigignore="
58791.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58801.99Skamil			    PRIx32 "\n",
58811.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
58821.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
58831.1Skamil
58841.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
58851.99Skamil			    sizeof(kp_sigignore)));
58861.99Skamil		}
58871.1Skamil
58881.99Skamil		SYSCALL_REQUIRE(
58891.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
58901.126Skamil		if (strcmp(fn, "spawn") == 0) {
58911.126Skamil			ATF_REQUIRE_EQ(
58921.126Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
58931.126Skamil			       PTRACE_POSIX_SPAWN);
58941.126Skamil		}
58951.126Skamil		if (strcmp(fn, "fork") == 0) {
58961.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
58971.99Skamil			       PTRACE_FORK);
58981.99Skamil		}
58991.126Skamil		if (strcmp(fn, "vfork") == 0) {
59001.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
59011.99Skamil			       PTRACE_VFORK);
59021.99Skamil		}
59031.1Skamil
59041.99Skamil		child2 = state.pe_other_pid;
59051.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
59061.1Skamil
59071.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
59081.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
59091.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59101.99Skamil		    child2);
59111.1Skamil
59121.99Skamil		validate_status_stopped(status, SIGTRAP);
59131.1Skamil
59141.99Skamil		name[3] = child2;
59151.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
59161.1Skamil
59171.99Skamil		if (masked) {
59181.99Skamil			DPRINTF("kp_sigmask="
59191.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59201.99Skamil			    PRIx32 "\n",
59211.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
59221.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
59231.1Skamil
59241.99Skamil			DPRINTF("kp.p_sigmask="
59251.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59261.99Skamil			    PRIx32 "\n",
59271.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
59281.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
59291.14Schristos
59301.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
59311.99Skamil			    sizeof(kp_sigmask)));
59321.99Skamil		}
59331.1Skamil
59341.99Skamil		if (ignored) {
59351.99Skamil			DPRINTF("kp_sigignore="
59361.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59371.99Skamil			    PRIx32 "\n",
59381.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
59391.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
59401.1Skamil
59411.99Skamil			DPRINTF("kp.p_sigignore="
59421.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59431.99Skamil			    PRIx32 "\n",
59441.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
59451.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
59461.1Skamil
59471.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
59481.99Skamil			    sizeof(kp_sigignore)));
59491.99Skamil		}
59501.1Skamil
59511.99Skamil		SYSCALL_REQUIRE(
59521.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
59531.126Skamil		if (strcmp(fn, "spawn") == 0) {
59541.126Skamil			ATF_REQUIRE_EQ(
59551.126Skamil			    state.pe_report_event & PTRACE_POSIX_SPAWN,
59561.126Skamil			       PTRACE_POSIX_SPAWN);
59571.126Skamil		}
59581.126Skamil		if (strcmp(fn, "fork") == 0) {
59591.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
59601.99Skamil			       PTRACE_FORK);
59611.99Skamil		}
59621.126Skamil		if (strcmp(fn, "vfork") == 0) {
59631.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
59641.99Skamil			       PTRACE_VFORK);
59651.99Skamil		}
59661.1Skamil
59671.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
59681.1Skamil
59691.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
59701.99Skamil		    "and without signal to be sent\n");
59711.99Skamil		SYSCALL_REQUIRE(
59721.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
59731.1Skamil
59741.99Skamil		DPRINTF("Before resuming the child process where it left off "
59751.99Skamil		    "and without signal to be sent\n");
59761.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59771.1Skamil	}
59781.1Skamil
59791.126Skamil	if (strcmp(fn, "vforkdone") == 0) {
59801.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
59811.99Skamil		    child);
59821.99Skamil		TWAIT_REQUIRE_SUCCESS(
59831.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
59841.1Skamil
59851.99Skamil		validate_status_stopped(status, SIGTRAP);
59861.1Skamil
59871.99Skamil		name[3] = child;
59881.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
59891.1Skamil
59901.102Skamil		/*
59911.102Skamil		 * SIGCHLD is now pending in the signal queue and
59921.102Skamil		 * the kernel presents it to userland as a masked signal.
59931.102Skamil		 */
59941.102Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
59951.102Skamil
59961.99Skamil		if (masked) {
59971.99Skamil			DPRINTF("kp_sigmask="
59981.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59991.99Skamil			    PRIx32 "\n",
60001.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
60011.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
60021.1Skamil
60031.99Skamil			DPRINTF("kp.p_sigmask="
60041.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
60051.99Skamil			    PRIx32 "\n",
60061.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
60071.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
60081.1Skamil
60091.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
60101.99Skamil			    sizeof(kp_sigmask)));
60111.99Skamil		}
60121.1Skamil
60131.99Skamil		if (ignored) {
60141.99Skamil			DPRINTF("kp_sigignore="
60151.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
60161.99Skamil			    PRIx32 "\n",
60171.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
60181.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
60191.1Skamil
60201.99Skamil			DPRINTF("kp.p_sigignore="
60211.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
60221.99Skamil			    PRIx32 "\n",
60231.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
60241.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
60251.1Skamil
60261.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
60271.99Skamil			    sizeof(kp_sigignore)));
60281.99Skamil		}
60291.1Skamil
60301.99Skamil		SYSCALL_REQUIRE(
60311.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
60321.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
60331.1Skamil
60341.99Skamil		child2 = state.pe_other_pid;
60351.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
60361.99Skamil		    child2);
60371.1Skamil
60381.99Skamil		DPRINTF("Before resuming the child process where it left off "
60391.99Skamil		    "and without signal to be sent\n");
60401.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60411.99Skamil	}
60421.1Skamil
60431.126Skamil	if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 ||
60441.126Skamil	    strcmp(fn, "vfork") == 0) {
60451.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
60461.99Skamil		    "\n", TWAIT_FNAME);
60471.99Skamil		TWAIT_REQUIRE_SUCCESS(
60481.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
60491.1Skamil
60501.99Skamil		validate_status_exited(status, exitval2);
60511.1Skamil
60521.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
60531.99Skamil		    "process\n", TWAIT_FNAME);
60541.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
60551.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
60561.99Skamil	}
60571.1Skamil
60581.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60591.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
60601.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60611.1Skamil
60621.1Skamil	validate_status_stopped(status, SIGCHLD);
60631.1Skamil
60641.57Skamil	DPRINTF("Before resuming the child process where it left off and "
60651.1Skamil	    "without signal to be sent\n");
60661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60671.1Skamil
60681.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60691.1Skamil	    TWAIT_FNAME);
60701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60711.1Skamil
60721.1Skamil	validate_status_exited(status, exitval);
60731.1Skamil
60741.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60751.57Skamil	    TWAIT_FNAME);
60761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60771.1Skamil}
60781.1Skamil
60791.126Skamil#define FORK2_TEST(name,fn,masked,ignored)				\
60801.99SkamilATF_TC(name);								\
60811.99SkamilATF_TC_HEAD(name, tc)							\
60821.99Skamil{									\
60831.126Skamil	atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught "	\
60841.99Skamil	    "regardless of signal %s%s", 				\
60851.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
60861.99Skamil}									\
60871.99Skamil									\
60881.99SkamilATF_TC_BODY(name, tc)							\
60891.99Skamil{									\
60901.99Skamil									\
60911.126Skamil	fork2_body(fn, masked, ignored);				\
60921.1Skamil}
60931.1Skamil
60941.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false)
60951.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true)
60961.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false)
60971.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true)
60981.110Skamil#if TEST_VFORK_ENABLED
60991.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false)
61001.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true)
61011.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false)
61021.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true)
61031.1Skamil#endif
61041.110Skamil#endif
61051.1Skamil
61061.99Skamil/// ----------------------------------------------------------------------------
61071.1Skamil
61081.83Skamilvolatile lwpid_t the_lwp_id = 0;
61091.83Skamil
61101.83Skamilstatic void
61111.83Skamillwp_main_func(void *arg)
61121.83Skamil{
61131.83Skamil	the_lwp_id = _lwp_self();
61141.83Skamil	_lwp_exit();
61151.83Skamil}
61161.83Skamil
61171.1SkamilATF_TC(signal9);
61181.1SkamilATF_TC_HEAD(signal9, tc)
61191.1Skamil{
61201.1Skamil	atf_tc_set_md_var(tc, "descr",
61211.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61221.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
61231.1Skamil}
61241.1Skamil
61251.1SkamilATF_TC_BODY(signal9, tc)
61261.1Skamil{
61271.1Skamil	const int exitval = 5;
61281.1Skamil	const int sigval = SIGSTOP;
61291.1Skamil	const int sigmasked = SIGTRAP;
61301.1Skamil	pid_t child, wpid;
61311.1Skamil#if defined(TWAIT_HAVE_STATUS)
61321.1Skamil	int status;
61331.1Skamil#endif
61341.1Skamil	sigset_t intmask;
61351.1Skamil	ptrace_state_t state;
61361.1Skamil	const int slen = sizeof(state);
61371.1Skamil	ptrace_event_t event;
61381.1Skamil	const int elen = sizeof(event);
61391.1Skamil	ucontext_t uc;
61401.1Skamil	lwpid_t lid;
61411.1Skamil	static const size_t ssize = 16*1024;
61421.1Skamil	void *stack;
61431.1Skamil
61441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61461.1Skamil	if (child == 0) {
61471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61491.1Skamil
61501.1Skamil		sigemptyset(&intmask);
61511.1Skamil		sigaddset(&intmask, sigmasked);
61521.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61531.1Skamil
61541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61561.1Skamil
61571.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
61581.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
61591.1Skamil
61601.13Schristos		DPRINTF("Before making context for new lwp in child\n");
61611.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
61621.1Skamil
61631.13Schristos		DPRINTF("Before creating new in child\n");
61641.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
61651.1Skamil
61661.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
61671.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
61681.1Skamil
61691.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
61701.1Skamil		    "are the same\n", lid, the_lwp_id);
61711.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
61721.1Skamil
61731.13Schristos		DPRINTF("Before exiting of the child process\n");
61741.1Skamil		_exit(exitval);
61751.1Skamil	}
61761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61771.1Skamil
61781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61801.1Skamil
61811.1Skamil	validate_status_stopped(status, sigval);
61821.1Skamil
61831.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
61841.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
61851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
61861.1Skamil
61871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61881.1Skamil	    "without signal to be sent\n");
61891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61901.1Skamil
61911.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61921.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
61931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61941.1Skamil
61951.1Skamil	validate_status_stopped(status, sigmasked);
61961.1Skamil
61971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
61981.1Skamil
61991.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
62001.1Skamil
62011.1Skamil	lid = state.pe_lwp;
62021.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
62031.1Skamil
62041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62051.1Skamil	    "without signal to be sent\n");
62061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62071.1Skamil
62081.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62091.1Skamil	    TWAIT_FNAME);
62101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62111.1Skamil
62121.1Skamil	validate_status_exited(status, exitval);
62131.1Skamil
62141.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62151.1Skamil	    TWAIT_FNAME);
62161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62171.1Skamil}
62181.1Skamil
62191.1SkamilATF_TC(signal10);
62201.1SkamilATF_TC_HEAD(signal10, tc)
62211.1Skamil{
62221.1Skamil	atf_tc_set_md_var(tc, "descr",
62231.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
62241.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
62251.1Skamil}
62261.1Skamil
62271.1SkamilATF_TC_BODY(signal10, tc)
62281.1Skamil{
62291.1Skamil	const int exitval = 5;
62301.1Skamil	const int sigval = SIGSTOP;
62311.1Skamil	const int sigmasked = SIGTRAP;
62321.1Skamil	pid_t child, wpid;
62331.1Skamil#if defined(TWAIT_HAVE_STATUS)
62341.1Skamil	int status;
62351.1Skamil#endif
62361.1Skamil	sigset_t intmask;
62371.1Skamil	ptrace_state_t state;
62381.1Skamil	const int slen = sizeof(state);
62391.1Skamil	ptrace_event_t event;
62401.1Skamil	const int elen = sizeof(event);
62411.1Skamil	ucontext_t uc;
62421.1Skamil	lwpid_t lid;
62431.1Skamil	static const size_t ssize = 16*1024;
62441.1Skamil	void *stack;
62451.1Skamil
62461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62481.1Skamil	if (child == 0) {
62491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62511.1Skamil
62521.1Skamil		sigemptyset(&intmask);
62531.1Skamil		sigaddset(&intmask, sigmasked);
62541.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
62551.1Skamil
62561.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62571.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62581.1Skamil
62591.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62601.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62611.1Skamil
62621.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62631.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
62641.1Skamil
62651.13Schristos		DPRINTF("Before creating new in child\n");
62661.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62671.1Skamil
62681.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62691.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62701.1Skamil
62711.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62721.1Skamil		    "are the same\n", lid, the_lwp_id);
62731.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
62741.1Skamil
62751.13Schristos		DPRINTF("Before exiting of the child process\n");
62761.1Skamil		_exit(exitval);
62771.1Skamil	}
62781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62791.1Skamil
62801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62821.1Skamil
62831.1Skamil	validate_status_stopped(status, sigval);
62841.1Skamil
62851.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
62861.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
62871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62881.1Skamil
62891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62901.1Skamil	    "without signal to be sent\n");
62911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62921.1Skamil
62931.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62941.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
62951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62961.1Skamil
62971.1Skamil	validate_status_stopped(status, sigmasked);
62981.1Skamil
62991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
63001.1Skamil
63011.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
63021.1Skamil
63031.1Skamil	lid = state.pe_lwp;
63041.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
63051.1Skamil
63061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63071.1Skamil	    "without signal to be sent\n");
63081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63091.1Skamil
63101.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63111.1Skamil	    TWAIT_FNAME);
63121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63131.1Skamil
63141.1Skamil	validate_status_exited(status, exitval);
63151.1Skamil
63161.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63171.1Skamil	    TWAIT_FNAME);
63181.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63191.1Skamil}
63201.1Skamil
63211.1Skamilstatic void
63221.1Skamillwp_main_stop(void *arg)
63231.1Skamil{
63241.1Skamil	the_lwp_id = _lwp_self();
63251.1Skamil
63261.1Skamil	raise(SIGTRAP);
63271.1Skamil
63281.1Skamil	_lwp_exit();
63291.1Skamil}
63301.1Skamil
63311.1SkamilATF_TC(suspend1);
63321.1SkamilATF_TC_HEAD(suspend1, tc)
63331.1Skamil{
63341.1Skamil	atf_tc_set_md_var(tc, "descr",
63351.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
63361.1Skamil	    "resumed by a tracee");
63371.1Skamil}
63381.1Skamil
63391.1SkamilATF_TC_BODY(suspend1, tc)
63401.1Skamil{
63411.1Skamil	const int exitval = 5;
63421.1Skamil	const int sigval = SIGSTOP;
63431.1Skamil	pid_t child, wpid;
63441.1Skamil#if defined(TWAIT_HAVE_STATUS)
63451.1Skamil	int status;
63461.1Skamil#endif
63471.1Skamil	ucontext_t uc;
63481.1Skamil	lwpid_t lid;
63491.1Skamil	static const size_t ssize = 16*1024;
63501.1Skamil	void *stack;
63511.1Skamil	struct ptrace_lwpinfo pl;
63521.1Skamil	struct ptrace_siginfo psi;
63531.1Skamil	volatile int go = 0;
63541.1Skamil
63551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63571.1Skamil	if (child == 0) {
63581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63601.1Skamil
63611.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63621.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63631.1Skamil
63641.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63651.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63661.1Skamil
63671.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63681.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
63691.1Skamil
63701.13Schristos		DPRINTF("Before creating new in child\n");
63711.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63721.1Skamil
63731.1Skamil		while (go == 0)
63741.1Skamil			continue;
63751.1Skamil
63761.1Skamil		raise(SIGINT);
63771.1Skamil
63781.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
63791.1Skamil
63801.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
63811.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
63821.1Skamil
63831.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
63841.1Skamil		    "are the same\n", lid, the_lwp_id);
63851.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63861.1Skamil
63871.13Schristos		DPRINTF("Before exiting of the child process\n");
63881.1Skamil		_exit(exitval);
63891.1Skamil	}
63901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63911.1Skamil
63921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63941.1Skamil
63951.1Skamil	validate_status_stopped(status, sigval);
63961.1Skamil
63971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63981.1Skamil	    "without signal to be sent\n");
63991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64001.1Skamil
64011.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64021.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
64031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64041.1Skamil
64051.1Skamil	validate_status_stopped(status, SIGTRAP);
64061.1Skamil
64071.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
64081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
64091.1Skamil
64101.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
64111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
64121.1Skamil
64131.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
64141.1Skamil	    child, getpid());
64151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
64161.1Skamil
64171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64181.1Skamil	    "without signal to be sent\n");
64191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64201.1Skamil
64211.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64221.1Skamil	    "SIGINT\n", TWAIT_FNAME);
64231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64241.1Skamil
64251.1Skamil	validate_status_stopped(status, SIGINT);
64261.1Skamil
64271.1Skamil	pl.pl_lwpid = 0;
64281.1Skamil
64291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
64301.1Skamil	while (pl.pl_lwpid != 0) {
64311.1Skamil
64321.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
64331.1Skamil		switch (pl.pl_lwpid) {
64341.1Skamil		case 1:
64351.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
64361.1Skamil			break;
64371.1Skamil		case 2:
64381.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
64391.1Skamil			break;
64401.1Skamil		}
64411.1Skamil	}
64421.1Skamil
64431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64441.1Skamil	    "without signal to be sent\n");
64451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64461.1Skamil
64471.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
64481.1Skamil	    TWAIT_FNAME);
64491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64501.1Skamil
64511.1Skamil	validate_status_exited(status, exitval);
64521.1Skamil
64531.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64541.1Skamil	    TWAIT_FNAME);
64551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64561.1Skamil}
64571.1Skamil
64581.1SkamilATF_TC(suspend2);
64591.1SkamilATF_TC_HEAD(suspend2, tc)
64601.1Skamil{
64611.1Skamil	atf_tc_set_md_var(tc, "descr",
64621.1Skamil	    "Verify that the while the only thread within a process is "
64631.1Skamil	    "suspended, the whole process cannot be unstopped");
64641.1Skamil}
64651.1Skamil
64661.1SkamilATF_TC_BODY(suspend2, tc)
64671.1Skamil{
64681.1Skamil	const int exitval = 5;
64691.1Skamil	const int sigval = SIGSTOP;
64701.1Skamil	pid_t child, wpid;
64711.1Skamil#if defined(TWAIT_HAVE_STATUS)
64721.1Skamil	int status;
64731.1Skamil#endif
64741.1Skamil	struct ptrace_siginfo psi;
64751.1Skamil
64761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64781.1Skamil	if (child == 0) {
64791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64811.1Skamil
64821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64841.1Skamil
64851.13Schristos		DPRINTF("Before exiting of the child process\n");
64861.1Skamil		_exit(exitval);
64871.1Skamil	}
64881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64891.1Skamil
64901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64921.1Skamil
64931.1Skamil	validate_status_stopped(status, sigval);
64941.1Skamil
64951.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
64961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
64971.1Skamil
64981.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
64991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65001.1Skamil
65011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65021.1Skamil	    "without signal to be sent\n");
65031.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
65041.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
65051.1Skamil
65061.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
65071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
65081.1Skamil
65091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65101.1Skamil	    "without signal to be sent\n");
65111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65121.1Skamil
65131.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65141.1Skamil	    TWAIT_FNAME);
65151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65161.1Skamil
65171.1Skamil	validate_status_exited(status, exitval);
65181.1Skamil
65191.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
65201.1Skamil	    TWAIT_FNAME);
65211.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65221.1Skamil}
65231.1Skamil
65241.1SkamilATF_TC(resume1);
65251.1SkamilATF_TC_HEAD(resume1, tc)
65261.1Skamil{
65271.1Skamil	atf_tc_set_md_var(tc, "descr",
65281.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
65291.1Skamil	    "resumed by the debugger");
65301.1Skamil}
65311.1Skamil
65321.1SkamilATF_TC_BODY(resume1, tc)
65331.1Skamil{
65341.1Skamil	struct msg_fds fds;
65351.1Skamil	const int exitval = 5;
65361.1Skamil	const int sigval = SIGSTOP;
65371.1Skamil	pid_t child, wpid;
65381.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
65391.1Skamil#if defined(TWAIT_HAVE_STATUS)
65401.1Skamil	int status;
65411.1Skamil#endif
65421.1Skamil	ucontext_t uc;
65431.1Skamil	lwpid_t lid;
65441.1Skamil	static const size_t ssize = 16*1024;
65451.1Skamil	void *stack;
65461.1Skamil	struct ptrace_lwpinfo pl;
65471.1Skamil	struct ptrace_siginfo psi;
65481.1Skamil
65491.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
65501.1Skamil
65511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
65521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
65531.1Skamil	if (child == 0) {
65541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65561.1Skamil
65571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65591.1Skamil
65601.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
65611.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
65621.1Skamil
65631.13Schristos		DPRINTF("Before making context for new lwp in child\n");
65641.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
65651.1Skamil
65661.13Schristos		DPRINTF("Before creating new in child\n");
65671.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
65681.1Skamil
65691.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
65701.1Skamil
65711.1Skamil		raise(SIGINT);
65721.1Skamil
65731.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
65741.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
65751.1Skamil
65761.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
65771.1Skamil		    "are the same\n", lid, the_lwp_id);
65781.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
65791.1Skamil
65801.13Schristos		DPRINTF("Before exiting of the child process\n");
65811.1Skamil		_exit(exitval);
65821.1Skamil	}
65831.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65841.1Skamil
65851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65871.1Skamil
65881.1Skamil	validate_status_stopped(status, sigval);
65891.1Skamil
65901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65911.1Skamil	    "without signal to be sent\n");
65921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65931.1Skamil
65941.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65951.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
65961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65971.1Skamil
65981.1Skamil	validate_status_stopped(status, SIGTRAP);
65991.1Skamil
66001.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
66011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
66021.1Skamil
66031.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
66041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
66051.1Skamil
66061.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
66071.1Skamil
66081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66091.1Skamil	    "without signal to be sent\n");
66101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66111.1Skamil
66121.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
66131.1Skamil	    "SIGINT\n", TWAIT_FNAME);
66141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66151.1Skamil
66161.1Skamil	validate_status_stopped(status, SIGINT);
66171.1Skamil
66181.1Skamil	pl.pl_lwpid = 0;
66191.1Skamil
66201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
66211.1Skamil	while (pl.pl_lwpid != 0) {
66221.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
66231.1Skamil		switch (pl.pl_lwpid) {
66241.1Skamil		case 1:
66251.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
66261.1Skamil			break;
66271.1Skamil		case 2:
66281.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
66291.1Skamil			break;
66301.1Skamil		}
66311.1Skamil	}
66321.1Skamil
66331.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
66341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
66351.1Skamil
66361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66371.1Skamil	    "without signal to be sent\n");
66381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66391.1Skamil
66401.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
66411.1Skamil	    TWAIT_FNAME);
66421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66431.1Skamil
66441.1Skamil	validate_status_exited(status, exitval);
66451.1Skamil
66461.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66471.1Skamil	    TWAIT_FNAME);
66481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66491.1Skamil
66501.1Skamil	msg_close(&fds);
66511.1Skamil}
66521.1Skamil
66531.1SkamilATF_TC(syscall1);
66541.1SkamilATF_TC_HEAD(syscall1, tc)
66551.1Skamil{
66561.1Skamil	atf_tc_set_md_var(tc, "descr",
66571.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
66581.1Skamil}
66591.1Skamil
66601.1SkamilATF_TC_BODY(syscall1, tc)
66611.1Skamil{
66621.1Skamil	const int exitval = 5;
66631.1Skamil	const int sigval = SIGSTOP;
66641.1Skamil	pid_t child, wpid;
66651.1Skamil#if defined(TWAIT_HAVE_STATUS)
66661.1Skamil	int status;
66671.1Skamil#endif
66681.1Skamil	struct ptrace_siginfo info;
66691.1Skamil	memset(&info, 0, sizeof(info));
66701.1Skamil
66711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66731.1Skamil	if (child == 0) {
66741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66761.1Skamil
66771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66791.1Skamil
66801.1Skamil		syscall(SYS_getpid);
66811.1Skamil
66821.13Schristos		DPRINTF("Before exiting of the child process\n");
66831.1Skamil		_exit(exitval);
66841.1Skamil	}
66851.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66861.1Skamil
66871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66891.1Skamil
66901.1Skamil	validate_status_stopped(status, sigval);
66911.1Skamil
66921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66931.1Skamil	    "without signal to be sent\n");
66941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
66951.1Skamil
66961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66981.1Skamil
66991.1Skamil	validate_status_stopped(status, SIGTRAP);
67001.1Skamil
67011.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
67021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
67031.1Skamil
67041.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
67051.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
67061.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
67071.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
67081.1Skamil
67091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67101.1Skamil	    "without signal to be sent\n");
67111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67121.1Skamil
67131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67151.1Skamil
67161.1Skamil	validate_status_stopped(status, SIGTRAP);
67171.1Skamil
67181.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
67191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
67201.1Skamil
67211.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
67221.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
67231.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
67241.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
67251.1Skamil
67261.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67271.1Skamil	    "without signal to be sent\n");
67281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67291.1Skamil
67301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67321.1Skamil
67331.1Skamil	validate_status_exited(status, exitval);
67341.1Skamil
67351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67371.1Skamil}
67381.1Skamil
67391.1SkamilATF_TC(syscallemu1);
67401.1SkamilATF_TC_HEAD(syscallemu1, tc)
67411.1Skamil{
67421.1Skamil	atf_tc_set_md_var(tc, "descr",
67431.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
67441.1Skamil}
67451.1Skamil
67461.1SkamilATF_TC_BODY(syscallemu1, tc)
67471.1Skamil{
67481.1Skamil	const int exitval = 5;
67491.1Skamil	const int sigval = SIGSTOP;
67501.1Skamil	pid_t child, wpid;
67511.1Skamil#if defined(TWAIT_HAVE_STATUS)
67521.1Skamil	int status;
67531.1Skamil#endif
67541.1Skamil
67551.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
67561.6Skamil	/* syscallemu does not work on sparc (32-bit) */
67571.6Skamil	atf_tc_expect_fail("PR kern/52166");
67581.6Skamil#endif
67591.6Skamil
67601.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67611.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67621.1Skamil	if (child == 0) {
67631.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67641.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67651.1Skamil
67661.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67671.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67681.1Skamil
67691.1Skamil		syscall(SYS_exit, 100);
67701.1Skamil
67711.13Schristos		DPRINTF("Before exiting of the child process\n");
67721.1Skamil		_exit(exitval);
67731.1Skamil	}
67741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67751.1Skamil
67761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67781.1Skamil
67791.1Skamil	validate_status_stopped(status, sigval);
67801.1Skamil
67811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67821.1Skamil	    "without signal to be sent\n");
67831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67841.1Skamil
67851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67871.1Skamil
67881.1Skamil	validate_status_stopped(status, SIGTRAP);
67891.1Skamil
67901.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
67911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
67921.1Skamil
67931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67941.1Skamil	    "without signal to be sent\n");
67951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67961.1Skamil
67971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67991.1Skamil
68001.1Skamil	validate_status_stopped(status, SIGTRAP);
68011.1Skamil
68021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68031.1Skamil	    "without signal to be sent\n");
68041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68051.1Skamil
68061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68081.1Skamil
68091.1Skamil	validate_status_exited(status, exitval);
68101.1Skamil
68111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68131.1Skamil}
68141.1Skamil
68151.103Skamil/// ----------------------------------------------------------------------------
68161.103Skamil
68171.106Skamilstatic void
68181.106Skamilclone_body(int flags, bool trackfork, bool trackvfork,
68191.106Skamil    bool trackvforkdone)
68201.106Skamil{
68211.106Skamil	const int exitval = 5;
68221.106Skamil	const int exitval2 = 15;
68231.106Skamil	const int sigval = SIGSTOP;
68241.106Skamil	pid_t child, child2 = 0, wpid;
68251.106Skamil#if defined(TWAIT_HAVE_STATUS)
68261.106Skamil	int status;
68271.106Skamil#endif
68281.106Skamil	ptrace_state_t state;
68291.106Skamil	const int slen = sizeof(state);
68301.106Skamil	ptrace_event_t event;
68311.106Skamil	const int elen = sizeof(event);
68321.106Skamil
68331.106Skamil	const size_t stack_size = 1024 * 1024;
68341.106Skamil	void *stack, *stack_base;
68351.106Skamil
68361.106Skamil	stack = malloc(stack_size);
68371.106Skamil	ATF_REQUIRE(stack != NULL);
68381.106Skamil
68391.106Skamil#ifdef __MACHINE_STACK_GROWS_UP
68401.106Skamil	stack_base = stack;
68411.106Skamil#else
68421.106Skamil	stack_base = (char *)stack + stack_size;
68431.106Skamil#endif
68441.106Skamil
68451.106Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
68461.106Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
68471.106Skamil	if (child == 0) {
68481.106Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68491.106Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68501.106Skamil
68511.106Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68521.106Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68531.106Skamil
68541.106Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
68551.106Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
68561.106Skamil
68571.106Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
68581.106Skamil		    child2);
68591.106Skamil
68601.106Skamil		// XXX WALLSIG?
68611.106Skamil		FORKEE_REQUIRE_SUCCESS
68621.106Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
68631.106Skamil
68641.106Skamil		forkee_status_exited(status, exitval2);
68651.106Skamil
68661.106Skamil		DPRINTF("Before exiting of the child process\n");
68671.106Skamil		_exit(exitval);
68681.106Skamil	}
68691.106Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
68701.106Skamil
68711.106Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68721.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68731.106Skamil
68741.106Skamil	validate_status_stopped(status, sigval);
68751.106Skamil
68761.106Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
68771.106Skamil	    trackfork ? "|PTRACE_FORK" : "",
68781.106Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
68791.106Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
68801.106Skamil	event.pe_set_event = 0;
68811.106Skamil	if (trackfork)
68821.106Skamil		event.pe_set_event |= PTRACE_FORK;
68831.106Skamil	if (trackvfork)
68841.106Skamil		event.pe_set_event |= PTRACE_VFORK;
68851.106Skamil	if (trackvforkdone)
68861.106Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
68871.106Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
68881.106Skamil
68891.106Skamil	DPRINTF("Before resuming the child process where it left off and "
68901.106Skamil	    "without signal to be sent\n");
68911.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68921.106Skamil
68931.106Skamil#if defined(TWAIT_HAVE_PID)
68941.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
68951.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
68961.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
68971.106Skamil		    child);
68981.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
68991.106Skamil		    child);
69001.106Skamil
69011.106Skamil		validate_status_stopped(status, SIGTRAP);
69021.106Skamil
69031.106Skamil		SYSCALL_REQUIRE(
69041.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
69051.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
69061.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
69071.106Skamil			       PTRACE_FORK);
69081.106Skamil		}
69091.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
69101.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
69111.106Skamil			       PTRACE_VFORK);
69121.106Skamil		}
69131.106Skamil
69141.106Skamil		child2 = state.pe_other_pid;
69151.106Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
69161.106Skamil
69171.106Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
69181.106Skamil		    "%d\n", TWAIT_FNAME, child2, child);
69191.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
69201.106Skamil		    child2);
69211.106Skamil
69221.106Skamil		validate_status_stopped(status, SIGTRAP);
69231.106Skamil
69241.106Skamil		SYSCALL_REQUIRE(
69251.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
69261.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
69271.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
69281.106Skamil			       PTRACE_FORK);
69291.106Skamil		}
69301.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
69311.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
69321.106Skamil			       PTRACE_VFORK);
69331.106Skamil		}
69341.106Skamil
69351.106Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
69361.106Skamil
69371.106Skamil		DPRINTF("Before resuming the forkee process where it left off "
69381.106Skamil		    "and without signal to be sent\n");
69391.106Skamil		SYSCALL_REQUIRE(
69401.106Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
69411.106Skamil
69421.106Skamil		DPRINTF("Before resuming the child process where it left off "
69431.106Skamil		    "and without signal to be sent\n");
69441.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69451.106Skamil	}
69461.106Skamil#endif
69471.106Skamil
69481.106Skamil	if (trackvforkdone && (flags & CLONE_VFORK)) {
69491.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
69501.106Skamil		    child);
69511.106Skamil		TWAIT_REQUIRE_SUCCESS(
69521.106Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
69531.106Skamil
69541.106Skamil		validate_status_stopped(status, SIGTRAP);
69551.106Skamil
69561.106Skamil		SYSCALL_REQUIRE(
69571.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
69581.106Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
69591.106Skamil
69601.106Skamil		child2 = state.pe_other_pid;
69611.106Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
69621.106Skamil		    child2);
69631.106Skamil
69641.106Skamil		DPRINTF("Before resuming the child process where it left off "
69651.106Skamil		    "and without signal to be sent\n");
69661.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69671.106Skamil	}
69681.106Skamil
69691.103Skamil#if defined(TWAIT_HAVE_PID)
69701.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
69711.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
69721.106Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
69731.106Skamil		    "\n", TWAIT_FNAME);
69741.106Skamil		TWAIT_REQUIRE_SUCCESS(
69751.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
69761.106Skamil
69771.106Skamil		validate_status_exited(status, exitval2);
69781.106Skamil
69791.106Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
69801.106Skamil		    "process\n", TWAIT_FNAME);
69811.106Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
69821.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
69831.106Skamil	}
69841.106Skamil#endif
69851.106Skamil
69861.106Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
69871.106Skamil	    "SIGCHLD\n", TWAIT_FNAME);
69881.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69891.106Skamil
69901.106Skamil	validate_status_stopped(status, SIGCHLD);
69911.106Skamil
69921.106Skamil	DPRINTF("Before resuming the child process where it left off and "
69931.106Skamil	    "without signal to be sent\n");
69941.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69951.106Skamil
69961.106Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
69971.106Skamil	    TWAIT_FNAME);
69981.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69991.106Skamil
70001.106Skamil	validate_status_exited(status, exitval);
70011.103Skamil
70021.106Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
70031.106Skamil	    TWAIT_FNAME);
70041.106Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
70051.106Skamil}
70061.103Skamil
70071.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone)			\
70081.106SkamilATF_TC(name);								\
70091.106SkamilATF_TC_HEAD(name, tc)							\
70101.106Skamil{									\
70111.106Skamil	atf_tc_set_md_var(tc, "descr", "Verify clone(%s) "		\
70121.106Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
70131.106Skamil	    #flags,							\
70141.106Skamil	    tfork ? "|PTRACE_FORK" : "",				\
70151.106Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
70161.106Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
70171.106Skamil}									\
70181.106Skamil									\
70191.106SkamilATF_TC_BODY(name, tc)							\
70201.106Skamil{									\
70211.106Skamil									\
70221.106Skamil	clone_body(flags, tfork, tvfork, tvforkdone);			\
70231.103Skamil}
70241.103Skamil
70251.106SkamilCLONE_TEST(clone1, 0, false, false, false)
70261.106Skamil#if defined(TWAIT_HAVE_PID)
70271.106SkamilCLONE_TEST(clone2, 0, true, false, false)
70281.106SkamilCLONE_TEST(clone3, 0, false, true, false)
70291.106SkamilCLONE_TEST(clone4, 0, true, true, false)
70301.106Skamil#endif
70311.106SkamilCLONE_TEST(clone5, 0, false, false, true)
70321.106Skamil#if defined(TWAIT_HAVE_PID)
70331.106SkamilCLONE_TEST(clone6, 0, true, false, true)
70341.106SkamilCLONE_TEST(clone7, 0, false, true, true)
70351.106SkamilCLONE_TEST(clone8, 0, true, true, true)
70361.106Skamil#endif
70371.106Skamil
70381.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false)
70391.106Skamil#if defined(TWAIT_HAVE_PID)
70401.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false)
70411.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false)
70421.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false)
70431.106Skamil#endif
70441.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true)
70451.106Skamil#if defined(TWAIT_HAVE_PID)
70461.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true)
70471.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true)
70481.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true)
70491.106Skamil#endif
70501.106Skamil
70511.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false)
70521.106Skamil#if defined(TWAIT_HAVE_PID)
70531.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false)
70541.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false)
70551.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false)
70561.106Skamil#endif
70571.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true)
70581.106Skamil#if defined(TWAIT_HAVE_PID)
70591.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true)
70601.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true)
70611.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true)
70621.106Skamil#endif
70631.106Skamil
70641.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false)
70651.106Skamil#if defined(TWAIT_HAVE_PID)
70661.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false)
70671.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false)
70681.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false)
70691.106Skamil#endif
70701.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true)
70711.106Skamil#if defined(TWAIT_HAVE_PID)
70721.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true)
70731.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true)
70741.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true)
70751.106Skamil#endif
70761.106Skamil
70771.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false)
70781.106Skamil#if defined(TWAIT_HAVE_PID)
70791.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false)
70801.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false)
70811.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false)
70821.106Skamil#endif
70831.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true)
70841.106Skamil#if defined(TWAIT_HAVE_PID)
70851.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true)
70861.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true)
70871.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true)
70881.106Skamil#endif
70891.106Skamil
70901.110Skamil#if TEST_VFORK_ENABLED
70911.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false)
70921.106Skamil#if defined(TWAIT_HAVE_PID)
70931.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false)
70941.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false)
70951.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false)
70961.106Skamil#endif
70971.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true)
70981.106Skamil#if defined(TWAIT_HAVE_PID)
70991.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true)
71001.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true)
71011.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true)
71021.106Skamil#endif
71031.110Skamil#endif
71041.106Skamil
71051.106Skamil/// ----------------------------------------------------------------------------
71061.106Skamil
71071.106Skamil#if defined(TWAIT_HAVE_PID)
71081.103Skamilstatic void
71091.106Skamilclone_body2(int flags, bool masked, bool ignored)
71101.103Skamil{
71111.103Skamil	const int exitval = 5;
71121.103Skamil	const int exitval2 = 15;
71131.103Skamil	const int sigval = SIGSTOP;
71141.103Skamil	pid_t child, child2 = 0, wpid;
71151.103Skamil#if defined(TWAIT_HAVE_STATUS)
71161.103Skamil	int status;
71171.103Skamil#endif
71181.103Skamil	ptrace_state_t state;
71191.103Skamil	const int slen = sizeof(state);
71201.103Skamil	ptrace_event_t event;
71211.103Skamil	const int elen = sizeof(event);
71221.103Skamil	struct sigaction sa;
71231.103Skamil	struct ptrace_siginfo info;
71241.103Skamil	sigset_t intmask;
71251.103Skamil	struct kinfo_proc2 kp;
71261.103Skamil	size_t len = sizeof(kp);
71271.103Skamil
71281.103Skamil	int name[6];
71291.103Skamil	const size_t namelen = __arraycount(name);
71301.103Skamil	ki_sigset_t kp_sigmask;
71311.103Skamil	ki_sigset_t kp_sigignore;
71321.103Skamil
71331.103Skamil	const size_t stack_size = 1024 * 1024;
71341.103Skamil	void *stack, *stack_base;
71351.103Skamil
71361.103Skamil	stack = malloc(stack_size);
71371.103Skamil	ATF_REQUIRE(stack != NULL);
71381.103Skamil
71391.103Skamil#ifdef __MACHINE_STACK_GROWS_UP
71401.103Skamil	stack_base = stack;
71411.103Skamil#else
71421.103Skamil	stack_base = (char *)stack + stack_size;
71431.103Skamil#endif
71441.103Skamil
71451.103Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
71461.103Skamil	if (child == 0) {
71471.103Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
71481.103Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
71491.103Skamil
71501.103Skamil		if (masked) {
71511.103Skamil			sigemptyset(&intmask);
71521.103Skamil			sigaddset(&intmask, SIGTRAP);
71531.103Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
71541.103Skamil		}
71551.103Skamil
71561.103Skamil		if (ignored) {
71571.103Skamil			memset(&sa, 0, sizeof(sa));
71581.103Skamil			sa.sa_handler = SIG_IGN;
71591.103Skamil			sigemptyset(&sa.sa_mask);
71601.103Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
71611.103Skamil		}
71621.103Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
71631.103Skamil		FORKEE_ASSERT(raise(sigval) == 0);
71641.103Skamil
71651.103Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
71661.103Skamil		    flags);
71671.103Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
71681.103Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
71691.103Skamil
71701.103Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
71711.103Skamil		    child2);
71721.103Skamil
71731.103Skamil		// XXX WALLSIG?
71741.103Skamil		FORKEE_REQUIRE_SUCCESS
71751.103Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
71761.103Skamil
71771.103Skamil		forkee_status_exited(status, exitval2);
71781.103Skamil
71791.103Skamil		DPRINTF("Before exiting of the child process\n");
71801.103Skamil		_exit(exitval);
71811.103Skamil	}
71821.103Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
71831.103Skamil
71841.103Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
71851.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
71861.103Skamil
71871.103Skamil	validate_status_stopped(status, sigval);
71881.103Skamil
71891.103Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
71901.103Skamil	SYSCALL_REQUIRE(
71911.103Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
71921.103Skamil
71931.103Skamil	DPRINTF("Before checking siginfo_t\n");
71941.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
71951.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
71961.103Skamil
71971.103Skamil	name[0] = CTL_KERN,
71981.103Skamil	name[1] = KERN_PROC2,
71991.103Skamil	name[2] = KERN_PROC_PID;
72001.103Skamil	name[3] = child;
72011.103Skamil	name[4] = sizeof(kp);
72021.103Skamil	name[5] = 1;
72031.103Skamil
72041.103Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
72051.103Skamil
72061.103Skamil	if (masked)
72071.103Skamil		kp_sigmask = kp.p_sigmask;
72081.103Skamil
72091.103Skamil	if (ignored)
72101.103Skamil		kp_sigignore = kp.p_sigignore;
72111.103Skamil
72121.103Skamil	DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in "
72131.103Skamil	    "EVENT_MASK for the child %d\n", child);
72141.103Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
72151.103Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
72161.103Skamil
72171.103Skamil	DPRINTF("Before resuming the child process where it left off and "
72181.103Skamil	    "without signal to be sent\n");
72191.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
72201.103Skamil
72211.103Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
72221.103Skamil	    child);
72231.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
72241.103Skamil	    child);
72251.103Skamil
72261.103Skamil	validate_status_stopped(status, SIGTRAP);
72271.103Skamil
72281.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
72291.103Skamil
72301.103Skamil	if (masked) {
72311.103Skamil		DPRINTF("kp_sigmask="
72321.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72331.103Skamil		    PRIx32 "\n",
72341.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
72351.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
72361.103Skamil
72371.103Skamil		DPRINTF("kp.p_sigmask="
72381.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72391.103Skamil		    PRIx32 "\n",
72401.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
72411.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
72421.103Skamil
72431.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
72441.103Skamil		    sizeof(kp_sigmask)));
72451.103Skamil	}
72461.103Skamil
72471.103Skamil	if (ignored) {
72481.103Skamil		DPRINTF("kp_sigignore="
72491.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72501.103Skamil		    PRIx32 "\n",
72511.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
72521.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
72531.103Skamil
72541.103Skamil		DPRINTF("kp.p_sigignore="
72551.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72561.103Skamil		    PRIx32 "\n",
72571.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
72581.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
72591.103Skamil
72601.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
72611.103Skamil		    sizeof(kp_sigignore)));
72621.103Skamil	}
72631.103Skamil
72641.103Skamil	SYSCALL_REQUIRE(
72651.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
72661.103Skamil	DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event,
72671.103Skamil	    child2);
72681.103Skamil	if (!(flags & CLONE_VFORK)) {
72691.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
72701.103Skamil		       PTRACE_FORK);
72711.103Skamil	} else {
72721.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
72731.103Skamil		       PTRACE_VFORK);
72741.103Skamil	}
72751.103Skamil
72761.103Skamil	child2 = state.pe_other_pid;
72771.103Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
72781.103Skamil
72791.103Skamil	DPRINTF("Before calling %s() for the forkee %d of the child "
72801.103Skamil	    "%d\n", TWAIT_FNAME, child2, child);
72811.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
72821.103Skamil	    child2);
72831.103Skamil
72841.103Skamil	validate_status_stopped(status, SIGTRAP);
72851.103Skamil
72861.103Skamil	name[3] = child2;
72871.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
72881.103Skamil
72891.103Skamil	if (masked) {
72901.103Skamil		DPRINTF("kp_sigmask="
72911.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72921.103Skamil		    PRIx32 "\n",
72931.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
72941.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
72951.103Skamil
72961.103Skamil		DPRINTF("kp.p_sigmask="
72971.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72981.103Skamil		    PRIx32 "\n",
72991.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
73001.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
73011.103Skamil
73021.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
73031.103Skamil		    sizeof(kp_sigmask)));
73041.103Skamil	}
73051.103Skamil
73061.103Skamil	if (ignored) {
73071.103Skamil		DPRINTF("kp_sigignore="
73081.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73091.103Skamil		    PRIx32 "\n",
73101.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
73111.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
73121.103Skamil
73131.103Skamil		DPRINTF("kp.p_sigignore="
73141.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73151.103Skamil		    PRIx32 "\n",
73161.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
73171.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
73181.103Skamil
73191.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
73201.103Skamil		    sizeof(kp_sigignore)));
73211.103Skamil	}
73221.103Skamil
73231.103Skamil	SYSCALL_REQUIRE(
73241.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
73251.103Skamil	if (!(flags & CLONE_VFORK)) {
73261.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
73271.103Skamil		       PTRACE_FORK);
73281.103Skamil	} else {
73291.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
73301.103Skamil		       PTRACE_VFORK);
73311.103Skamil	}
73321.103Skamil
73331.103Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
73341.103Skamil
73351.103Skamil	DPRINTF("Before resuming the forkee process where it left off "
73361.103Skamil	    "and without signal to be sent\n");
73371.103Skamil	SYSCALL_REQUIRE(
73381.103Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
73391.103Skamil
73401.103Skamil	DPRINTF("Before resuming the child process where it left off "
73411.103Skamil	    "and without signal to be sent\n");
73421.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
73431.103Skamil
73441.103Skamil	if (flags & CLONE_VFORK) {
73451.103Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
73461.103Skamil		    child);
73471.103Skamil		TWAIT_REQUIRE_SUCCESS(
73481.103Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
73491.103Skamil
73501.103Skamil		validate_status_stopped(status, SIGTRAP);
73511.103Skamil
73521.103Skamil		name[3] = child;
73531.103Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
73541.103Skamil
73551.103Skamil		/*
73561.103Skamil		 * SIGCHLD is now pending in the signal queue and
73571.103Skamil		 * the kernel presents it to userland as a masked signal.
73581.103Skamil		 */
73591.103Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
73601.103Skamil
73611.103Skamil		if (masked) {
73621.103Skamil			DPRINTF("kp_sigmask="
73631.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73641.103Skamil			    PRIx32 "\n",
73651.103Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
73661.103Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
73671.103Skamil
73681.103Skamil			DPRINTF("kp.p_sigmask="
73691.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73701.103Skamil			    PRIx32 "\n",
73711.103Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
73721.103Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
73731.103Skamil
73741.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
73751.103Skamil			    sizeof(kp_sigmask)));
73761.103Skamil		}
73771.103Skamil
73781.103Skamil		if (ignored) {
73791.103Skamil			DPRINTF("kp_sigignore="
73801.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73811.103Skamil			    PRIx32 "\n",
73821.103Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
73831.103Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
73841.103Skamil
73851.103Skamil			DPRINTF("kp.p_sigignore="
73861.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
73871.103Skamil			    PRIx32 "\n",
73881.103Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
73891.103Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
73901.103Skamil
73911.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
73921.103Skamil			    sizeof(kp_sigignore)));
73931.103Skamil		}
73941.103Skamil
73951.103Skamil		SYSCALL_REQUIRE(
73961.103Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
73971.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
73981.103Skamil
73991.103Skamil		child2 = state.pe_other_pid;
74001.103Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
74011.103Skamil		    child2);
74021.103Skamil
74031.103Skamil		DPRINTF("Before resuming the child process where it left off "
74041.103Skamil		    "and without signal to be sent\n");
74051.103Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
74061.103Skamil	}
74071.103Skamil
74081.103Skamil	DPRINTF("Before calling %s() for the forkee - expected exited"
74091.103Skamil	    "\n", TWAIT_FNAME);
74101.103Skamil	TWAIT_REQUIRE_SUCCESS(
74111.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
74121.103Skamil
74131.103Skamil	validate_status_exited(status, exitval2);
74141.103Skamil
74151.103Skamil	DPRINTF("Before calling %s() for the forkee - expected no "
74161.103Skamil	    "process\n", TWAIT_FNAME);
74171.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
74181.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
74191.103Skamil
74201.103Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
74211.103Skamil	    "SIGCHLD\n", TWAIT_FNAME);
74221.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
74231.103Skamil
74241.103Skamil	validate_status_stopped(status, SIGCHLD);
74251.103Skamil
74261.103Skamil	DPRINTF("Before resuming the child process where it left off and "
74271.103Skamil	    "without signal to be sent\n");
74281.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
74291.103Skamil
74301.103Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
74311.103Skamil	    TWAIT_FNAME);
74321.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
74331.103Skamil
74341.103Skamil	validate_status_exited(status, exitval);
74351.103Skamil
74361.103Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
74371.103Skamil	    TWAIT_FNAME);
74381.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
74391.103Skamil}
74401.103Skamil
74411.106Skamil#define CLONE_TEST2(name,flags,masked,ignored)				\
74421.103SkamilATF_TC(name);								\
74431.103SkamilATF_TC_HEAD(name, tc)							\
74441.103Skamil{									\
74451.103Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\
74461.103Skamil	    " regardless of signal %s%s", 				\
74471.103Skamil	    #flags, masked ? "masked" : "", ignored ? "ignored" : "");	\
74481.103Skamil}									\
74491.103Skamil									\
74501.103SkamilATF_TC_BODY(name, tc)							\
74511.103Skamil{									\
74521.103Skamil									\
74531.106Skamil	clone_body2(flags, masked, ignored);				\
74541.103Skamil}
74551.103Skamil
74561.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false)
74571.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true)
74581.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false)
74591.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true)
74601.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false)
74611.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true)
74621.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false)
74631.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true)
74641.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX
74651.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true)  // XXX
74661.110Skamil#if TEST_VFORK_ENABLED
74671.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false)
74681.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true)
74691.103Skamil#endif
74701.110Skamil#endif
74711.103Skamil
74721.103Skamil/// ----------------------------------------------------------------------------
74731.103Skamil
74741.111Skamil#if TEST_VFORK_ENABLED
74751.107Skamil#if defined(TWAIT_HAVE_PID)
74761.107Skamilstatic void
74771.107Skamiltraceme_vfork_clone_body(int flags)
74781.107Skamil{
74791.107Skamil	const int exitval = 5;
74801.107Skamil	const int exitval2 = 15;
74811.107Skamil	pid_t child, child2 = 0, wpid;
74821.107Skamil#if defined(TWAIT_HAVE_STATUS)
74831.107Skamil	int status;
74841.107Skamil#endif
74851.107Skamil
74861.107Skamil	const size_t stack_size = 1024 * 1024;
74871.107Skamil	void *stack, *stack_base;
74881.107Skamil
74891.107Skamil	stack = malloc(stack_size);
74901.107Skamil	ATF_REQUIRE(stack != NULL);
74911.107Skamil
74921.107Skamil#ifdef __MACHINE_STACK_GROWS_UP
74931.107Skamil	stack_base = stack;
74941.107Skamil#else
74951.107Skamil	stack_base = (char *)stack + stack_size;
74961.107Skamil#endif
74971.107Skamil
74981.107Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
74991.107Skamil	if (child == 0) {
75001.107Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
75011.107Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
75021.107Skamil
75031.107Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
75041.107Skamil		    flags);
75051.107Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
75061.107Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
75071.107Skamil
75081.107Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
75091.107Skamil		    child2);
75101.107Skamil
75111.107Skamil		// XXX WALLSIG?
75121.107Skamil		FORKEE_REQUIRE_SUCCESS
75131.107Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
75141.107Skamil
75151.107Skamil		forkee_status_exited(status, exitval2);
75161.107Skamil
75171.107Skamil		DPRINTF("Before exiting of the child process\n");
75181.107Skamil		_exit(exitval);
75191.107Skamil	}
75201.107Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
75211.107Skamil
75221.107Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
75231.107Skamil	    TWAIT_FNAME);
75241.107Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
75251.107Skamil
75261.107Skamil	validate_status_exited(status, exitval);
75271.107Skamil
75281.107Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
75291.107Skamil	    TWAIT_FNAME);
75301.107Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
75311.107Skamil}
75321.107Skamil
75331.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags)				\
75341.107SkamilATF_TC(name);								\
75351.107SkamilATF_TC_HEAD(name, tc)							\
75361.107Skamil{									\
75371.107Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is "	\
75381.107Skamil	    "handled correctly with vfork(2)ed tracer", 		\
75391.107Skamil	    #flags);							\
75401.107Skamil}									\
75411.107Skamil									\
75421.107SkamilATF_TC_BODY(name, tc)							\
75431.107Skamil{									\
75441.107Skamil									\
75451.107Skamil	traceme_vfork_clone_body(flags);				\
75461.107Skamil}
75471.107Skamil
75481.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0)
75491.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM)
75501.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS)
75511.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES)
75521.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND)  // XXX
75531.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK)
75541.107Skamil#endif
75551.110Skamil#endif
75561.107Skamil
75571.107Skamil/// ----------------------------------------------------------------------------
75581.107Skamil
75591.122Skamilstatic void
75601.122Skamiluser_va0_disable(int operation)
75611.122Skamil{
75621.122Skamil	pid_t child, wpid;
75631.122Skamil#if defined(TWAIT_HAVE_STATUS)
75641.122Skamil	int status;
75651.122Skamil#endif
75661.122Skamil	const int sigval = SIGSTOP;
75671.122Skamil	int rv;
75681.122Skamil
75691.122Skamil	struct ptrace_siginfo info;
75701.122Skamil
75711.122Skamil	if (get_user_va0_disable() == 0)
75721.122Skamil		atf_tc_skip("vm.user_va0_disable is set to 0");
75731.122Skamil
75741.122Skamil	memset(&info, 0, sizeof(info));
75751.122Skamil
75761.122Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
75771.122Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
75781.122Skamil	if (child == 0) {
75791.122Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
75801.122Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
75811.122Skamil
75821.122Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
75831.122Skamil		FORKEE_ASSERT(raise(sigval) == 0);
75841.122Skamil
75851.122Skamil		/* NOTREACHED */
75861.122Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
75871.122Skamil		__unreachable();
75881.122Skamil	}
75891.122Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
75901.122Skamil
75911.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
75921.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
75931.122Skamil
75941.122Skamil	validate_status_stopped(status, sigval);
75951.122Skamil
75961.122Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
75971.122Skamil		"child\n");
75981.122Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
75991.122Skamil		sizeof(info)) != -1);
76001.122Skamil
76011.122Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
76021.122Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
76031.122Skamil		"si_errno=%#x\n",
76041.122Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
76051.122Skamil		info.psi_siginfo.si_errno);
76061.122Skamil
76071.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
76081.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
76091.122Skamil
76101.122Skamil	DPRINTF("Before resuming the child process in PC=0x0 "
76111.122Skamil	    "and without signal to be sent\n");
76121.122Skamil	errno = 0;
76131.122Skamil	rv = ptrace(operation, child, (void *)0, 0);
76141.122Skamil	ATF_REQUIRE_EQ(errno, EINVAL);
76151.122Skamil	ATF_REQUIRE_EQ(rv, -1);
76161.122Skamil
76171.122Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
76181.122Skamil
76191.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
76201.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
76211.122Skamil	validate_status_signaled(status, SIGKILL, 0);
76221.122Skamil
76231.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
76241.122Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
76251.122Skamil}
76261.122Skamil
76271.122Skamil#define USER_VA0_DISABLE(test, operation)				\
76281.122SkamilATF_TC(test);								\
76291.122SkamilATF_TC_HEAD(test, tc)							\
76301.122Skamil{									\
76311.122Skamil	atf_tc_set_md_var(tc, "descr",					\
76321.122Skamil	    "Verify behavior of " #operation " with PC set to 0x0");	\
76331.122Skamil}									\
76341.122Skamil									\
76351.122SkamilATF_TC_BODY(test, tc)							\
76361.122Skamil{									\
76371.122Skamil									\
76381.122Skamil	user_va0_disable(operation);					\
76391.122Skamil}
76401.122Skamil
76411.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE)
76421.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL)
76431.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH)
76441.122Skamil
76451.122Skamil/// ----------------------------------------------------------------------------
76461.122Skamil
76471.130Smgorny/*
76481.130Smgorny * Parse the core file and find the requested note.  If the reading or parsing
76491.130Smgorny * fails, the test is failed.  If the note is found, it is read onto buf, up to
76501.130Smgorny * buf_len.  The actual length of the note is returned (which can be greater
76511.130Smgorny * than buf_len, indicating that it has been truncated).  If the note is not
76521.130Smgorny * found, -1 is returned.
76531.130Smgorny */
76541.130Smgornystatic ssize_t core_find_note(const char *core_path,
76551.130Smgorny    const char *note_name, uint64_t note_type, void *buf, size_t buf_len)
76561.130Smgorny{
76571.130Smgorny	int core_fd;
76581.130Smgorny	Elf *core_elf;
76591.130Smgorny	size_t core_numhdr, i;
76601.130Smgorny	ssize_t ret = -1;
76611.130Smgorny	/* note: we assume note name will be null-terminated */
76621.130Smgorny	size_t name_len = strlen(note_name) + 1;
76631.130Smgorny
76641.130Smgorny	SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1);
76651.130Smgorny	SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE);
76661.130Smgorny	SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL)));
76671.130Smgorny
76681.130Smgorny	SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0);
76691.130Smgorny	for (i = 0; i < core_numhdr && ret == -1; i++) {
76701.130Smgorny		GElf_Phdr core_hdr;
76711.130Smgorny		size_t offset;
76721.130Smgorny		SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr));
76731.130Smgorny		if (core_hdr.p_type != PT_NOTE)
76741.130Smgorny		    continue;
76751.130Smgorny
76761.130Smgorny		for (offset = core_hdr.p_offset;
76771.130Smgorny		    offset < core_hdr.p_offset + core_hdr.p_filesz;) {
76781.130Smgorny			Elf64_Nhdr note_hdr;
76791.130Smgorny			char name_buf[64];
76801.130Smgorny
76811.130Smgorny			switch (gelf_getclass(core_elf)) {
76821.130Smgorny			case ELFCLASS64:
76831.130Smgorny				SYSCALL_REQUIRE(pread(core_fd, &note_hdr,
76841.130Smgorny				    sizeof(note_hdr), offset)
76851.130Smgorny				    == sizeof(note_hdr));
76861.130Smgorny				offset += sizeof(note_hdr);
76871.130Smgorny				break;
76881.130Smgorny			case ELFCLASS32:
76891.130Smgorny				{
76901.130Smgorny				Elf32_Nhdr tmp_hdr;
76911.130Smgorny				SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr,
76921.130Smgorny				    sizeof(tmp_hdr), offset)
76931.130Smgorny				    == sizeof(tmp_hdr));
76941.130Smgorny				offset += sizeof(tmp_hdr);
76951.130Smgorny				note_hdr.n_namesz = tmp_hdr.n_namesz;
76961.130Smgorny				note_hdr.n_descsz = tmp_hdr.n_descsz;
76971.130Smgorny				note_hdr.n_type = tmp_hdr.n_type;
76981.130Smgorny				}
76991.130Smgorny				break;
77001.130Smgorny			}
77011.130Smgorny
77021.130Smgorny			/* indicates end of notes */
77031.130Smgorny			if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0)
77041.130Smgorny				break;
77051.130Smgorny			if (note_hdr.n_namesz == name_len &&
77061.130Smgorny			    note_hdr.n_namesz <= sizeof(name_buf)) {
77071.130Smgorny				SYSCALL_REQUIRE(pread(core_fd, name_buf,
77081.130Smgorny				    note_hdr.n_namesz, offset)
77091.130Smgorny				    == note_hdr.n_namesz);
77101.130Smgorny
77111.130Smgorny				if (!strncmp(note_name, name_buf, name_len) &&
77121.130Smgorny				    note_hdr.n_type == note_type)
77131.130Smgorny					ret = note_hdr.n_descsz;
77141.130Smgorny			}
77151.130Smgorny
77161.130Smgorny			offset += note_hdr.n_namesz;
77171.130Smgorny			/* fix to alignment */
77181.130Smgorny			offset = ((offset + core_hdr.p_align - 1)
77191.130Smgorny			    / core_hdr.p_align) * core_hdr.p_align;
77201.130Smgorny
77211.130Smgorny			/* if name & type matched above */
77221.130Smgorny			if (ret != -1) {
77231.130Smgorny				ssize_t read_len = MIN(buf_len,
77241.130Smgorny				    note_hdr.n_descsz);
77251.130Smgorny				SYSCALL_REQUIRE(pread(core_fd, buf,
77261.130Smgorny				    read_len, offset) == read_len);
77271.130Smgorny				break;
77281.130Smgorny			}
77291.130Smgorny
77301.130Smgorny			offset += note_hdr.n_descsz;
77311.130Smgorny		}
77321.130Smgorny	}
77331.130Smgorny
77341.130Smgorny	elf_end(core_elf);
77351.130Smgorny	close(core_fd);
77361.130Smgorny
77371.130Smgorny	return ret;
77381.130Smgorny}
77391.130Smgorny
77401.130SmgornyATF_TC(core_dump_procinfo);
77411.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc)
77421.130Smgorny{
77431.130Smgorny	atf_tc_set_md_var(tc, "descr",
77441.130Smgorny		"Trigger a core dump and verify its contents.");
77451.130Smgorny}
77461.130Smgorny
77471.130SmgornyATF_TC_BODY(core_dump_procinfo, tc)
77481.130Smgorny{
77491.130Smgorny	const int exitval = 5;
77501.130Smgorny	pid_t child, wpid;
77511.130Smgorny#if defined(TWAIT_HAVE_STATUS)
77521.130Smgorny	const int sigval = SIGTRAP;
77531.130Smgorny	int status;
77541.130Smgorny#endif
77551.130Smgorny	char core_path[] = "/tmp/core.XXXXXX";
77561.130Smgorny	int core_fd;
77571.130Smgorny	struct netbsd_elfcore_procinfo procinfo;
77581.130Smgorny
77591.130Smgorny	DPRINTF("Before forking process PID=%d\n", getpid());
77601.130Smgorny	SYSCALL_REQUIRE((child = fork()) != -1);
77611.130Smgorny	if (child == 0) {
77621.130Smgorny		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
77631.130Smgorny		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
77641.130Smgorny
77651.130Smgorny		DPRINTF("Before triggering SIGTRAP\n");
77661.130Smgorny		trigger_trap();
77671.130Smgorny
77681.130Smgorny		DPRINTF("Before exiting of the child process\n");
77691.130Smgorny		_exit(exitval);
77701.130Smgorny	}
77711.130Smgorny	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
77721.130Smgorny
77731.130Smgorny	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
77741.130Smgorny	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
77751.130Smgorny
77761.130Smgorny	validate_status_stopped(status, sigval);
77771.130Smgorny
77781.130Smgorny	SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1);
77791.130Smgorny	close(core_fd);
77801.130Smgorny
77811.130Smgorny	DPRINTF("Call DUMPCORE for the child process\n");
77821.130Smgorny	SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path))
77831.130Smgorny	    != -1);
77841.130Smgorny
77851.130Smgorny	DPRINTF("Read core file\n");
77861.130Smgorny	ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE",
77871.130Smgorny	    ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)),
77881.130Smgorny	    sizeof(procinfo));
77891.130Smgorny
77901.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_version, 1);
77911.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo));
77921.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP);
77931.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_pid, child);
77941.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_ppid, getpid());
77951.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child));
77961.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child));
77971.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_ruid, getuid());
77981.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_euid, geteuid());
77991.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_rgid, getgid());
78001.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_egid, getegid());
78011.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_nlwps, 1);
78021.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_siglwp, 1);
78031.130Smgorny
78041.130Smgorny	unlink(core_path);
78051.130Smgorny
78061.130Smgorny	DPRINTF("Before resuming the child process where it left off and "
78071.130Smgorny	    "without signal to be sent\n");
78081.130Smgorny	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
78091.130Smgorny
78101.130Smgorny	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
78111.130Smgorny	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
78121.130Smgorny
78131.130Smgorny	validate_status_exited(status, exitval);
78141.130Smgorny
78151.130Smgorny	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
78161.130Smgorny	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
78171.130Smgorny}
78181.130Smgorny
78191.130Smgorny/// ----------------------------------------------------------------------------
78201.130Smgorny
78211.1Skamil#include "t_ptrace_amd64_wait.h"
78221.1Skamil#include "t_ptrace_i386_wait.h"
78231.1Skamil#include "t_ptrace_x86_wait.h"
78241.1Skamil
78251.1SkamilATF_TP_ADD_TCS(tp)
78261.1Skamil{
78271.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
78281.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
78291.33Skamil
78301.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
78311.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
78321.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
78331.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
78341.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
78351.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
78361.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
78371.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
78381.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
78391.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
78401.33Skamil
78411.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
78421.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
78431.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
78441.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
78451.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
78461.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
78471.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
78481.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
78491.87Skamil
78501.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
78511.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
78521.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
78531.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
78541.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
78551.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
78561.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
78571.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
78581.86Skamil
78591.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
78601.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
78611.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
78621.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
78631.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
78641.59Skamil
78651.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
78661.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
78671.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
78681.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
78691.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
78701.88Skamil
78711.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
78721.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
78731.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
78741.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
78751.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
78761.88Skamil
78771.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
78781.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
78791.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
78801.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
78811.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
78821.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
78831.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
78841.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
78851.50Skamil
78861.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
78871.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
78881.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
78891.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
78901.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
78911.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
78921.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
78931.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
78941.50Skamil
78951.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
78961.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
78971.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
78981.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
78991.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
79001.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
79011.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
79021.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
79031.50Skamil
79041.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
79051.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
79061.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
79071.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
79081.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
79091.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
79101.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
79111.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
79121.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
79131.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
79141.1Skamil
79151.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
79161.37Skamil
79171.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
79181.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
79191.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
79201.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
79211.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
79221.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
79231.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
79241.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
79251.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
79261.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
79271.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
79281.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
79291.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
79301.40Skamil
79311.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
79321.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
79331.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
79341.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
79351.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
79361.41Skamil
79371.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
79381.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
79391.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
79401.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
79411.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
79421.92Skamil
79431.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
79441.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
79451.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
79461.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
79471.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
79481.92Skamil
79491.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
79501.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
79511.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
79521.43Skamil
79531.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
79541.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
79551.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
79561.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
79571.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
79581.59Skamil
79591.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79601.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
79611.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79621.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
79631.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79641.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
79651.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79661.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
79671.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79681.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
79691.94Skamil
79701.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79711.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
79721.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79731.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
79741.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79751.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
79761.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79771.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
79781.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79791.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
79801.94Skamil
79811.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
79821.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
79831.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
79841.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
79851.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
79861.51Skamil
79871.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
79881.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
79891.51Skamil
79901.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
79911.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
79921.51Skamil
79931.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79941.51Skamil		tracee_sees_its_original_parent_getppid);
79951.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79961.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
79971.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
79981.51Skamil		tracee_sees_its_original_parent_procfs_status);
79991.1Skamil
80001.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
80011.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
80021.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
80031.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
80041.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
80051.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
80061.125Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn);
80071.1Skamil
80081.31Skamil	ATF_TP_ADD_TC(tp, fork1);
80091.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
80101.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
80111.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
80121.31Skamil	ATF_TP_ADD_TC(tp, fork5);
80131.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
80141.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
80151.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
80161.125Skamil	ATF_TP_ADD_TC(tp, fork9);
80171.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork10);
80181.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork11);
80191.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork12);
80201.125Skamil	ATF_TP_ADD_TC(tp, fork13);
80211.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork14);
80221.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork15);
80231.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork16);
80241.31Skamil
80251.109Skamil#if TEST_VFORK_ENABLED
80261.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
80271.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
80281.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
80291.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
80301.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
80311.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
80321.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
80331.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
80341.125Skamil	ATF_TP_ADD_TC(tp, vfork9);
80351.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork10);
80361.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork11);
80371.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork12);
80381.125Skamil	ATF_TP_ADD_TC(tp, vfork13);
80391.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork14);
80401.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork15);
80411.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork16);
80421.116Skamil#endif
80431.1Skamil
80441.124Skamil	ATF_TP_ADD_TC(tp, posix_spawn1);
80451.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn2);
80461.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn3);
80471.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn4);
80481.124Skamil	ATF_TP_ADD_TC(tp, posix_spawn5);
80491.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn6);
80501.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn7);
80511.125Skamil	ATF_TP_ADD_TC(tp, posix_spawn8);
80521.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9);
80531.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10);
80541.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11);
80551.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12);
80561.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13);
80571.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14);
80581.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15);
80591.125Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16);
80601.124Skamil
80611.126Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner);
80621.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker);
80631.116Skamil#if TEST_VFORK_ENABLED
80641.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker);
80651.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone);
80661.116Skamil#endif
80671.126Skamil
80681.126Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner);
80691.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker);
80701.116Skamil#if TEST_VFORK_ENABLED
80711.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker);
80721.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone);
80731.116Skamil#endif
80741.116Skamil
80751.116Skamil#if TEST_VFORK_ENABLED
80761.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_fork);
80771.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_vfork);
80781.109Skamil#endif
80791.108Skamil
80801.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
80811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
80821.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
80831.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
80841.54Skamil
80851.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
80861.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
80871.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
80881.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
80891.54Skamil
80901.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
80911.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
80921.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
80931.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
80941.54Skamil
80951.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
80961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
80971.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
80981.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
80991.54Skamil
81001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
81011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
81021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
81031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
81041.54Skamil
81051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
81061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
81071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
81081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
81091.54Skamil
81101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
81111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
81121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
81131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
81141.54Skamil
81151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
81161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
81171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
81181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
81191.54Skamil
81201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
81211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
81221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
81231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
81241.54Skamil
81251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
81261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
81271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
81281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
81291.1Skamil
81301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
81311.1Skamil
81321.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i);
81331.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d);
81341.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i);
81351.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d);
81361.101Skamil
81371.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i);
81381.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d);
81391.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i);
81401.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d);
81411.101Skamil
81421.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv);
81431.101Skamil
81441.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i);
81451.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d);
81461.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i);
81471.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d);
81481.115Skamil
81491.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i);
81501.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d);
81511.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i);
81521.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d);
81531.115Skamil
81541.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
81551.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
81561.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
81571.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
81581.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
81591.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
81601.1Skamil
81611.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
81621.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
81631.1Skamil
81641.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
81651.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
81661.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
81671.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
81681.1Skamil
81691.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
81701.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
81711.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
81721.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
81731.2Skamil
81741.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
81751.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
81761.95Skamil
81771.1Skamil	ATF_TP_ADD_TC(tp, kill1);
81781.1Skamil	ATF_TP_ADD_TC(tp, kill2);
81791.75Skamil	ATF_TP_ADD_TC(tp, kill3);
81801.1Skamil
81811.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
81821.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
81831.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
81841.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
81851.77Skamil
81861.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
81871.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
81881.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
81891.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
81901.1Skamil
81911.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
81921.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
81931.79Skamil
81941.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
81951.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
81961.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
81971.1Skamil
81981.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_nolwpevents);
81991.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpexit);
82001.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate);
82011.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit);
82021.1Skamil
82031.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
82041.84Skamil
82051.126Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked);
82061.126Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored);
82071.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
82081.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
82091.109Skamil#if TEST_VFORK_ENABLED
82101.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
82111.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
82121.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
82131.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
82141.109Skamil#endif
82151.99Skamil
82161.1Skamil	ATF_TP_ADD_TC(tp, signal9);
82171.1Skamil	ATF_TP_ADD_TC(tp, signal10);
82181.1Skamil
82191.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
82201.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
82211.1Skamil
82221.1Skamil	ATF_TP_ADD_TC(tp, resume1);
82231.1Skamil
82241.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
82251.1Skamil
82261.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
82271.1Skamil
82281.106Skamil	ATF_TP_ADD_TC(tp, clone1);
82291.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone2);
82301.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone3);
82311.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone4);
82321.106Skamil	ATF_TP_ADD_TC(tp, clone5);
82331.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone6);
82341.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone7);
82351.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone8);
82361.106Skamil
82371.106Skamil	ATF_TP_ADD_TC(tp, clone_vm1);
82381.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2);
82391.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3);
82401.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4);
82411.106Skamil	ATF_TP_ADD_TC(tp, clone_vm5);
82421.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6);
82431.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7);
82441.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8);
82451.106Skamil
82461.106Skamil	ATF_TP_ADD_TC(tp, clone_fs1);
82471.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2);
82481.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3);
82491.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4);
82501.106Skamil	ATF_TP_ADD_TC(tp, clone_fs5);
82511.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6);
82521.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7);
82531.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8);
82541.106Skamil
82551.106Skamil	ATF_TP_ADD_TC(tp, clone_files1);
82561.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2);
82571.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3);
82581.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4);
82591.106Skamil	ATF_TP_ADD_TC(tp, clone_files5);
82601.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6);
82611.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7);
82621.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8);
82631.106Skamil
82641.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand1); // XXX
82651.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX
82661.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX
82671.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX
82681.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand5); // XXX
82691.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX
82701.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX
82711.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX
82721.106Skamil
82731.109Skamil#if TEST_VFORK_ENABLED
82741.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork1);
82751.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2);
82761.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3);
82771.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4);
82781.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork5);
82791.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6);
82801.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7);
82811.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8);
82821.109Skamil#endif
82831.106Skamil
82841.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored);
82851.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked);
82861.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored);
82871.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked);
82881.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored);
82891.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked);
82901.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored);
82911.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked);
82921.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX
82931.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX
82941.109Skamil#if TEST_VFORK_ENABLED
82951.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored);
82961.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked);
82971.109Skamil#endif
82981.103Skamil
82991.109Skamil#if TEST_VFORK_ENABLED
83001.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone);
83011.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm);
83021.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs);
83031.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files);
83041.107Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX
83051.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork);
83061.109Skamil#endif
83071.107Skamil
83081.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue);
83091.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall);
83101.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach);
83111.122Skamil
83121.130Smgorny	ATF_TP_ADD_TC(tp, core_dump_procinfo);
83131.130Smgorny
83141.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
83151.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
83161.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
83171.1Skamil
83181.1Skamil	return atf_no_error();
83191.1Skamil}
8320