t_ptrace_wait.c revision 1.121
11.121Smgorny/*	$NetBSD: t_ptrace_wait.c,v 1.121 2019/05/09 13:07:35 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.121Smgorny__RCSID("$NetBSD: t_ptrace_wait.c,v 1.121 2019/05/09 13:07:35 mgorny Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.77Skamil#include <pthread.h>
471.1Skamil#include <sched.h>
481.1Skamil#include <signal.h>
491.1Skamil#include <stdint.h>
501.1Skamil#include <stdio.h>
511.1Skamil#include <stdlib.h>
521.1Skamil#include <strings.h>
531.26Skamil#include <time.h>
541.1Skamil#include <unistd.h>
551.1Skamil
561.114Skamil#include <fenv.h>
571.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__
581.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
591.114Skamil#endif
601.114Skamil
611.121Smgorny#if defined(__i386__) || defined(__x86_64__)
621.121Smgorny#include <cpuid.h>
631.121Smgorny#include <x86/cpu_extended_state.h>
641.121Smgorny#endif
651.121Smgorny
661.1Skamil#include <atf-c.h>
671.1Skamil
681.1Skamil#include "h_macros.h"
691.1Skamil
701.1Skamil#include "t_ptrace_wait.h"
711.1Skamil#include "msg.h"
721.1Skamil
731.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
741.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
751.61Skre	sizeof(msg)) == 0)
761.1Skamil
771.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
781.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
791.61Skre	sizeof(msg)) == 0)
801.1Skamil
811.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
821.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
831.61Skre	sizeof(msg)) == 0)
841.1Skamil
851.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
861.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
871.61Skre	sizeof(msg)) == 0)
881.13Schristos
891.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
901.13Schristos    strerror(errno))
911.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
921.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
931.13Schristos
941.13Schristosstatic int debug = 0;
951.13Schristos
961.13Schristos#define DPRINTF(a, ...)	do  \
971.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
981.13Schristos    while (/*CONSTCOND*/0)
991.1Skamil
1001.110Skamil#ifndef TEST_VFORK_ENABLED
1011.109Skamil#define TEST_VFORK_ENABLED 0
1021.110Skamil#endif
1031.109Skamil
1041.34Skamil/// ----------------------------------------------------------------------------
1051.34Skamil
1061.33Skamilstatic void
1071.33Skamiltraceme_raise(int sigval)
1081.1Skamil{
1091.1Skamil	const int exitval = 5;
1101.1Skamil	pid_t child, wpid;
1111.1Skamil#if defined(TWAIT_HAVE_STATUS)
1121.1Skamil	int status;
1131.1Skamil#endif
1141.1Skamil
1151.45Skamil	struct ptrace_siginfo info;
1161.45Skamil	memset(&info, 0, sizeof(info));
1171.45Skamil
1181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1201.1Skamil	if (child == 0) {
1211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1231.1Skamil
1241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1261.1Skamil
1271.36Skamil		switch (sigval) {
1281.36Skamil		case SIGKILL:
1291.36Skamil			/* NOTREACHED */
1301.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1311.70Smrg			__unreachable();
1321.36Skamil		default:
1331.36Skamil			DPRINTF("Before exiting of the child process\n");
1341.36Skamil			_exit(exitval);
1351.36Skamil		}
1361.1Skamil	}
1371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1381.1Skamil
1391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1411.1Skamil
1421.36Skamil	switch (sigval) {
1431.36Skamil	case SIGKILL:
1441.36Skamil		validate_status_signaled(status, sigval, 0);
1451.36Skamil		break;
1461.36Skamil	default:
1471.36Skamil		validate_status_stopped(status, sigval);
1481.1Skamil
1491.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1501.61Skre			"child\n");
1511.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1521.61Skre			sizeof(info)) != -1);
1531.45Skamil
1541.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1551.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1561.61Skre			"si_errno=%#x\n",
1571.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1581.61Skre			info.psi_siginfo.si_errno);
1591.45Skamil
1601.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1611.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1621.45Skamil
1631.36Skamil		DPRINTF("Before resuming the child process where it left off "
1641.36Skamil		    "and without signal to be sent\n");
1651.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1661.1Skamil
1671.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1681.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1691.61Skre		    child);
1701.36Skamil		break;
1711.36Skamil	}
1721.1Skamil
1731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1751.1Skamil}
1761.1Skamil
1771.61Skre#define TRACEME_RAISE(test, sig)					\
1781.61SkreATF_TC(test);								\
1791.61SkreATF_TC_HEAD(test, tc)							\
1801.61Skre{									\
1811.61Skre	atf_tc_set_md_var(tc, "descr",					\
1821.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1831.61Skre}									\
1841.61Skre									\
1851.61SkreATF_TC_BODY(test, tc)							\
1861.61Skre{									\
1871.61Skre									\
1881.61Skre	traceme_raise(sig);						\
1891.33Skamil}
1901.33Skamil
1911.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1921.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1931.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1941.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1951.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1961.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1971.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1981.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1991.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
2001.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
2011.33Skamil
2021.34Skamil/// ----------------------------------------------------------------------------
2031.1Skamil
2041.1Skamilstatic void
2051.87Skamiltraceme_raisesignal_ignored(int sigignored)
2061.87Skamil{
2071.87Skamil	const int exitval = 5;
2081.87Skamil	const int sigval = SIGSTOP;
2091.87Skamil	pid_t child, wpid;
2101.87Skamil	struct sigaction sa;
2111.87Skamil#if defined(TWAIT_HAVE_STATUS)
2121.87Skamil	int status;
2131.87Skamil#endif
2141.87Skamil	struct ptrace_siginfo info;
2151.87Skamil
2161.87Skamil	memset(&info, 0, sizeof(info));
2171.87Skamil
2181.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2191.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2201.87Skamil	if (child == 0) {
2211.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2221.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2231.87Skamil
2241.87Skamil		memset(&sa, 0, sizeof(sa));
2251.87Skamil		sa.sa_handler = SIG_IGN;
2261.87Skamil		sigemptyset(&sa.sa_mask);
2271.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2281.87Skamil
2291.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2301.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2311.87Skamil
2321.87Skamil		DPRINTF("Before raising %s from child\n",
2331.87Skamil		    strsignal(sigignored));
2341.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2351.87Skamil
2361.87Skamil		DPRINTF("Before exiting of the child process\n");
2371.87Skamil		_exit(exitval);
2381.87Skamil	}
2391.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2401.87Skamil
2411.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2421.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2431.87Skamil
2441.87Skamil	validate_status_stopped(status, sigval);
2451.87Skamil
2461.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2471.87Skamil	SYSCALL_REQUIRE(
2481.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2491.87Skamil
2501.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2511.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2521.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2531.87Skamil	    info.psi_siginfo.si_errno);
2541.87Skamil
2551.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2561.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2571.87Skamil
2581.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2591.87Skamil	    "without signal to be sent\n");
2601.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2611.87Skamil
2621.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2631.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2641.87Skamil
2651.87Skamil	validate_status_stopped(status, sigignored);
2661.87Skamil
2671.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2681.87Skamil	SYSCALL_REQUIRE(
2691.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2701.87Skamil
2711.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2721.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2731.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2741.87Skamil	    info.psi_siginfo.si_errno);
2751.87Skamil
2761.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2771.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2781.87Skamil
2791.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2801.87Skamil	    "without signal to be sent\n");
2811.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2821.87Skamil
2831.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2841.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2851.87Skamil
2861.87Skamil	validate_status_exited(status, exitval);
2871.87Skamil
2881.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2891.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2901.87Skamil}
2911.87Skamil
2921.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2931.87SkamilATF_TC(test);								\
2941.87SkamilATF_TC_HEAD(test, tc)							\
2951.87Skamil{									\
2961.87Skamil	atf_tc_set_md_var(tc, "descr",					\
2971.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
2981.87Skamil	    "does not stop tracer from catching this raised signal");	\
2991.87Skamil}									\
3001.87Skamil									\
3011.87SkamilATF_TC_BODY(test, tc)							\
3021.87Skamil{									\
3031.87Skamil									\
3041.87Skamil	traceme_raisesignal_ignored(sig);				\
3051.87Skamil}
3061.87Skamil
3071.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
3081.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
3091.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
3101.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
3111.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
3121.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
3131.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3141.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3151.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3161.87Skamil
3171.87Skamil/// ----------------------------------------------------------------------------
3181.87Skamil
3191.87Skamilstatic void
3201.86Skamiltraceme_raisesignal_masked(int sigmasked)
3211.86Skamil{
3221.86Skamil	const int exitval = 5;
3231.86Skamil	const int sigval = SIGSTOP;
3241.86Skamil	pid_t child, wpid;
3251.86Skamil#if defined(TWAIT_HAVE_STATUS)
3261.86Skamil	int status;
3271.86Skamil#endif
3281.86Skamil	sigset_t intmask;
3291.86Skamil	struct ptrace_siginfo info;
3301.86Skamil
3311.86Skamil	memset(&info, 0, sizeof(info));
3321.86Skamil
3331.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3341.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3351.86Skamil	if (child == 0) {
3361.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3371.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3381.86Skamil
3391.86Skamil		sigemptyset(&intmask);
3401.86Skamil		sigaddset(&intmask, sigmasked);
3411.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3421.86Skamil
3431.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3441.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3451.86Skamil
3461.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3471.86Skamil		    strsignal(sigmasked));
3481.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3491.86Skamil
3501.86Skamil		DPRINTF("Before exiting of the child process\n");
3511.86Skamil		_exit(exitval);
3521.86Skamil	}
3531.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3541.86Skamil
3551.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3561.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3571.86Skamil
3581.86Skamil	validate_status_stopped(status, sigval);
3591.86Skamil
3601.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3611.86Skamil	SYSCALL_REQUIRE(
3621.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3631.86Skamil
3641.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3651.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3661.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3671.86Skamil	    info.psi_siginfo.si_errno);
3681.86Skamil
3691.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3701.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3711.86Skamil
3721.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3731.86Skamil	    "without signal to be sent\n");
3741.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3751.86Skamil
3761.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3771.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3781.86Skamil
3791.86Skamil	validate_status_exited(status, exitval);
3801.86Skamil
3811.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3821.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3831.86Skamil}
3841.86Skamil
3851.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3861.86SkamilATF_TC(test);								\
3871.86SkamilATF_TC_HEAD(test, tc)							\
3881.86Skamil{									\
3891.86Skamil	atf_tc_set_md_var(tc, "descr",					\
3901.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3911.86Skamil	    "stops tracer from catching this raised signal");		\
3921.86Skamil}									\
3931.86Skamil									\
3941.86SkamilATF_TC_BODY(test, tc)							\
3951.86Skamil{									\
3961.86Skamil									\
3971.86Skamil	traceme_raisesignal_masked(sig);				\
3981.86Skamil}
3991.86Skamil
4001.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4011.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
4021.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
4031.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
4041.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
4051.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
4061.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
4071.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
4081.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
4091.86Skamil
4101.86Skamil/// ----------------------------------------------------------------------------
4111.86Skamil
4121.86Skamilstatic void
4131.59Skamiltraceme_crash(int sig)
4141.59Skamil{
4151.59Skamil	pid_t child, wpid;
4161.59Skamil#if defined(TWAIT_HAVE_STATUS)
4171.59Skamil	int status;
4181.59Skamil#endif
4191.59Skamil	struct ptrace_siginfo info;
4201.61Skre
4211.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4221.71Skamil	if (sig == SIGILL)
4231.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4241.71Skamil#endif
4251.71Skamil
4261.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
4271.114Skamil		atf_tc_skip("FP exceptions are not supported");
4281.114Skamil
4291.59Skamil	memset(&info, 0, sizeof(info));
4301.59Skamil
4311.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4321.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4331.59Skamil	if (child == 0) {
4341.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4351.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4361.59Skamil
4371.59Skamil		DPRINTF("Before executing a trap\n");
4381.59Skamil		switch (sig) {
4391.59Skamil		case SIGTRAP:
4401.59Skamil			trigger_trap();
4411.59Skamil			break;
4421.59Skamil		case SIGSEGV:
4431.59Skamil			trigger_segv();
4441.59Skamil			break;
4451.59Skamil		case SIGILL:
4461.59Skamil			trigger_ill();
4471.59Skamil			break;
4481.59Skamil		case SIGFPE:
4491.59Skamil			trigger_fpe();
4501.59Skamil			break;
4511.59Skamil		case SIGBUS:
4521.59Skamil			trigger_bus();
4531.59Skamil			break;
4541.59Skamil		default:
4551.59Skamil			/* NOTREACHED */
4561.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4571.59Skamil		}
4581.59Skamil
4591.59Skamil		/* NOTREACHED */
4601.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4611.59Skamil	}
4621.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4631.59Skamil
4641.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4651.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4661.59Skamil
4671.59Skamil	validate_status_stopped(status, sig);
4681.59Skamil
4691.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4701.61Skre	SYSCALL_REQUIRE(
4711.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4721.59Skamil
4731.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4741.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4751.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4761.61Skre	    info.psi_siginfo.si_errno);
4771.59Skamil
4781.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4791.59Skamil	switch (sig) {
4801.59Skamil	case SIGTRAP:
4811.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4821.59Skamil		break;
4831.59Skamil	case SIGSEGV:
4841.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4851.59Skamil		break;
4861.71Skamil	case SIGILL:
4871.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
4881.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
4891.71Skamil		break;
4901.59Skamil	case SIGFPE:
4911.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4921.59Skamil		break;
4931.59Skamil	case SIGBUS:
4941.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
4951.59Skamil		break;
4961.59Skamil	}
4971.59Skamil
4981.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
4991.59Skamil
5001.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5011.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5021.59Skamil
5031.59Skamil	validate_status_signaled(status, SIGKILL, 0);
5041.59Skamil
5051.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5061.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5071.59Skamil}
5081.59Skamil
5091.61Skre#define TRACEME_CRASH(test, sig)					\
5101.61SkreATF_TC(test);								\
5111.61SkreATF_TC_HEAD(test, tc)							\
5121.61Skre{									\
5131.61Skre	atf_tc_set_md_var(tc, "descr",					\
5141.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
5151.61Skre}									\
5161.61Skre									\
5171.61SkreATF_TC_BODY(test, tc)							\
5181.61Skre{									\
5191.61Skre									\
5201.61Skre	traceme_crash(sig);						\
5211.59Skamil}
5221.59Skamil
5231.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5241.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5251.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5261.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5271.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5281.59Skamil
5291.59Skamil/// ----------------------------------------------------------------------------
5301.59Skamil
5311.59Skamilstatic void
5321.88Skamiltraceme_signalmasked_crash(int sig)
5331.88Skamil{
5341.89Skamil	const int sigval = SIGSTOP;
5351.88Skamil	pid_t child, wpid;
5361.88Skamil#if defined(TWAIT_HAVE_STATUS)
5371.88Skamil	int status;
5381.88Skamil#endif
5391.88Skamil	struct ptrace_siginfo info;
5401.88Skamil	sigset_t intmask;
5411.89Skamil	struct kinfo_proc2 kp;
5421.89Skamil	size_t len = sizeof(kp);
5431.89Skamil
5441.89Skamil	int name[6];
5451.89Skamil	const size_t namelen = __arraycount(name);
5461.89Skamil	ki_sigset_t kp_sigmask;
5471.88Skamil
5481.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5491.88Skamil	if (sig == SIGILL)
5501.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5511.88Skamil#endif
5521.88Skamil
5531.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
5541.114Skamil		atf_tc_skip("FP exceptions are not supported");
5551.114Skamil
5561.88Skamil	memset(&info, 0, sizeof(info));
5571.88Skamil
5581.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5591.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5601.88Skamil	if (child == 0) {
5611.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5621.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5631.88Skamil
5641.88Skamil		sigemptyset(&intmask);
5651.88Skamil		sigaddset(&intmask, sig);
5661.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5671.88Skamil
5681.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5691.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5701.89Skamil
5711.88Skamil		DPRINTF("Before executing a trap\n");
5721.88Skamil		switch (sig) {
5731.88Skamil		case SIGTRAP:
5741.88Skamil			trigger_trap();
5751.88Skamil			break;
5761.88Skamil		case SIGSEGV:
5771.88Skamil			trigger_segv();
5781.88Skamil			break;
5791.88Skamil		case SIGILL:
5801.88Skamil			trigger_ill();
5811.88Skamil			break;
5821.88Skamil		case SIGFPE:
5831.88Skamil			trigger_fpe();
5841.88Skamil			break;
5851.88Skamil		case SIGBUS:
5861.88Skamil			trigger_bus();
5871.88Skamil			break;
5881.88Skamil		default:
5891.88Skamil			/* NOTREACHED */
5901.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5911.88Skamil		}
5921.88Skamil
5931.88Skamil		/* NOTREACHED */
5941.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5951.88Skamil	}
5961.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5971.88Skamil
5981.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5991.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6001.88Skamil
6011.89Skamil	validate_status_stopped(status, sigval);
6021.89Skamil
6031.89Skamil	name[0] = CTL_KERN,
6041.89Skamil	name[1] = KERN_PROC2,
6051.89Skamil	name[2] = KERN_PROC_PID;
6061.89Skamil	name[3] = child;
6071.89Skamil	name[4] = sizeof(kp);
6081.89Skamil	name[5] = 1;
6091.89Skamil
6101.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6111.89Skamil
6121.89Skamil	kp_sigmask = kp.p_sigmask;
6131.89Skamil
6141.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6151.89Skamil	SYSCALL_REQUIRE(
6161.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6171.89Skamil
6181.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6191.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6201.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6211.89Skamil	    info.psi_siginfo.si_errno);
6221.89Skamil
6231.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6241.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6251.89Skamil
6261.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6271.89Skamil	    "without signal to be sent\n");
6281.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6291.89Skamil
6301.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6311.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6321.89Skamil
6331.88Skamil	validate_status_stopped(status, sig);
6341.88Skamil
6351.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6361.88Skamil	SYSCALL_REQUIRE(
6371.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6381.88Skamil
6391.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6401.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6411.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6421.88Skamil	    info.psi_siginfo.si_errno);
6431.88Skamil
6441.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6451.89Skamil
6461.89Skamil	DPRINTF("kp_sigmask="
6471.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6481.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6491.89Skamil	    kp_sigmask.__bits[3]);
6501.89Skamil
6511.89Skamil	DPRINTF("kp.p_sigmask="
6521.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6531.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6541.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6551.89Skamil
6561.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6571.89Skamil
6581.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6591.88Skamil	switch (sig) {
6601.88Skamil	case SIGTRAP:
6611.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6621.88Skamil		break;
6631.88Skamil	case SIGSEGV:
6641.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6651.88Skamil		break;
6661.88Skamil	case SIGILL:
6671.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
6681.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
6691.88Skamil		break;
6701.88Skamil	case SIGFPE:
6711.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6721.88Skamil		break;
6731.88Skamil	case SIGBUS:
6741.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6751.88Skamil		break;
6761.88Skamil	}
6771.88Skamil
6781.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6791.88Skamil
6801.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6811.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6821.88Skamil
6831.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6841.88Skamil
6851.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6861.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6871.88Skamil}
6881.88Skamil
6891.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6901.88SkamilATF_TC(test);								\
6911.88SkamilATF_TC_HEAD(test, tc)							\
6921.88Skamil{									\
6931.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6941.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6951.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6961.88Skamil}									\
6971.88Skamil									\
6981.88SkamilATF_TC_BODY(test, tc)							\
6991.88Skamil{									\
7001.88Skamil									\
7011.88Skamil	traceme_signalmasked_crash(sig);				\
7021.88Skamil}
7031.88Skamil
7041.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
7051.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
7061.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
7071.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
7081.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
7091.88Skamil
7101.88Skamil/// ----------------------------------------------------------------------------
7111.88Skamil
7121.88Skamilstatic void
7131.88Skamiltraceme_signalignored_crash(int sig)
7141.88Skamil{
7151.90Skamil	const int sigval = SIGSTOP;
7161.88Skamil	pid_t child, wpid;
7171.88Skamil#if defined(TWAIT_HAVE_STATUS)
7181.88Skamil	int status;
7191.88Skamil#endif
7201.88Skamil	struct sigaction sa;
7211.88Skamil	struct ptrace_siginfo info;
7221.90Skamil	struct kinfo_proc2 kp;
7231.90Skamil	size_t len = sizeof(kp);
7241.90Skamil
7251.90Skamil	int name[6];
7261.90Skamil	const size_t namelen = __arraycount(name);
7271.90Skamil	ki_sigset_t kp_sigignore;
7281.88Skamil
7291.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7301.88Skamil	if (sig == SIGILL)
7311.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7321.88Skamil#endif
7331.88Skamil
7341.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
7351.114Skamil		atf_tc_skip("FP exceptions are not supported");
7361.114Skamil
7371.88Skamil	memset(&info, 0, sizeof(info));
7381.88Skamil
7391.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7401.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7411.88Skamil	if (child == 0) {
7421.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7431.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7441.88Skamil
7451.88Skamil		memset(&sa, 0, sizeof(sa));
7461.88Skamil		sa.sa_handler = SIG_IGN;
7471.88Skamil		sigemptyset(&sa.sa_mask);
7481.88Skamil
7491.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7501.88Skamil
7511.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7521.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7531.90Skamil
7541.88Skamil		DPRINTF("Before executing a trap\n");
7551.88Skamil		switch (sig) {
7561.88Skamil		case SIGTRAP:
7571.88Skamil			trigger_trap();
7581.88Skamil			break;
7591.88Skamil		case SIGSEGV:
7601.88Skamil			trigger_segv();
7611.88Skamil			break;
7621.88Skamil		case SIGILL:
7631.88Skamil			trigger_ill();
7641.88Skamil			break;
7651.88Skamil		case SIGFPE:
7661.88Skamil			trigger_fpe();
7671.88Skamil			break;
7681.88Skamil		case SIGBUS:
7691.88Skamil			trigger_bus();
7701.88Skamil			break;
7711.88Skamil		default:
7721.88Skamil			/* NOTREACHED */
7731.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7741.88Skamil		}
7751.88Skamil
7761.88Skamil		/* NOTREACHED */
7771.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7781.88Skamil	}
7791.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7801.88Skamil
7811.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7821.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7831.88Skamil
7841.90Skamil	validate_status_stopped(status, sigval);
7851.90Skamil
7861.90Skamil	name[0] = CTL_KERN,
7871.90Skamil	name[1] = KERN_PROC2,
7881.90Skamil	name[2] = KERN_PROC_PID;
7891.90Skamil	name[3] = child;
7901.90Skamil	name[4] = sizeof(kp);
7911.90Skamil	name[5] = 1;
7921.90Skamil
7931.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
7941.90Skamil
7951.90Skamil	kp_sigignore = kp.p_sigignore;
7961.90Skamil
7971.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7981.90Skamil	SYSCALL_REQUIRE(
7991.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8001.90Skamil
8011.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8021.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8031.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8041.90Skamil	    info.psi_siginfo.si_errno);
8051.90Skamil
8061.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8071.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
8081.90Skamil
8091.90Skamil	DPRINTF("Before resuming the child process where it left off and "
8101.90Skamil	    "without signal to be sent\n");
8111.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8121.90Skamil
8131.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8141.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8151.90Skamil
8161.88Skamil	validate_status_stopped(status, sig);
8171.88Skamil
8181.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
8191.88Skamil	SYSCALL_REQUIRE(
8201.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8211.88Skamil
8221.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8231.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8241.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8251.88Skamil	    info.psi_siginfo.si_errno);
8261.88Skamil
8271.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8281.90Skamil
8291.90Skamil	DPRINTF("kp_sigignore="
8301.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8311.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8321.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8331.90Skamil
8341.90Skamil	DPRINTF("kp.p_sigignore="
8351.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8361.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8371.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8381.90Skamil
8391.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8401.90Skamil
8411.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8421.88Skamil	switch (sig) {
8431.88Skamil	case SIGTRAP:
8441.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8451.88Skamil		break;
8461.88Skamil	case SIGSEGV:
8471.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8481.88Skamil		break;
8491.88Skamil	case SIGILL:
8501.113Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC &&
8511.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
8521.88Skamil		break;
8531.88Skamil	case SIGFPE:
8541.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8551.88Skamil		break;
8561.88Skamil	case SIGBUS:
8571.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8581.88Skamil		break;
8591.88Skamil	}
8601.88Skamil
8611.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8621.88Skamil
8631.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8641.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8651.88Skamil
8661.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8671.88Skamil
8681.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8691.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8701.88Skamil}
8711.88Skamil
8721.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8731.88SkamilATF_TC(test);								\
8741.88SkamilATF_TC_HEAD(test, tc)							\
8751.88Skamil{									\
8761.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8771.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8781.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8791.88Skamil}									\
8801.88Skamil									\
8811.88SkamilATF_TC_BODY(test, tc)							\
8821.88Skamil{									\
8831.88Skamil									\
8841.88Skamil	traceme_signalignored_crash(sig);				\
8851.88Skamil}
8861.88Skamil
8871.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8881.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8891.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8901.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8911.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8921.88Skamil
8931.88Skamil/// ----------------------------------------------------------------------------
8941.88Skamil
8951.88Skamilstatic void
8961.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
8971.1Skamil{
8981.1Skamil	const int exitval = 5;
8991.34Skamil	const int sigval = SIGSTOP;
9001.1Skamil	pid_t child, wpid;
9011.1Skamil	struct sigaction sa;
9021.1Skamil#if defined(TWAIT_HAVE_STATUS)
9031.1Skamil	int status;
9041.1Skamil#endif
9051.61Skre	struct ptrace_siginfo info;
9061.1Skamil
9071.45Skamil	memset(&info, 0, sizeof(info));
9081.45Skamil
9091.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
9101.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
9111.1Skamil	if (child == 0) {
9121.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9131.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9141.1Skamil
9151.34Skamil		sa.sa_handler = sah;
9161.1Skamil		sa.sa_flags = SA_SIGINFO;
9171.1Skamil		sigemptyset(&sa.sa_mask);
9181.1Skamil
9191.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
9201.1Skamil
9211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9231.1Skamil
9241.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9251.1Skamil
9261.13Schristos		DPRINTF("Before exiting of the child process\n");
9271.1Skamil		_exit(exitval);
9281.1Skamil	}
9291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9301.1Skamil
9311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9331.1Skamil
9341.1Skamil	validate_status_stopped(status, sigval);
9351.1Skamil
9361.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9371.61Skre	SYSCALL_REQUIRE(
9381.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9391.45Skamil
9401.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9411.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9421.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9431.45Skamil	    info.psi_siginfo.si_errno);
9441.45Skamil
9451.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9461.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9471.45Skamil
9481.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9491.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9511.1Skamil
9521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9541.1Skamil
9551.1Skamil	validate_status_exited(status, exitval);
9561.1Skamil
9571.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9591.1Skamil}
9601.1Skamil
9611.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9621.61SkreATF_TC(test);								\
9631.61SkreATF_TC_HEAD(test, tc)							\
9641.61Skre{									\
9651.61Skre	atf_tc_set_md_var(tc, "descr",					\
9661.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9671.61Skre	    "handled correctly and caught by a signal handler");	\
9681.61Skre}									\
9691.61Skre									\
9701.61Skrestatic int test##_caught = 0;						\
9711.61Skre									\
9721.61Skrestatic void								\
9731.61Skretest##_sighandler(int arg)						\
9741.61Skre{									\
9751.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9761.61Skre									\
9771.61Skre	++ test##_caught;						\
9781.61Skre}									\
9791.61Skre									\
9801.61SkreATF_TC_BODY(test, tc)							\
9811.61Skre{									\
9821.61Skre									\
9831.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9841.34Skamil}
9851.34Skamil
9861.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9871.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9881.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9891.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9901.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9911.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9921.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9931.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
9941.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
9951.34Skamil
9961.34Skamil/// ----------------------------------------------------------------------------
9971.34Skamil
9981.35Skamilstatic void
9991.50Skamiltraceme_sendsignal_masked(int sigsent)
10001.50Skamil{
10011.50Skamil	const int exitval = 5;
10021.50Skamil	const int sigval = SIGSTOP;
10031.50Skamil	pid_t child, wpid;
10041.50Skamil	sigset_t set;
10051.50Skamil#if defined(TWAIT_HAVE_STATUS)
10061.50Skamil	int status;
10071.50Skamil#endif
10081.61Skre	struct ptrace_siginfo info;
10091.50Skamil
10101.50Skamil	memset(&info, 0, sizeof(info));
10111.50Skamil
10121.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10131.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10141.50Skamil	if (child == 0) {
10151.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10161.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10171.50Skamil
10181.50Skamil		sigemptyset(&set);
10191.50Skamil		sigaddset(&set, sigsent);
10201.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
10211.50Skamil
10221.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10231.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10241.50Skamil
10251.50Skamil		_exit(exitval);
10261.50Skamil	}
10271.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10281.50Skamil
10291.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10301.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10311.50Skamil
10321.50Skamil	validate_status_stopped(status, sigval);
10331.50Skamil
10341.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10351.61Skre	SYSCALL_REQUIRE(
10361.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10371.50Skamil
10381.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10391.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10401.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10411.50Skamil	    info.psi_siginfo.si_errno);
10421.50Skamil
10431.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10441.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10451.50Skamil
10461.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10471.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10481.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10491.50Skamil
10501.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10511.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10521.50Skamil
10531.50Skamil	validate_status_exited(status, exitval);
10541.50Skamil
10551.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10561.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10571.50Skamil}
10581.50Skamil
10591.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10601.61SkreATF_TC(test);								\
10611.61SkreATF_TC_HEAD(test, tc)							\
10621.61Skre{									\
10631.61Skre	atf_tc_set_md_var(tc, "descr",					\
10641.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10651.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10661.61Skre}									\
10671.61Skre									\
10681.61SkreATF_TC_BODY(test, tc)							\
10691.61Skre{									\
10701.61Skre									\
10711.61Skre	traceme_sendsignal_masked(sig);					\
10721.50Skamil}
10731.50Skamil
10741.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10751.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10761.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10771.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10781.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10791.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10801.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10811.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10821.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10831.50Skamil
10841.50Skamil/// ----------------------------------------------------------------------------
10851.50Skamil
10861.50Skamilstatic void
10871.50Skamiltraceme_sendsignal_ignored(int sigsent)
10881.50Skamil{
10891.50Skamil	const int exitval = 5;
10901.50Skamil	const int sigval = SIGSTOP;
10911.50Skamil	pid_t child, wpid;
10921.50Skamil	struct sigaction sa;
10931.50Skamil#if defined(TWAIT_HAVE_STATUS)
10941.50Skamil	int status;
10951.50Skamil#endif
10961.61Skre	struct ptrace_siginfo info;
10971.50Skamil
10981.50Skamil	memset(&info, 0, sizeof(info));
10991.50Skamil
11001.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
11011.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
11021.50Skamil	if (child == 0) {
11031.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11041.61Skre
11051.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11061.50Skamil
11071.50Skamil		memset(&sa, 0, sizeof(sa));
11081.50Skamil		sa.sa_handler = SIG_IGN;
11091.50Skamil		sigemptyset(&sa.sa_mask);
11101.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
11111.50Skamil
11121.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11131.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11141.50Skamil
11151.50Skamil		_exit(exitval);
11161.50Skamil	}
11171.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11181.50Skamil
11191.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11201.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11211.50Skamil
11221.50Skamil	validate_status_stopped(status, sigval);
11231.50Skamil
11241.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11251.61Skre	SYSCALL_REQUIRE(
11261.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11271.50Skamil
11281.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11291.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11301.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11311.50Skamil	    info.psi_siginfo.si_errno);
11321.50Skamil
11331.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11341.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11351.50Skamil
11361.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11371.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11381.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11391.50Skamil
11401.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11411.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11421.50Skamil
11431.50Skamil	validate_status_exited(status, exitval);
11441.50Skamil
11451.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11461.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11471.50Skamil}
11481.50Skamil
11491.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11501.61SkreATF_TC(test);								\
11511.61SkreATF_TC_HEAD(test, tc)							\
11521.61Skre{									\
11531.61Skre	atf_tc_set_md_var(tc, "descr",					\
11541.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11551.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11561.61Skre}									\
11571.61Skre									\
11581.61SkreATF_TC_BODY(test, tc)							\
11591.61Skre{									\
11601.61Skre									\
11611.61Skre	traceme_sendsignal_ignored(sig);				\
11621.50Skamil}
11631.50Skamil
11641.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11651.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11661.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11671.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11681.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11691.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11701.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11711.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11721.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11731.50Skamil
11741.50Skamil/// ----------------------------------------------------------------------------
11751.50Skamil
11761.50Skamilstatic void
11771.50Skamiltraceme_sendsignal_simple(int sigsent)
11781.1Skamil{
11791.35Skamil	const int sigval = SIGSTOP;
11801.35Skamil	int exitval = 0;
11811.1Skamil	pid_t child, wpid;
11821.1Skamil#if defined(TWAIT_HAVE_STATUS)
11831.1Skamil	int status;
11841.85Skamil	int expect_core;
11851.85Skamil
11861.85Skamil	switch (sigsent) {
11871.85Skamil	case SIGABRT:
11881.85Skamil	case SIGTRAP:
11891.85Skamil	case SIGBUS:
11901.85Skamil	case SIGILL:
11911.85Skamil	case SIGFPE:
11921.85Skamil	case SIGSEGV:
11931.85Skamil		expect_core = 1;
11941.85Skamil		break;
11951.85Skamil	default:
11961.85Skamil		expect_core = 0;
11971.85Skamil		break;
11981.85Skamil	}
11991.1Skamil#endif
12001.61Skre	struct ptrace_siginfo info;
12011.1Skamil
12021.45Skamil	memset(&info, 0, sizeof(info));
12031.45Skamil
12041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12061.1Skamil	if (child == 0) {
12071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12091.1Skamil
12101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12121.1Skamil
12131.35Skamil		switch (sigsent) {
12141.35Skamil		case SIGCONT:
12151.48Skamil		case SIGSTOP:
12161.35Skamil			_exit(exitval);
12171.35Skamil		default:
12181.35Skamil			/* NOTREACHED */
12191.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
12201.35Skamil		}
12211.1Skamil	}
12221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12231.1Skamil
12241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12261.1Skamil
12271.1Skamil	validate_status_stopped(status, sigval);
12281.1Skamil
12291.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12301.61Skre	SYSCALL_REQUIRE(
12311.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12321.45Skamil
12331.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12341.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12351.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12361.45Skamil	    info.psi_siginfo.si_errno);
12371.45Skamil
12381.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12391.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12401.45Skamil
12411.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12421.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12441.1Skamil
12451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12471.1Skamil
12481.35Skamil	switch (sigsent) {
12491.48Skamil	case SIGSTOP:
12501.48Skamil		validate_status_stopped(status, sigsent);
12511.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12521.61Skre		    "child\n");
12531.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12541.61Skre		    sizeof(info)) != -1);
12551.48Skamil
12561.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12571.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12581.61Skre		    "si_errno=%#x\n",
12591.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12601.61Skre		    info.psi_siginfo.si_errno);
12611.48Skamil
12621.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12631.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12641.48Skamil
12651.48Skamil		DPRINTF("Before resuming the child process where it left off "
12661.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12671.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12681.48Skamil
12691.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12701.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12711.61Skre		    child);
12721.48Skamil		/* FALLTHROUGH */
12731.35Skamil	case SIGCONT:
12741.35Skamil		validate_status_exited(status, exitval);
12751.35Skamil		break;
12761.35Skamil	default:
12771.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12781.35Skamil		break;
12791.35Skamil	}
12801.1Skamil
12811.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12831.1Skamil}
12841.1Skamil
12851.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12861.61SkreATF_TC(test);								\
12871.61SkreATF_TC_HEAD(test, tc)							\
12881.61Skre{									\
12891.61Skre	atf_tc_set_md_var(tc, "descr",					\
12901.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12911.61Skre	    "handled correctly in a child without a signal handler");	\
12921.61Skre}									\
12931.61Skre									\
12941.61SkreATF_TC_BODY(test, tc)							\
12951.61Skre{									\
12961.61Skre									\
12971.61Skre	traceme_sendsignal_simple(sig);					\
12981.35Skamil}
12991.35Skamil
13001.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
13011.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
13021.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
13031.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
13041.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
13051.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
13061.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
13071.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
13081.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
13091.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
13101.35Skamil
13111.35Skamil/// ----------------------------------------------------------------------------
13121.35Skamil
13131.37SkamilATF_TC(traceme_pid1_parent);
13141.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
13151.37Skamil{
13161.37Skamil	atf_tc_set_md_var(tc, "descr",
13171.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
13181.37Skamil}
13191.37Skamil
13201.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
13211.37Skamil{
13221.37Skamil	struct msg_fds parent_child;
13231.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13241.37Skamil	pid_t child1, child2, wpid;
13251.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13261.37Skamil#if defined(TWAIT_HAVE_STATUS)
13271.37Skamil	int status;
13281.37Skamil#endif
13291.37Skamil
13301.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13311.37Skamil
13321.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13331.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13341.37Skamil	if (child1 == 0) {
13351.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13361.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13371.37Skamil		if (child2 != 0) {
13381.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13391.61Skre			    getpid(), child2);
13401.37Skamil			_exit(exitval_child1);
13411.37Skamil		}
13421.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13431.37Skamil
13441.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13451.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13461.37Skamil
13471.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13481.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13491.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13501.37Skamil
13511.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13521.37Skamil
13531.37Skamil		_exit(exitval_child2);
13541.37Skamil	}
13551.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13561.37Skamil
13571.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13581.61Skre	TWAIT_REQUIRE_SUCCESS(
13591.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13601.37Skamil
13611.37Skamil	validate_status_exited(status, exitval_child1);
13621.37Skamil
13631.37Skamil	DPRINTF("Notify that child1 is dead\n");
13641.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13651.37Skamil
13661.37Skamil	DPRINTF("Wait for exiting of child2\n");
13671.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13681.37Skamil}
13691.37Skamil
13701.37Skamil/// ----------------------------------------------------------------------------
13711.37Skamil
13721.40Skamilstatic void
13731.40Skamiltraceme_vfork_raise(int sigval)
13741.40Skamil{
13751.46Skamil	const int exitval = 5, exitval_watcher = 10;
13761.46Skamil	pid_t child, parent, watcher, wpid;
13771.46Skamil	int rv;
13781.40Skamil#if defined(TWAIT_HAVE_STATUS)
13791.40Skamil	int status;
13801.85Skamil
13811.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13821.85Skamil	volatile int expect_core;
13831.85Skamil
13841.85Skamil	switch (sigval) {
13851.85Skamil	case SIGABRT:
13861.85Skamil	case SIGTRAP:
13871.85Skamil	case SIGBUS:
13881.85Skamil	case SIGILL:
13891.85Skamil	case SIGFPE:
13901.85Skamil	case SIGSEGV:
13911.85Skamil		expect_core = 1;
13921.85Skamil		break;
13931.85Skamil	default:
13941.85Skamil		expect_core = 0;
13951.85Skamil		break;
13961.85Skamil	}
13971.40Skamil#endif
13981.40Skamil
13991.46Skamil	/*
14001.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
14011.46Skamil	 * the SIGKILL signal to it.
14021.46Skamil	 *
14031.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
14041.46Skamil	 * simpler to reparent this process to initproc and forget about it.
14051.46Skamil	 */
14061.46Skamil	if (sigval == SIGSTOP) {
14071.46Skamil		parent = getpid();
14081.46Skamil
14091.46Skamil		watcher = fork();
14101.46Skamil		ATF_REQUIRE(watcher != 1);
14111.46Skamil		if (watcher == 0) {
14121.46Skamil			/* Double fork(2) trick to reparent to initproc */
14131.46Skamil			watcher = fork();
14141.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
14151.46Skamil			if (watcher != 0)
14161.46Skamil				_exit(exitval_watcher);
14171.46Skamil
14181.46Skamil			child = await_stopped_child(parent);
14191.46Skamil
14201.46Skamil			errno = 0;
14211.46Skamil			rv = kill(child, SIGKILL);
14221.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
14231.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14241.46Skamil
14251.46Skamil			/* This exit value will be collected by initproc */
14261.46Skamil			_exit(0);
14271.46Skamil		}
14281.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14291.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14301.61Skre		    watcher);
14311.46Skamil
14321.46Skamil		validate_status_exited(status, exitval_watcher);
14331.46Skamil
14341.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14351.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14361.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14371.46Skamil	}
14381.46Skamil
14391.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14401.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14411.40Skamil	if (child == 0) {
14421.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14431.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14441.40Skamil
14451.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14461.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14471.40Skamil
14481.40Skamil		switch (sigval) {
14491.46Skamil		case SIGSTOP:
14501.40Skamil		case SIGKILL:
14511.40Skamil		case SIGABRT:
14521.40Skamil		case SIGHUP:
14531.85Skamil		case SIGTRAP:
14541.85Skamil		case SIGBUS:
14551.85Skamil		case SIGILL:
14561.85Skamil		case SIGFPE:
14571.85Skamil		case SIGSEGV:
14581.40Skamil			/* NOTREACHED */
14591.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14601.70Smrg			__unreachable();
14611.40Skamil		default:
14621.40Skamil			DPRINTF("Before exiting of the child process\n");
14631.40Skamil			_exit(exitval);
14641.40Skamil		}
14651.40Skamil	}
14661.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14671.40Skamil
14681.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14691.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14701.40Skamil
14711.40Skamil	switch (sigval) {
14721.40Skamil	case SIGKILL:
14731.40Skamil	case SIGABRT:
14741.40Skamil	case SIGHUP:
14751.85Skamil	case SIGTRAP:
14761.85Skamil	case SIGBUS:
14771.85Skamil	case SIGILL:
14781.85Skamil	case SIGFPE:
14791.85Skamil	case SIGSEGV:
14801.40Skamil		validate_status_signaled(status, sigval, expect_core);
14811.40Skamil		break;
14821.40Skamil	case SIGSTOP:
14831.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14841.46Skamil		break;
14851.40Skamil	case SIGCONT:
14861.47Skamil	case SIGTSTP:
14871.47Skamil	case SIGTTIN:
14881.47Skamil	case SIGTTOU:
14891.40Skamil		validate_status_exited(status, exitval);
14901.40Skamil		break;
14911.40Skamil	default:
14921.40Skamil		/* NOTREACHED */
14931.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
14941.40Skamil		break;
14951.40Skamil	}
14961.40Skamil
14971.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14981.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14991.40Skamil}
15001.40Skamil
15011.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
15021.61SkreATF_TC(test);								\
15031.61SkreATF_TC_HEAD(test, tc)							\
15041.61Skre{									\
15051.61Skre	atf_tc_set_md_var(tc, "descr",					\
15061.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
15071.61Skre	    "vfork(2)ed child");					\
15081.61Skre}									\
15091.61Skre									\
15101.61SkreATF_TC_BODY(test, tc)							\
15111.61Skre{									\
15121.61Skre									\
15131.61Skre	traceme_vfork_raise(sig);					\
15141.40Skamil}
15151.40Skamil
15161.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
15171.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
15181.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
15191.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
15201.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
15211.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
15221.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
15231.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15241.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15251.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15261.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15271.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15281.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15291.40Skamil
15301.40Skamil/// ----------------------------------------------------------------------------
15311.40Skamil
15321.52Skamilstatic void
15331.52Skamiltraceme_vfork_crash(int sig)
15341.41Skamil{
15351.41Skamil	pid_t child, wpid;
15361.41Skamil#if defined(TWAIT_HAVE_STATUS)
15371.41Skamil	int status;
15381.41Skamil#endif
15391.41Skamil
15401.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15411.71Skamil	if (sig == SIGILL)
15421.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15431.71Skamil#endif
15441.71Skamil
15451.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
15461.114Skamil		atf_tc_skip("FP exceptions are not supported");
15471.114Skamil
15481.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15491.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15501.41Skamil	if (child == 0) {
15511.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15521.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15531.41Skamil
15541.52Skamil		DPRINTF("Before executing a trap\n");
15551.52Skamil		switch (sig) {
15561.52Skamil		case SIGTRAP:
15571.52Skamil			trigger_trap();
15581.52Skamil			break;
15591.52Skamil		case SIGSEGV:
15601.52Skamil			trigger_segv();
15611.52Skamil			break;
15621.52Skamil		case SIGILL:
15631.52Skamil			trigger_ill();
15641.52Skamil			break;
15651.52Skamil		case SIGFPE:
15661.52Skamil			trigger_fpe();
15671.52Skamil			break;
15681.52Skamil		case SIGBUS:
15691.52Skamil			trigger_bus();
15701.52Skamil			break;
15711.52Skamil		default:
15721.52Skamil			/* NOTREACHED */
15731.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15741.52Skamil		}
15751.41Skamil
15761.41Skamil		/* NOTREACHED */
15771.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15781.41Skamil	}
15791.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15801.41Skamil
15811.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15821.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15831.41Skamil
15841.52Skamil	validate_status_signaled(status, sig, 1);
15851.41Skamil
15861.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15871.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15881.41Skamil}
15891.41Skamil
15901.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15911.61SkreATF_TC(test);								\
15921.61SkreATF_TC_HEAD(test, tc)							\
15931.61Skre{									\
15941.61Skre	atf_tc_set_md_var(tc, "descr",					\
15951.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
15961.61Skre	    "vfork(2)ed child");					\
15971.61Skre}									\
15981.61Skre									\
15991.61SkreATF_TC_BODY(test, tc)							\
16001.61Skre{									\
16011.61Skre									\
16021.61Skre	traceme_vfork_crash(sig);					\
16031.52Skamil}
16041.52Skamil
16051.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
16061.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
16071.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
16081.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
16091.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
16101.52Skamil
16111.41Skamil/// ----------------------------------------------------------------------------
16121.41Skamil
16131.92Skamilstatic void
16141.92Skamiltraceme_vfork_signalmasked_crash(int sig)
16151.92Skamil{
16161.92Skamil	pid_t child, wpid;
16171.92Skamil#if defined(TWAIT_HAVE_STATUS)
16181.92Skamil	int status;
16191.92Skamil#endif
16201.92Skamil	sigset_t intmask;
16211.92Skamil
16221.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16231.92Skamil	if (sig == SIGILL)
16241.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16251.92Skamil#endif
16261.92Skamil
16271.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
16281.114Skamil		atf_tc_skip("FP exceptions are not supported");
16291.114Skamil
16301.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16311.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16321.92Skamil	if (child == 0) {
16331.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16341.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16351.92Skamil
16361.92Skamil		sigemptyset(&intmask);
16371.92Skamil		sigaddset(&intmask, sig);
16381.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16391.92Skamil
16401.92Skamil		DPRINTF("Before executing a trap\n");
16411.92Skamil		switch (sig) {
16421.92Skamil		case SIGTRAP:
16431.92Skamil			trigger_trap();
16441.92Skamil			break;
16451.92Skamil		case SIGSEGV:
16461.92Skamil			trigger_segv();
16471.92Skamil			break;
16481.92Skamil		case SIGILL:
16491.92Skamil			trigger_ill();
16501.92Skamil			break;
16511.92Skamil		case SIGFPE:
16521.92Skamil			trigger_fpe();
16531.92Skamil			break;
16541.92Skamil		case SIGBUS:
16551.92Skamil			trigger_bus();
16561.92Skamil			break;
16571.92Skamil		default:
16581.92Skamil			/* NOTREACHED */
16591.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16601.92Skamil		}
16611.92Skamil
16621.92Skamil		/* NOTREACHED */
16631.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16641.92Skamil	}
16651.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16661.92Skamil
16671.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16681.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16691.92Skamil
16701.92Skamil	validate_status_signaled(status, sig, 1);
16711.92Skamil
16721.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16731.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16741.92Skamil}
16751.92Skamil
16761.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16771.92SkamilATF_TC(test);								\
16781.92SkamilATF_TC_HEAD(test, tc)							\
16791.92Skamil{									\
16801.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16811.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16821.92Skamil	    "vfork(2)ed child with a masked signal");			\
16831.92Skamil}									\
16841.92Skamil									\
16851.92SkamilATF_TC_BODY(test, tc)							\
16861.92Skamil{									\
16871.92Skamil									\
16881.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16891.92Skamil}
16901.92Skamil
16911.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16921.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16931.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
16941.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
16951.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
16961.92Skamil
16971.92Skamil/// ----------------------------------------------------------------------------
16981.92Skamil
16991.92Skamilstatic void
17001.92Skamiltraceme_vfork_signalignored_crash(int sig)
17011.92Skamil{
17021.92Skamil	pid_t child, wpid;
17031.92Skamil#if defined(TWAIT_HAVE_STATUS)
17041.92Skamil	int status;
17051.92Skamil#endif
17061.92Skamil	struct sigaction sa;
17071.92Skamil
17081.92Skamil#ifndef PTRACE_ILLEGAL_ASM
17091.92Skamil	if (sig == SIGILL)
17101.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
17111.92Skamil#endif
17121.92Skamil
17131.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
17141.114Skamil		atf_tc_skip("FP exceptions are not supported");
17151.114Skamil
17161.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17171.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17181.92Skamil	if (child == 0) {
17191.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17201.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17211.92Skamil
17221.92Skamil		memset(&sa, 0, sizeof(sa));
17231.92Skamil		sa.sa_handler = SIG_IGN;
17241.92Skamil		sigemptyset(&sa.sa_mask);
17251.92Skamil
17261.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
17271.92Skamil
17281.92Skamil		DPRINTF("Before executing a trap\n");
17291.92Skamil		switch (sig) {
17301.92Skamil		case SIGTRAP:
17311.92Skamil			trigger_trap();
17321.92Skamil			break;
17331.92Skamil		case SIGSEGV:
17341.92Skamil			trigger_segv();
17351.92Skamil			break;
17361.92Skamil		case SIGILL:
17371.92Skamil			trigger_ill();
17381.92Skamil			break;
17391.92Skamil		case SIGFPE:
17401.92Skamil			trigger_fpe();
17411.92Skamil			break;
17421.92Skamil		case SIGBUS:
17431.92Skamil			trigger_bus();
17441.92Skamil			break;
17451.92Skamil		default:
17461.92Skamil			/* NOTREACHED */
17471.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17481.92Skamil		}
17491.92Skamil
17501.92Skamil		/* NOTREACHED */
17511.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17521.92Skamil	}
17531.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17541.92Skamil
17551.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17561.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17571.92Skamil
17581.92Skamil	validate_status_signaled(status, sig, 1);
17591.92Skamil
17601.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17611.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17621.92Skamil}
17631.92Skamil
17641.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17651.92SkamilATF_TC(test);								\
17661.92SkamilATF_TC_HEAD(test, tc)							\
17671.92Skamil{									\
17681.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17691.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17701.92Skamil	    "vfork(2)ed child with ignored signal");			\
17711.92Skamil}									\
17721.92Skamil									\
17731.92SkamilATF_TC_BODY(test, tc)							\
17741.92Skamil{									\
17751.92Skamil									\
17761.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17771.92Skamil}
17781.92Skamil
17791.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17801.92Skamil    SIGTRAP)
17811.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17821.92Skamil    SIGSEGV)
17831.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17841.92Skamil    SIGILL)
17851.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17861.92Skamil    SIGFPE)
17871.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17881.92Skamil    SIGBUS)
17891.92Skamil
17901.92Skamil/// ----------------------------------------------------------------------------
17911.92Skamil
17921.96Skamilstatic void
17931.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
17941.43Skamil{
17951.43Skamil	const int sigval = SIGTRAP;
17961.43Skamil	pid_t child, wpid;
17971.43Skamil#if defined(TWAIT_HAVE_STATUS)
17981.43Skamil	int status;
17991.43Skamil#endif
18001.96Skamil	struct sigaction sa;
18011.61Skre	struct ptrace_siginfo info;
18021.96Skamil	sigset_t intmask;
18031.96Skamil	struct kinfo_proc2 kp;
18041.96Skamil	size_t len = sizeof(kp);
18051.96Skamil
18061.96Skamil	int name[6];
18071.96Skamil	const size_t namelen = __arraycount(name);
18081.96Skamil	ki_sigset_t kp_sigmask;
18091.96Skamil	ki_sigset_t kp_sigignore;
18101.43Skamil
18111.43Skamil	memset(&info, 0, sizeof(info));
18121.43Skamil
18131.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
18141.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
18151.43Skamil	if (child == 0) {
18161.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18171.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18181.43Skamil
18191.96Skamil		if (masked) {
18201.96Skamil			sigemptyset(&intmask);
18211.96Skamil			sigaddset(&intmask, sigval);
18221.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
18231.96Skamil		}
18241.96Skamil
18251.96Skamil		if (ignored) {
18261.96Skamil			memset(&sa, 0, sizeof(sa));
18271.96Skamil			sa.sa_handler = SIG_IGN;
18281.96Skamil			sigemptyset(&sa.sa_mask);
18291.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
18301.96Skamil		}
18311.96Skamil
18321.43Skamil		DPRINTF("Before calling execve(2) from child\n");
18331.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
18341.43Skamil
18351.43Skamil		/* NOTREACHED */
18361.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18371.43Skamil	}
18381.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18391.43Skamil
18401.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18411.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18421.43Skamil
18431.43Skamil	validate_status_stopped(status, sigval);
18441.43Skamil
18451.96Skamil	name[0] = CTL_KERN,
18461.96Skamil	name[1] = KERN_PROC2,
18471.96Skamil	name[2] = KERN_PROC_PID;
18481.96Skamil	name[3] = getpid();
18491.96Skamil	name[4] = sizeof(kp);
18501.96Skamil	name[5] = 1;
18511.96Skamil
18521.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18531.96Skamil
18541.96Skamil	if (masked)
18551.96Skamil		kp_sigmask = kp.p_sigmask;
18561.96Skamil
18571.96Skamil	if (ignored)
18581.96Skamil		kp_sigignore = kp.p_sigignore;
18591.96Skamil
18601.96Skamil	name[3] = getpid();
18611.96Skamil
18621.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18631.96Skamil
18641.96Skamil	if (masked) {
18651.96Skamil		DPRINTF("kp_sigmask="
18661.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18671.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18681.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18691.96Skamil
18701.96Skamil	        DPRINTF("kp.p_sigmask="
18711.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18721.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18731.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18741.96Skamil
18751.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18761.96Skamil		    sizeof(kp_sigmask)));
18771.96Skamil	}
18781.96Skamil
18791.96Skamil	if (ignored) {
18801.96Skamil		DPRINTF("kp_sigignore="
18811.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18821.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18831.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18841.96Skamil
18851.96Skamil	        DPRINTF("kp.p_sigignore="
18861.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18871.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
18881.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
18891.96Skamil
18901.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
18911.96Skamil		    sizeof(kp_sigignore)));
18921.96Skamil	}
18931.96Skamil
18941.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
18951.61Skre	SYSCALL_REQUIRE(
18961.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
18971.43Skamil
18981.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
18991.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
19001.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
19011.43Skamil	    info.psi_siginfo.si_errno);
19021.43Skamil
19031.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
19041.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
19051.43Skamil
19061.43Skamil	DPRINTF("Before resuming the child process where it left off and "
19071.43Skamil	    "without signal to be sent\n");
19081.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19091.43Skamil
19101.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19111.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19121.43Skamil
19131.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19141.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19151.43Skamil}
19161.43Skamil
19171.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
19181.96SkamilATF_TC(test);								\
19191.96SkamilATF_TC_HEAD(test, tc)							\
19201.96Skamil{									\
19211.96Skamil	atf_tc_set_md_var(tc, "descr",					\
19221.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
19231.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
19241.96Skamil	    masked ? " with ignored signal" : "");			\
19251.96Skamil}									\
19261.96Skamil									\
19271.96SkamilATF_TC_BODY(test, tc)							\
19281.96Skamil{									\
19291.96Skamil									\
19301.96Skamil	traceme_vfork_exec(masked, ignored);				\
19311.96Skamil}
19321.96Skamil
19331.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
19341.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19351.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19361.96Skamil
19371.43Skamil/// ----------------------------------------------------------------------------
19381.43Skamil
19391.1Skamil#if defined(TWAIT_HAVE_PID)
19401.51Skamilstatic void
19411.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19421.59Skamil{
19431.94Skamil	const int sigval = SIGSTOP;
19441.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19451.59Skamil	const int exitval = 10;
19461.59Skamil	pid_t tracee, tracer, wpid;
19471.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19481.59Skamil#if defined(TWAIT_HAVE_STATUS)
19491.59Skamil	int status;
19501.59Skamil#endif
19511.94Skamil	struct sigaction sa;
19521.59Skamil	struct ptrace_siginfo info;
19531.94Skamil	sigset_t intmask;
19541.94Skamil	struct kinfo_proc2 kp;
19551.94Skamil	size_t len = sizeof(kp);
19561.94Skamil
19571.94Skamil	int name[6];
19581.94Skamil	const size_t namelen = __arraycount(name);
19591.94Skamil	ki_sigset_t kp_sigmask;
19601.94Skamil	ki_sigset_t kp_sigignore;
19611.61Skre
19621.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19631.71Skamil	if (sig == SIGILL)
19641.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19651.71Skamil#endif
19661.71Skamil
19671.114Skamil	if (sig == SIGFPE && !are_fpu_exceptions_supported())
19681.114Skamil		atf_tc_skip("FP exceptions are not supported");
19691.114Skamil
19701.59Skamil	memset(&info, 0, sizeof(info));
19711.59Skamil
19721.59Skamil	DPRINTF("Spawn tracee\n");
19731.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19741.59Skamil	tracee = atf_utils_fork();
19751.59Skamil	if (tracee == 0) {
19761.59Skamil		// Wait for parent to let us crash
19771.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19781.61Skre
19791.94Skamil		if (masked) {
19801.94Skamil			sigemptyset(&intmask);
19811.94Skamil			sigaddset(&intmask, sig);
19821.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19831.94Skamil		}
19841.94Skamil
19851.94Skamil		if (ignored) {
19861.94Skamil			memset(&sa, 0, sizeof(sa));
19871.94Skamil			sa.sa_handler = SIG_IGN;
19881.94Skamil			sigemptyset(&sa.sa_mask);
19891.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
19901.94Skamil		}
19911.94Skamil
19921.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19931.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19941.94Skamil
19951.59Skamil		DPRINTF("Before executing a trap\n");
19961.59Skamil		switch (sig) {
19971.59Skamil		case SIGTRAP:
19981.59Skamil			trigger_trap();
19991.59Skamil			break;
20001.59Skamil		case SIGSEGV:
20011.59Skamil			trigger_segv();
20021.59Skamil			break;
20031.59Skamil		case SIGILL:
20041.59Skamil			trigger_ill();
20051.59Skamil			break;
20061.59Skamil		case SIGFPE:
20071.59Skamil			trigger_fpe();
20081.59Skamil			break;
20091.59Skamil		case SIGBUS:
20101.59Skamil			trigger_bus();
20111.59Skamil			break;
20121.59Skamil		default:
20131.59Skamil			/* NOTREACHED */
20141.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
20151.59Skamil		}
20161.59Skamil
20171.59Skamil		/* NOTREACHED */
20181.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
20191.59Skamil	}
20201.59Skamil
20211.59Skamil	DPRINTF("Spawn debugger\n");
20221.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
20231.59Skamil	tracer = atf_utils_fork();
20241.59Skamil	if (tracer == 0) {
20251.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
20261.59Skamil		tracer = atf_utils_fork();
20271.59Skamil		if (tracer != 0)
20281.61Skre			_exit(exitval);
20291.59Skamil
20301.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
20311.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
20321.59Skamil
20331.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
20341.59Skamil		FORKEE_REQUIRE_SUCCESS(
20351.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20361.59Skamil
20371.59Skamil		forkee_status_stopped(status, SIGSTOP);
20381.59Skamil
20391.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20401.94Skamil		    "traced process\n");
20411.94Skamil		SYSCALL_REQUIRE(
20421.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20431.94Skamil
20441.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20451.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20461.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20471.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20481.94Skamil
20491.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20501.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20511.94Skamil
20521.59Skamil		/* Resume tracee with PT_CONTINUE */
20531.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20541.59Skamil
20551.59Skamil		/* Inform parent that tracer has attached to tracee */
20561.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20571.59Skamil
20581.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20591.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20601.59Skamil
20611.59Skamil		/* Wait for tracee and assert that it exited */
20621.59Skamil		FORKEE_REQUIRE_SUCCESS(
20631.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20641.59Skamil
20651.94Skamil		forkee_status_stopped(status, sigval);
20661.94Skamil
20671.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20681.94Skamil		    "traced process\n");
20691.94Skamil		SYSCALL_REQUIRE(
20701.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20711.94Skamil
20721.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20731.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20741.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20751.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20761.94Skamil
20771.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20781.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20791.94Skamil
20801.94Skamil		name[0] = CTL_KERN,
20811.94Skamil		name[1] = KERN_PROC2,
20821.94Skamil		name[2] = KERN_PROC_PID;
20831.94Skamil		name[3] = tracee;
20841.94Skamil		name[4] = sizeof(kp);
20851.94Skamil		name[5] = 1;
20861.94Skamil
20871.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20881.94Skamil
20891.94Skamil		if (masked)
20901.94Skamil			kp_sigmask = kp.p_sigmask;
20911.94Skamil
20921.94Skamil		if (ignored)
20931.94Skamil			kp_sigignore = kp.p_sigignore;
20941.94Skamil
20951.94Skamil		/* Resume tracee with PT_CONTINUE */
20961.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20971.94Skamil
20981.94Skamil		/* Wait for tracee and assert that it exited */
20991.94Skamil		FORKEE_REQUIRE_SUCCESS(
21001.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21011.94Skamil
21021.93Skamil		forkee_status_stopped(status, sig);
21031.59Skamil
21041.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
21051.61Skre		    "traced process\n");
21061.61Skre		SYSCALL_REQUIRE(
21071.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
21081.59Skamil
21091.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
21101.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
21111.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
21121.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
21131.59Skamil
21141.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
21151.94Skamil
21161.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
21171.94Skamil
21181.94Skamil		if (masked) {
21191.94Skamil			DPRINTF("kp_sigmask="
21201.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21211.94Skamil			    PRIx32 "\n",
21221.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
21231.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
21241.94Skamil
21251.94Skamil			DPRINTF("kp.p_sigmask="
21261.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21271.94Skamil			    PRIx32 "\n",
21281.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
21291.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
21301.94Skamil
21311.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
21321.94Skamil			    sizeof(kp_sigmask)));
21331.94Skamil		}
21341.94Skamil
21351.94Skamil		if (ignored) {
21361.94Skamil			DPRINTF("kp_sigignore="
21371.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21381.94Skamil			    PRIx32 "\n",
21391.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21401.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21411.94Skamil
21421.94Skamil			DPRINTF("kp.p_sigignore="
21431.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21441.94Skamil			    PRIx32 "\n",
21451.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21461.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21471.94Skamil
21481.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21491.94Skamil			    sizeof(kp_sigignore)));
21501.94Skamil		}
21511.94Skamil
21521.59Skamil		switch (sig) {
21531.59Skamil		case SIGTRAP:
21541.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21551.59Skamil			break;
21561.59Skamil		case SIGSEGV:
21571.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21581.59Skamil			break;
21591.71Skamil		case SIGILL:
21601.113Skamil			FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC &&
21611.112Skamil			            info.psi_siginfo.si_code <= ILL_BADSTK);
21621.71Skamil			break;
21631.59Skamil		case SIGFPE:
21641.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21651.59Skamil			break;
21661.59Skamil		case SIGBUS:
21671.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21681.59Skamil			break;
21691.59Skamil		}
21701.59Skamil
21711.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21721.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21731.93Skamil		FORKEE_REQUIRE_SUCCESS(
21741.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21751.59Skamil
21761.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21771.59Skamil
21781.71Skamil		/* Inform parent that tracer is exiting normally */
21791.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21801.71Skamil
21811.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21821.59Skamil		_exit(0 /* collect by initproc */);
21831.59Skamil	}
21841.59Skamil
21851.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21861.59Skamil	    "calling %s()\n", TWAIT_FNAME);
21871.59Skamil	TWAIT_REQUIRE_SUCCESS(
21881.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21891.59Skamil
21901.59Skamil	validate_status_exited(status, exitval);
21911.59Skamil
21921.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
21931.59Skamil	    TWAIT_FNAME);
21941.59Skamil	TWAIT_REQUIRE_SUCCESS(
21951.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
21961.59Skamil
21971.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
21981.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
21991.59Skamil
22001.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
22011.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
22021.59Skamil
22031.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
22041.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
22051.59Skamil
22061.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
22071.59Skamil	    TWAIT_FNAME);
22081.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22091.59Skamil
22101.59Skamil	validate_status_signaled(status, SIGKILL, 0);
22111.59Skamil
22121.71Skamil	DPRINTF("Await normal exit of tracer\n");
22131.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
22141.71Skamil
22151.59Skamil	msg_close(&parent_tracer);
22161.59Skamil	msg_close(&parent_tracee);
22171.59Skamil}
22181.59Skamil
22191.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
22201.61SkreATF_TC(test);								\
22211.61SkreATF_TC_HEAD(test, tc)							\
22221.61Skre{									\
22231.61Skre	atf_tc_set_md_var(tc, "descr",					\
22241.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22251.94Skamil	    "the debuggee");						\
22261.61Skre}									\
22271.61Skre									\
22281.61SkreATF_TC_BODY(test, tc)							\
22291.61Skre{									\
22301.61Skre									\
22311.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
22321.59Skamil}
22331.59Skamil
22341.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
22351.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
22361.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
22371.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
22381.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22391.94Skamil
22401.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22411.94SkamilATF_TC(test);								\
22421.94SkamilATF_TC_HEAD(test, tc)							\
22431.94Skamil{									\
22441.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22451.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22461.94Skamil	    "the debuggee with masked signal");				\
22471.94Skamil}									\
22481.94Skamil									\
22491.94SkamilATF_TC_BODY(test, tc)							\
22501.94Skamil{									\
22511.94Skamil									\
22521.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22531.94Skamil}
22541.94Skamil
22551.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22561.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22571.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22581.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22591.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22601.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22611.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22621.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22631.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22641.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22651.94Skamil
22661.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22671.94SkamilATF_TC(test);								\
22681.94SkamilATF_TC_HEAD(test, tc)							\
22691.94Skamil{									\
22701.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22711.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22721.94Skamil	    "the debuggee with signal ignored");			\
22731.94Skamil}									\
22741.94Skamil									\
22751.94SkamilATF_TC_BODY(test, tc)							\
22761.94Skamil{									\
22771.94Skamil									\
22781.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22791.94Skamil}
22801.94Skamil
22811.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22821.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22831.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22841.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22851.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22861.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
22871.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22881.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
22891.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22901.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
22911.59Skamil#endif
22921.59Skamil
22931.59Skamil/// ----------------------------------------------------------------------------
22941.59Skamil
22951.59Skamil#if defined(TWAIT_HAVE_PID)
22961.59Skamilstatic void
22971.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
22981.67Skamil                                             bool stopped)
22991.1Skamil{
23001.51Skamil	/*
23011.51Skamil	 * notimeout - disable timeout in await zombie function
23021.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
23031.67Skamil	 * stopped - attach to a stopped process
23041.51Skamil	 */
23051.1Skamil
23061.1Skamil	struct msg_fds parent_tracee, parent_tracer;
23071.1Skamil	const int exitval_tracee = 5;
23081.1Skamil	const int exitval_tracer = 10;
23091.1Skamil	pid_t tracee, tracer, wpid;
23101.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
23111.1Skamil#if defined(TWAIT_HAVE_STATUS)
23121.1Skamil	int status;
23131.1Skamil#endif
23141.1Skamil
23151.67Skamil	/*
23161.67Skamil	 * Only a subset of options are supported.
23171.67Skamil	 */
23181.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
23191.67Skamil	            (!notimeout && unrelated && !stopped) ||
23201.67Skamil	            (notimeout && !unrelated && !stopped) ||
23211.67Skamil	            (!notimeout && unrelated && stopped));
23221.67Skamil
23231.13Schristos	DPRINTF("Spawn tracee\n");
23241.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
23251.1Skamil	tracee = atf_utils_fork();
23261.1Skamil	if (tracee == 0) {
23271.67Skamil		if (stopped) {
23281.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
23291.67Skamil			raise(SIGSTOP);
23301.67Skamil		}
23311.67Skamil
23321.1Skamil		// Wait for parent to let us exit
23331.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
23341.1Skamil		_exit(exitval_tracee);
23351.1Skamil	}
23361.1Skamil
23371.13Schristos	DPRINTF("Spawn debugger\n");
23381.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23391.1Skamil	tracer = atf_utils_fork();
23401.1Skamil	if (tracer == 0) {
23411.51Skamil		if(unrelated) {
23421.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23431.51Skamil			tracer = atf_utils_fork();
23441.51Skamil			if (tracer != 0)
23451.51Skamil				_exit(exitval_tracer);
23461.51Skamil		}
23471.51Skamil
23481.67Skamil		if (stopped) {
23491.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23501.67Skamil			await_stopped(tracee);
23511.67Skamil		}
23521.67Skamil
23531.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23541.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23551.1Skamil
23561.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23571.1Skamil		FORKEE_REQUIRE_SUCCESS(
23581.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23591.1Skamil
23601.1Skamil		forkee_status_stopped(status, SIGSTOP);
23611.1Skamil
23621.1Skamil		/* Resume tracee with PT_CONTINUE */
23631.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23641.1Skamil
23651.1Skamil		/* Inform parent that tracer has attached to tracee */
23661.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23671.1Skamil
23681.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23691.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23701.1Skamil
23711.1Skamil		/* Wait for tracee and assert that it exited */
23721.1Skamil		FORKEE_REQUIRE_SUCCESS(
23731.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23741.1Skamil
23751.1Skamil		forkee_status_exited(status, exitval_tracee);
23761.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23771.1Skamil
23781.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23791.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23801.51Skamil	}
23811.51Skamil
23821.51Skamil	if (unrelated) {
23831.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23841.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23851.51Skamil		TWAIT_REQUIRE_SUCCESS(
23861.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23871.51Skamil
23881.51Skamil		validate_status_exited(status, exitval_tracer);
23891.51Skamil
23901.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
23911.51Skamil		    TWAIT_FNAME);
23921.51Skamil		TWAIT_REQUIRE_SUCCESS(
23931.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
23941.1Skamil	}
23951.1Skamil
23961.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
23971.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
23981.1Skamil
23991.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
24001.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
24011.1Skamil
24021.13Schristos	DPRINTF("Detect that tracee is zombie\n");
24031.51Skamil	if (notimeout)
24041.26Skamil		await_zombie_raw(tracee, 0);
24051.26Skamil	else
24061.26Skamil		await_zombie(tracee);
24071.1Skamil
24081.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
24091.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
24101.1Skamil	    TWAIT_FNAME);
24111.1Skamil	TWAIT_REQUIRE_SUCCESS(
24121.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
24131.1Skamil
24141.51Skamil	if (unrelated) {
24151.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
24161.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
24171.51Skamil	} else {
24181.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
24191.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
24201.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
24211.59Skamil			"%s()\n", TWAIT_FNAME);
24221.51Skamil
24231.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
24241.59Skamil			"tracee\n");
24251.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
24261.51Skamil		    tracer);
24271.1Skamil
24281.51Skamil		validate_status_exited(status, exitval_tracer);
24291.51Skamil	}
24301.1Skamil
24311.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
24321.1Skamil	    TWAIT_FNAME);
24331.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
24341.1Skamil
24351.1Skamil	validate_status_exited(status, exitval_tracee);
24361.1Skamil
24371.1Skamil	msg_close(&parent_tracer);
24381.1Skamil	msg_close(&parent_tracee);
24391.1Skamil}
24401.26Skamil
24411.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24421.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24431.51Skamil{
24441.51Skamil	atf_tc_set_md_var(tc, "descr",
24451.51Skamil	    "Assert that tracer sees process termination before the parent");
24461.51Skamil}
24471.51Skamil
24481.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24491.26Skamil{
24501.26Skamil
24511.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24521.26Skamil}
24531.26Skamil
24541.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24551.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24561.1Skamil{
24571.1Skamil	atf_tc_set_md_var(tc, "descr",
24581.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24591.51Skamil	    "process and no other error is reported");
24601.1Skamil}
24611.1Skamil
24621.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24631.1Skamil{
24641.51Skamil	time_t start, end;
24651.51Skamil	double diff;
24661.51Skamil	unsigned long N = 0;
24671.1Skamil
24681.51Skamil	/*
24691.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24701.51Skamil	 * This test body isn't specific to this race, however it's just good
24711.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24721.51Skamil	 */
24731.1Skamil
24741.51Skamil	start = time(NULL);
24751.51Skamil	while (true) {
24761.51Skamil		DPRINTF("Step: %lu\n", N);
24771.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24781.67Skamil		                                             false);
24791.51Skamil		end = time(NULL);
24801.51Skamil		diff = difftime(end, start);
24811.51Skamil		if (diff >= 5.0)
24821.51Skamil			break;
24831.51Skamil		++N;
24841.1Skamil	}
24851.51Skamil	DPRINTF("Iterations: %lu\n", N);
24861.51Skamil}
24871.1Skamil
24881.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
24891.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24901.51Skamil{
24911.51Skamil	atf_tc_set_md_var(tc, "descr",
24921.51Skamil	    "Assert that tracer sees process termination before the parent");
24931.51Skamil}
24941.1Skamil
24951.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24961.51Skamil{
24971.1Skamil
24981.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
24991.67Skamil}
25001.67Skamil
25011.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
25021.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
25031.67Skamil{
25041.67Skamil	atf_tc_set_md_var(tc, "descr",
25051.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
25061.67Skamil}
25071.67Skamil
25081.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
25091.67Skamil{
25101.67Skamil
25111.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
25121.1Skamil}
25131.1Skamil#endif
25141.1Skamil
25151.51Skamil/// ----------------------------------------------------------------------------
25161.51Skamil
25171.66Skamilstatic void
25181.66Skamilparent_attach_to_its_child(bool stopped)
25191.1Skamil{
25201.1Skamil	struct msg_fds parent_tracee;
25211.1Skamil	const int exitval_tracee = 5;
25221.1Skamil	pid_t tracee, wpid;
25231.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25241.1Skamil#if defined(TWAIT_HAVE_STATUS)
25251.1Skamil	int status;
25261.1Skamil#endif
25271.1Skamil
25281.13Schristos	DPRINTF("Spawn tracee\n");
25291.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25301.1Skamil	tracee = atf_utils_fork();
25311.1Skamil	if (tracee == 0) {
25321.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25331.13Schristos		DPRINTF("Parent should now attach to tracee\n");
25341.1Skamil
25351.66Skamil		if (stopped) {
25361.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
25371.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
25381.66Skamil		}
25391.66Skamil
25401.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25411.1Skamil		/* Wait for message from the parent */
25421.1Skamil		_exit(exitval_tracee);
25431.1Skamil	}
25441.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25451.57Skamil
25461.66Skamil	if (stopped) {
25471.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25481.66Skamil		await_stopped(tracee);
25491.66Skamil	}
25501.66Skamil
25511.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25531.1Skamil
25541.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25551.1Skamil	    TWAIT_FNAME);
25561.1Skamil	TWAIT_REQUIRE_SUCCESS(
25571.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25581.1Skamil
25591.1Skamil	validate_status_stopped(status, SIGSTOP);
25601.1Skamil
25611.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25631.1Skamil
25641.13Schristos	DPRINTF("Let the tracee exit now\n");
25651.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25661.1Skamil
25671.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25681.1Skamil	TWAIT_REQUIRE_SUCCESS(
25691.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25701.1Skamil
25711.1Skamil	validate_status_exited(status, exitval_tracee);
25721.1Skamil
25731.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25751.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25761.1Skamil
25771.1Skamil	msg_close(&parent_tracee);
25781.1Skamil}
25791.1Skamil
25801.66SkamilATF_TC(parent_attach_to_its_child);
25811.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25821.66Skamil{
25831.66Skamil	atf_tc_set_md_var(tc, "descr",
25841.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25851.66Skamil}
25861.66Skamil
25871.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
25881.66Skamil{
25891.66Skamil
25901.66Skamil	parent_attach_to_its_child(false);
25911.66Skamil}
25921.66Skamil
25931.66SkamilATF_TC(parent_attach_to_its_stopped_child);
25941.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
25951.66Skamil{
25961.66Skamil	atf_tc_set_md_var(tc, "descr",
25971.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
25981.66Skamil}
25991.66Skamil
26001.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
26011.66Skamil{
26021.66Skamil
26031.66Skamil	parent_attach_to_its_child(true);
26041.66Skamil}
26051.66Skamil
26061.51Skamil/// ----------------------------------------------------------------------------
26071.51Skamil
26081.65Skamilstatic void
26091.65Skamilchild_attach_to_its_parent(bool stopped)
26101.1Skamil{
26111.1Skamil	struct msg_fds parent_tracee;
26121.1Skamil	const int exitval_tracer = 5;
26131.1Skamil	pid_t tracer, wpid;
26141.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
26151.1Skamil#if defined(TWAIT_HAVE_STATUS)
26161.1Skamil	int status;
26171.1Skamil#endif
26181.1Skamil
26191.13Schristos	DPRINTF("Spawn tracer\n");
26201.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
26211.1Skamil	tracer = atf_utils_fork();
26221.1Skamil	if (tracer == 0) {
26231.1Skamil		/* Wait for message from the parent */
26241.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
26251.1Skamil
26261.65Skamil		if (stopped) {
26271.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
26281.65Skamil			        getppid());
26291.65Skamil			await_stopped(getppid());
26301.65Skamil		}
26311.65Skamil
26321.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
26331.1Skamil		    getppid());
26341.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
26351.1Skamil
26361.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
26371.1Skamil		    TWAIT_FNAME);
26381.1Skamil		FORKEE_REQUIRE_SUCCESS(
26391.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26401.1Skamil
26411.1Skamil		forkee_status_stopped(status, SIGSTOP);
26421.1Skamil
26431.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26441.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26451.1Skamil		    != -1);
26461.1Skamil
26471.1Skamil		/* Tell parent we are ready */
26481.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26491.1Skamil
26501.1Skamil		_exit(exitval_tracer);
26511.1Skamil	}
26521.1Skamil
26531.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26541.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26551.65Skamil
26561.65Skamil	if (stopped) {
26571.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26581.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26591.65Skamil	}
26601.65Skamil
26611.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26621.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26631.1Skamil
26641.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26651.1Skamil	TWAIT_REQUIRE_SUCCESS(
26661.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26671.1Skamil
26681.1Skamil	validate_status_exited(status, exitval_tracer);
26691.1Skamil
26701.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26721.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26731.1Skamil
26741.1Skamil	msg_close(&parent_tracee);
26751.1Skamil}
26761.1Skamil
26771.65SkamilATF_TC(child_attach_to_its_parent);
26781.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26791.65Skamil{
26801.65Skamil	atf_tc_set_md_var(tc, "descr",
26811.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26821.65Skamil}
26831.65Skamil
26841.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26851.65Skamil{
26861.65Skamil
26871.65Skamil	child_attach_to_its_parent(false);
26881.65Skamil}
26891.65Skamil
26901.65SkamilATF_TC(child_attach_to_its_stopped_parent);
26911.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
26921.65Skamil{
26931.65Skamil	atf_tc_set_md_var(tc, "descr",
26941.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
26951.65Skamil}
26961.65Skamil
26971.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
26981.65Skamil{
26991.65Skamil	/*
27001.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
27011.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
27021.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
27031.65Skamil	 *
27041.65Skamil	 * As a workaround spawn this test as a subprocess.
27051.65Skamil	 */
27061.65Skamil
27071.65Skamil	const int exitval = 15;
27081.65Skamil	pid_t child, wpid;
27091.65Skamil#if defined(TWAIT_HAVE_STATUS)
27101.65Skamil	int status;
27111.65Skamil#endif
27121.65Skamil
27131.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
27141.65Skamil	if (child == 0) {
27151.65Skamil		child_attach_to_its_parent(true);
27161.65Skamil		_exit(exitval);
27171.65Skamil	} else {
27181.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27191.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27201.65Skamil
27211.65Skamil		validate_status_exited(status, exitval);
27221.65Skamil
27231.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
27241.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27251.65Skamil	}
27261.65Skamil}
27271.65Skamil
27281.51Skamil/// ----------------------------------------------------------------------------
27291.51Skamil
27301.1Skamil#if defined(TWAIT_HAVE_PID)
27311.1Skamil
27321.51Skamilenum tracee_sees_its_original_parent_type {
27331.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
27341.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
27351.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
27361.51Skamil};
27371.51Skamil
27381.51Skamilstatic void
27391.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27401.1Skamil{
27411.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27421.1Skamil	const int exitval_tracee = 5;
27431.1Skamil	const int exitval_tracer = 10;
27441.1Skamil	pid_t parent, tracee, tracer, wpid;
27451.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27461.1Skamil#if defined(TWAIT_HAVE_STATUS)
27471.1Skamil	int status;
27481.1Skamil#endif
27491.51Skamil	/* sysctl(3) - kinfo_proc2 */
27501.51Skamil	int name[CTL_MAXNAME];
27511.51Skamil	struct kinfo_proc2 kp;
27521.51Skamil	size_t len = sizeof(kp);
27531.51Skamil	unsigned int namelen;
27541.51Skamil
27551.51Skamil	/* procfs - status  */
27561.51Skamil	FILE *fp;
27571.51Skamil	struct stat st;
27581.51Skamil	const char *fname = "/proc/curproc/status";
27591.51Skamil	char s_executable[MAXPATHLEN];
27601.51Skamil	int s_pid, s_ppid;
27611.51Skamil	int rv;
27621.51Skamil
27631.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27641.61Skre		SYSCALL_REQUIRE(
27651.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27661.61Skre		if (rv != 0)
27671.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27681.51Skamil	}
27691.1Skamil
27701.13Schristos	DPRINTF("Spawn tracee\n");
27711.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27721.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27731.1Skamil	tracee = atf_utils_fork();
27741.1Skamil	if (tracee == 0) {
27751.1Skamil		parent = getppid();
27761.1Skamil
27771.1Skamil		/* Emit message to the parent */
27781.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27791.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27801.1Skamil
27811.51Skamil		switch (type) {
27821.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27831.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27841.51Skamil			break;
27851.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27861.51Skamil			namelen = 0;
27871.51Skamil			name[namelen++] = CTL_KERN;
27881.51Skamil			name[namelen++] = KERN_PROC2;
27891.51Skamil			name[namelen++] = KERN_PROC_PID;
27901.51Skamil			name[namelen++] = getpid();
27911.51Skamil			name[namelen++] = len;
27921.51Skamil			name[namelen++] = 1;
27931.51Skamil
27941.61Skre			FORKEE_ASSERT_EQ(
27951.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
27961.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
27971.51Skamil			break;
27981.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
27991.51Skamil			/*
28001.51Skamil			 * Format:
28011.51Skamil			 *  EXECUTABLE PID PPID ...
28021.51Skamil			 */
28031.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
28041.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
28051.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
28061.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
28071.51Skamil			break;
28081.51Skamil		}
28091.1Skamil
28101.1Skamil		_exit(exitval_tracee);
28111.1Skamil	}
28121.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
28131.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
28141.1Skamil
28151.13Schristos	DPRINTF("Spawn debugger\n");
28161.1Skamil	tracer = atf_utils_fork();
28171.1Skamil	if (tracer == 0) {
28181.1Skamil		/* No IPC to communicate with the child */
28191.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
28201.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
28211.1Skamil
28221.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
28231.1Skamil		FORKEE_REQUIRE_SUCCESS(
28241.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28251.1Skamil
28261.1Skamil		forkee_status_stopped(status, SIGSTOP);
28271.1Skamil
28281.1Skamil		/* Resume tracee with PT_CONTINUE */
28291.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
28301.1Skamil
28311.1Skamil		/* Inform parent that tracer has attached to tracee */
28321.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
28331.1Skamil
28341.1Skamil		/* Wait for parent to tell use that tracee should have exited */
28351.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
28361.1Skamil
28371.1Skamil		/* Wait for tracee and assert that it exited */
28381.1Skamil		FORKEE_REQUIRE_SUCCESS(
28391.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28401.1Skamil
28411.1Skamil		forkee_status_exited(status, exitval_tracee);
28421.1Skamil
28431.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28441.1Skamil		_exit(exitval_tracer);
28451.1Skamil	}
28461.1Skamil
28471.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28481.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28491.1Skamil
28501.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28511.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28521.1Skamil
28531.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28541.1Skamil	await_zombie(tracee);
28551.1Skamil
28561.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28571.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28581.1Skamil	TWAIT_REQUIRE_SUCCESS(
28591.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28601.1Skamil
28611.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28621.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28631.1Skamil
28641.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28661.1Skamil	    tracer);
28671.1Skamil
28681.1Skamil	validate_status_exited(status, exitval_tracer);
28691.1Skamil
28701.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28711.1Skamil	    TWAIT_FNAME);
28721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28731.1Skamil	    tracee);
28741.1Skamil
28751.1Skamil	validate_status_exited(status, exitval_tracee);
28761.1Skamil
28771.1Skamil	msg_close(&parent_tracer);
28781.1Skamil	msg_close(&parent_tracee);
28791.1Skamil}
28801.1Skamil
28811.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28821.61SkreATF_TC(test);								\
28831.61SkreATF_TC_HEAD(test, tc)							\
28841.61Skre{									\
28851.61Skre	atf_tc_set_md_var(tc, "descr",					\
28861.61Skre	    "Assert that tracee sees its original parent when being traced " \
28871.61Skre	    "(check " descr ")");					\
28881.61Skre}									\
28891.61Skre									\
28901.61SkreATF_TC_BODY(test, tc)							\
28911.61Skre{									\
28921.61Skre									\
28931.61Skre	tracee_sees_its_original_parent(type);				\
28941.1Skamil}
28951.1Skamil
28961.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28971.51Skamil	tracee_sees_its_original_parent_getppid,
28981.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
28991.51Skamil	"getppid(2)");
29001.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29011.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
29021.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
29031.51Skamil	"sysctl(3) and kinfo_proc2");
29041.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
29051.51Skamil	tracee_sees_its_original_parent_procfs_status,
29061.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
29071.51Skamil	"the status file in procfs");
29081.1Skamil#endif
29091.1Skamil
29101.51Skamil/// ----------------------------------------------------------------------------
29111.1Skamil
29121.53Skamilstatic void
29131.53Skamileventmask_preserved(int event)
29141.1Skamil{
29151.1Skamil	const int exitval = 5;
29161.1Skamil	const int sigval = SIGSTOP;
29171.1Skamil	pid_t child, wpid;
29181.1Skamil#if defined(TWAIT_HAVE_STATUS)
29191.1Skamil	int status;
29201.1Skamil#endif
29211.1Skamil	ptrace_event_t set_event, get_event;
29221.1Skamil	const int len = sizeof(ptrace_event_t);
29231.1Skamil
29241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29261.1Skamil	if (child == 0) {
29271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29291.1Skamil
29301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29321.1Skamil
29331.13Schristos		DPRINTF("Before exiting of the child process\n");
29341.1Skamil		_exit(exitval);
29351.1Skamil	}
29361.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29371.1Skamil
29381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29401.1Skamil
29411.1Skamil	validate_status_stopped(status, sigval);
29421.1Skamil
29431.53Skamil	set_event.pe_set_event = event;
29441.61Skre	SYSCALL_REQUIRE(
29451.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29461.61Skre	SYSCALL_REQUIRE(
29471.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29481.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29491.1Skamil
29501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29511.1Skamil	    "without signal to be sent\n");
29521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29531.1Skamil
29541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29561.1Skamil
29571.1Skamil	validate_status_exited(status, exitval);
29581.1Skamil
29591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29611.1Skamil}
29621.1Skamil
29631.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29641.61SkreATF_TC(test);								\
29651.61SkreATF_TC_HEAD(test, tc)							\
29661.61Skre{									\
29671.61Skre	atf_tc_set_md_var(tc, "descr",					\
29681.61Skre	    "Verify that eventmask " #event " is preserved");		\
29691.61Skre}									\
29701.61Skre									\
29711.61SkreATF_TC_BODY(test, tc)							\
29721.61Skre{									\
29731.61Skre									\
29741.61Skre	eventmask_preserved(event);					\
29751.1Skamil}
29761.1Skamil
29771.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29781.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29791.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29801.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29811.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29821.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29831.1Skamil
29841.53Skamil/// ----------------------------------------------------------------------------
29851.1Skamil
29861.28Skamilstatic void
29871.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
29881.105Skamil    bool trackvforkdone)
29891.1Skamil{
29901.1Skamil	const int exitval = 5;
29911.1Skamil	const int exitval2 = 15;
29921.1Skamil	const int sigval = SIGSTOP;
29931.31Skamil	pid_t child, child2 = 0, wpid;
29941.1Skamil#if defined(TWAIT_HAVE_STATUS)
29951.1Skamil	int status;
29961.1Skamil#endif
29971.1Skamil	ptrace_state_t state;
29981.1Skamil	const int slen = sizeof(state);
29991.1Skamil	ptrace_event_t event;
30001.1Skamil	const int elen = sizeof(event);
30011.1Skamil
30021.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30031.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30041.1Skamil	if (child == 0) {
30051.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30061.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30071.1Skamil
30081.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30091.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30101.1Skamil
30111.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
30121.1Skamil
30131.1Skamil		if (child2 == 0)
30141.1Skamil			_exit(exitval2);
30151.1Skamil
30161.1Skamil		FORKEE_REQUIRE_SUCCESS
30171.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30181.1Skamil
30191.1Skamil		forkee_status_exited(status, exitval2);
30201.1Skamil
30211.13Schristos		DPRINTF("Before exiting of the child process\n");
30221.1Skamil		_exit(exitval);
30231.1Skamil	}
30241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30251.1Skamil
30261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30281.1Skamil
30291.1Skamil	validate_status_stopped(status, sigval);
30301.1Skamil
30311.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
30321.61Skre	    trackfork ? "|PTRACE_FORK" : "",
30331.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
30341.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
30351.30Skamil	event.pe_set_event = 0;
30361.30Skamil	if (trackfork)
30371.30Skamil		event.pe_set_event |= PTRACE_FORK;
30381.30Skamil	if (trackvfork)
30391.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30401.30Skamil	if (trackvforkdone)
30411.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30431.1Skamil
30441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30451.1Skamil	    "without signal to be sent\n");
30461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30471.1Skamil
30481.29Skamil#if defined(TWAIT_HAVE_PID)
30491.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30501.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30511.61Skre		    child);
30521.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30531.61Skre		    child);
30541.1Skamil
30551.29Skamil		validate_status_stopped(status, SIGTRAP);
30561.1Skamil
30571.61Skre		SYSCALL_REQUIRE(
30581.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30591.31Skamil		if (trackfork && fn == fork) {
30601.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30611.30Skamil			       PTRACE_FORK);
30621.30Skamil		}
30631.31Skamil		if (trackvfork && fn == vfork) {
30641.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30651.30Skamil			       PTRACE_VFORK);
30661.30Skamil		}
30671.29Skamil
30681.29Skamil		child2 = state.pe_other_pid;
30691.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
30701.29Skamil
30711.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
30721.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
30731.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
30741.29Skamil		    child2);
30751.1Skamil
30761.29Skamil		validate_status_stopped(status, SIGTRAP);
30771.1Skamil
30781.61Skre		SYSCALL_REQUIRE(
30791.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
30801.31Skamil		if (trackfork && fn == fork) {
30811.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30821.30Skamil			       PTRACE_FORK);
30831.30Skamil		}
30841.31Skamil		if (trackvfork && fn == vfork) {
30851.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30861.30Skamil			       PTRACE_VFORK);
30871.30Skamil		}
30881.30Skamil
30891.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
30901.29Skamil
30911.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
30921.29Skamil		    "and without signal to be sent\n");
30931.61Skre		SYSCALL_REQUIRE(
30941.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
30951.29Skamil
30961.29Skamil		DPRINTF("Before resuming the child process where it left off "
30971.61Skre		    "and without signal to be sent\n");
30981.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30991.30Skamil	}
31001.30Skamil#endif
31011.30Skamil
31021.31Skamil	if (trackvforkdone && fn == vfork) {
31031.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
31041.61Skre		    child);
31051.61Skre		TWAIT_REQUIRE_SUCCESS(
31061.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
31071.30Skamil
31081.30Skamil		validate_status_stopped(status, SIGTRAP);
31091.30Skamil
31101.61Skre		SYSCALL_REQUIRE(
31111.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
31121.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
31131.30Skamil
31141.30Skamil		child2 = state.pe_other_pid;
31151.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
31161.61Skre		    child2);
31171.30Skamil
31181.30Skamil		DPRINTF("Before resuming the child process where it left off "
31191.61Skre		    "and without signal to be sent\n");
31201.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31211.30Skamil	}
31221.29Skamil
31231.30Skamil#if defined(TWAIT_HAVE_PID)
31241.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
31251.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
31261.61Skre		    "\n", TWAIT_FNAME);
31271.61Skre		TWAIT_REQUIRE_SUCCESS(
31281.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
31291.29Skamil
31301.29Skamil		validate_status_exited(status, exitval2);
31311.29Skamil
31321.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
31331.61Skre		    "process\n", TWAIT_FNAME);
31341.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
31351.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
31361.29Skamil	}
31371.29Skamil#endif
31381.1Skamil
31391.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31401.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31421.1Skamil
31431.1Skamil	validate_status_stopped(status, SIGCHLD);
31441.1Skamil
31451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31461.1Skamil	    "without signal to be sent\n");
31471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31481.1Skamil
31491.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31501.1Skamil	    TWAIT_FNAME);
31511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31521.1Skamil
31531.1Skamil	validate_status_exited(status, exitval);
31541.1Skamil
31551.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31561.1Skamil	    TWAIT_FNAME);
31571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31581.1Skamil}
31591.28Skamil
31601.105Skamil#define FORK_TEST(name,fun,tfork,tvfork,tvforkdone)			\
31611.61SkreATF_TC(name);								\
31621.61SkreATF_TC_HEAD(name, tc)							\
31631.61Skre{									\
31641.105Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
31651.105Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
31661.105Skamil	    tfork ? "|PTRACE_FORK" : "",				\
31671.105Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
31681.105Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
31691.61Skre}									\
31701.61Skre									\
31711.61SkreATF_TC_BODY(name, tc)							\
31721.61Skre{									\
31731.61Skre									\
31741.105Skamil	fork_body(fun, tfork, tvfork, tvforkdone);			\
31751.32Skamil}
31761.32Skamil
31771.105SkamilFORK_TEST(fork1, fork, false, false, false)
31781.31Skamil#if defined(TWAIT_HAVE_PID)
31791.105SkamilFORK_TEST(fork2, fork, true, false, false)
31801.105SkamilFORK_TEST(fork3, fork, false, true, false)
31811.105SkamilFORK_TEST(fork4, fork, true, true, false)
31821.31Skamil#endif
31831.105SkamilFORK_TEST(fork5, fork, false, false, true)
31841.31Skamil#if defined(TWAIT_HAVE_PID)
31851.105SkamilFORK_TEST(fork6, fork, true, false, true)
31861.105SkamilFORK_TEST(fork7, fork, false, true, true)
31871.105SkamilFORK_TEST(fork8, fork, true, true, true)
31881.31Skamil#endif
31891.1Skamil
31901.110Skamil#if TEST_VFORK_ENABLED
31911.105SkamilFORK_TEST(vfork1, vfork, false, false, false)
31921.31Skamil#if defined(TWAIT_HAVE_PID)
31931.105SkamilFORK_TEST(vfork2, vfork, true, false, false)
31941.105SkamilFORK_TEST(vfork3, vfork, false, true, false)
31951.105SkamilFORK_TEST(vfork4, vfork, true, true, false)
31961.31Skamil#endif
31971.105SkamilFORK_TEST(vfork5, vfork, false, false, true)
31981.31Skamil#if defined(TWAIT_HAVE_PID)
31991.105SkamilFORK_TEST(vfork6, vfork, true, false, true)
32001.105SkamilFORK_TEST(vfork7, vfork, false, true, true)
32011.105SkamilFORK_TEST(vfork8, vfork, true, true, true)
32021.31Skamil#endif
32031.110Skamil#endif
32041.31Skamil
32051.54Skamil/// ----------------------------------------------------------------------------
32061.31Skamil
32071.116Skamil#if defined(TWAIT_HAVE_PID)
32081.116Skamilstatic void
32091.116Skamilfork_detach_forker_body(bool detachfork, bool detachvfork,
32101.116Skamil    bool detachvforkdone, bool kill_process)
32111.116Skamil{
32121.116Skamil	const int exitval = 5;
32131.116Skamil	const int exitval2 = 15;
32141.116Skamil	const int sigval = SIGSTOP;
32151.116Skamil	pid_t child, child2 = 0, wpid;
32161.116Skamil#if defined(TWAIT_HAVE_STATUS)
32171.116Skamil	int status;
32181.116Skamil#endif
32191.116Skamil	ptrace_state_t state;
32201.116Skamil	const int slen = sizeof(state);
32211.116Skamil	ptrace_event_t event;
32221.116Skamil	const int elen = sizeof(event);
32231.116Skamil
32241.116Skamil	pid_t (*fn)(void);
32251.116Skamil	int op;
32261.116Skamil
32271.116Skamil	ATF_REQUIRE((detachfork && !detachvfork && !detachvforkdone) ||
32281.116Skamil	            (!detachfork && detachvfork && !detachvforkdone) ||
32291.116Skamil	            (!detachfork && !detachvfork && detachvforkdone));
32301.116Skamil
32311.116Skamil	if (detachfork)
32321.116Skamil		fn = fork;
32331.116Skamil	else
32341.116Skamil		fn = vfork;
32351.116Skamil
32361.116Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
32371.116Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
32381.116Skamil	if (child == 0) {
32391.116Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32401.116Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32411.116Skamil
32421.116Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32431.116Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32441.116Skamil
32451.116Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
32461.116Skamil
32471.116Skamil		if (child2 == 0)
32481.116Skamil			_exit(exitval2);
32491.116Skamil
32501.116Skamil		FORKEE_REQUIRE_SUCCESS
32511.116Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
32521.116Skamil
32531.116Skamil		forkee_status_exited(status, exitval2);
32541.116Skamil
32551.116Skamil		DPRINTF("Before exiting of the child process\n");
32561.116Skamil		_exit(exitval);
32571.116Skamil	}
32581.116Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32591.116Skamil
32601.116Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32611.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32621.116Skamil
32631.116Skamil	validate_status_stopped(status, sigval);
32641.116Skamil
32651.116Skamil	DPRINTF("Set EVENT_MASK for the child %d\n", child);
32661.116Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
32671.116Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
32681.116Skamil
32691.116Skamil	DPRINTF("Before resuming the child process where it left off and "
32701.116Skamil	    "without signal to be sent\n");
32711.116Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32721.116Skamil
32731.116Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
32741.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32751.116Skamil
32761.116Skamil	validate_status_stopped(status, SIGTRAP);
32771.116Skamil
32781.116Skamil	SYSCALL_REQUIRE(
32791.116Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
32801.116Skamil	op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK;
32811.116Skamil	ATF_REQUIRE_EQ(state.pe_report_event & op, op);
32821.116Skamil
32831.116Skamil	child2 = state.pe_other_pid;
32841.116Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
32851.116Skamil
32861.116Skamil	if (detachfork || detachvfork)
32871.116Skamil		op = kill_process ? PT_KILL : PT_DETACH;
32881.116Skamil	else
32891.116Skamil		op = PT_CONTINUE;
32901.116Skamil	SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1);
32911.116Skamil
32921.116Skamil	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
32931.116Skamil	    TWAIT_FNAME, child2, child);
32941.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
32951.116Skamil
32961.116Skamil	validate_status_stopped(status, SIGTRAP);
32971.116Skamil
32981.116Skamil	SYSCALL_REQUIRE(
32991.116Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
33001.116Skamil	op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK;
33011.116Skamil	ATF_REQUIRE_EQ(state.pe_report_event & op, op);
33021.116Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
33031.116Skamil
33041.116Skamil	DPRINTF("Before resuming the forkee process where it left off "
33051.116Skamil	    "and without signal to be sent\n");
33061.116Skamil 	SYSCALL_REQUIRE(
33071.116Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
33081.116Skamil
33091.116Skamil	if (detachvforkdone && fn == vfork) {
33101.116Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
33111.116Skamil		    child);
33121.116Skamil		TWAIT_REQUIRE_SUCCESS(
33131.116Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
33141.116Skamil
33151.116Skamil		validate_status_stopped(status, SIGTRAP);
33161.116Skamil
33171.116Skamil		SYSCALL_REQUIRE(
33181.116Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
33191.116Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
33201.116Skamil
33211.116Skamil		child2 = state.pe_other_pid;
33221.116Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
33231.116Skamil		    child2);
33241.116Skamil
33251.116Skamil		op = kill_process ? PT_KILL : PT_DETACH;
33261.116Skamil		DPRINTF("Before resuming the child process where it left off "
33271.116Skamil		    "and without signal to be sent\n");
33281.116Skamil		SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1);
33291.116Skamil	}
33301.116Skamil
33311.116Skamil	DPRINTF("Before calling %s() for the forkee - expected exited\n",
33321.116Skamil	    TWAIT_FNAME);
33331.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
33341.116Skamil
33351.116Skamil	validate_status_exited(status, exitval2);
33361.116Skamil
33371.116Skamil	DPRINTF("Before calling %s() for the forkee - expected no process\n",
33381.116Skamil	    TWAIT_FNAME);
33391.116Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0));
33401.116Skamil
33411.116Skamil	DPRINTF("Before calling %s() for the forkee - expected exited\n",
33421.116Skamil	    TWAIT_FNAME);
33431.116Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33441.116Skamil
33451.116Skamil	if (kill_process) {
33461.116Skamil		validate_status_signaled(status, SIGKILL, 0);
33471.116Skamil	} else {
33481.116Skamil		validate_status_exited(status, exitval);
33491.116Skamil	}
33501.116Skamil
33511.116Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
33521.116Skamil	    TWAIT_FNAME);
33531.116Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33541.116Skamil}
33551.116Skamil
33561.116Skamil#define FORK_DETACH_FORKER(name,detfork,detvfork,detvforkdone,kprocess)	\
33571.116SkamilATF_TC(name);								\
33581.116SkamilATF_TC_HEAD(name, tc)							\
33591.116Skamil{									\
33601.116Skamil	atf_tc_set_md_var(tc, "descr", "Verify %s %s%s%s",		\
33611.116Skamil	    kprocess ? "killed" : "detached",				\
33621.116Skamil	    detfork ? "forker" : "",					\
33631.116Skamil	    detvfork ? "vforker" : "",					\
33641.116Skamil	    detvforkdone ? "vforker done" : "");			\
33651.116Skamil}									\
33661.116Skamil									\
33671.116SkamilATF_TC_BODY(name, tc)							\
33681.116Skamil{									\
33691.116Skamil									\
33701.116Skamil	fork_detach_forker_body(detfork, detvfork, detvforkdone,	\
33711.116Skamil	                        kprocess);				\
33721.116Skamil}
33731.116Skamil
33741.116SkamilFORK_DETACH_FORKER(fork_detach_forker, true, false, false, false)
33751.116Skamil#if TEST_VFORK_ENABLED
33761.116SkamilFORK_DETACH_FORKER(vfork_detach_vforker, false, true, false, false)
33771.116SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, false, false, true, false)
33781.116Skamil#endif
33791.116SkamilFORK_DETACH_FORKER(fork_kill_forker, true, false, false, true)
33801.116Skamil#if TEST_VFORK_ENABLED
33811.116SkamilFORK_DETACH_FORKER(vfork_kill_vforker, false, true, false, true)
33821.116SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, false, false, true, true)
33831.116Skamil#endif
33841.116Skamil#endif
33851.116Skamil
33861.116Skamil/// ----------------------------------------------------------------------------
33871.116Skamil
33881.110Skamil#if TEST_VFORK_ENABLED
33891.108Skamilstatic void
33901.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void))
33911.108Skamil{
33921.108Skamil	const int exitval = 5;
33931.108Skamil	const int exitval2 = 15;
33941.108Skamil	pid_t child, child2 = 0, wpid;
33951.108Skamil#if defined(TWAIT_HAVE_STATUS)
33961.108Skamil	int status;
33971.108Skamil#endif
33981.108Skamil
33991.108Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
34001.108Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
34011.108Skamil	if (child == 0) {
34021.108Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34031.108Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34041.108Skamil
34051.108Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
34061.108Skamil
34071.108Skamil		if (child2 == 0)
34081.108Skamil			_exit(exitval2);
34091.108Skamil
34101.108Skamil		FORKEE_REQUIRE_SUCCESS
34111.108Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
34121.108Skamil
34131.108Skamil		forkee_status_exited(status, exitval2);
34141.108Skamil
34151.108Skamil		DPRINTF("Before exiting of the child process\n");
34161.108Skamil		_exit(exitval);
34171.108Skamil	}
34181.108Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34191.108Skamil
34201.108Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
34211.108Skamil	    TWAIT_FNAME);
34221.108Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34231.108Skamil
34241.108Skamil	validate_status_exited(status, exitval);
34251.108Skamil
34261.108Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
34271.108Skamil	    TWAIT_FNAME);
34281.108Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34291.108Skamil}
34301.108Skamil
34311.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun)				\
34321.108SkamilATF_TC(name);								\
34331.108SkamilATF_TC_HEAD(name, tc)							\
34341.108Skamil{									\
34351.108Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
34361.108Skamil	    "called from vfork(2)ed child");				\
34371.108Skamil}									\
34381.108Skamil									\
34391.108SkamilATF_TC_BODY(name, tc)							\
34401.108Skamil{									\
34411.108Skamil									\
34421.108Skamil	traceme_vfork_fork_body(fun);					\
34431.108Skamil}
34441.108Skamil
34451.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork)
34461.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork)
34471.110Skamil#endif
34481.108Skamil
34491.108Skamil/// ----------------------------------------------------------------------------
34501.108Skamil
34511.54Skamilenum bytes_transfer_type {
34521.54Skamil	BYTES_TRANSFER_DATA,
34531.54Skamil	BYTES_TRANSFER_DATAIO,
34541.54Skamil	BYTES_TRANSFER_TEXT,
34551.54Skamil	BYTES_TRANSFER_TEXTIO,
34561.54Skamil	BYTES_TRANSFER_AUXV
34571.54Skamil};
34581.31Skamil
34591.54Skamilstatic int __used
34601.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
34611.54Skamil{
34621.54Skamil	int e, f, g, h;
34631.1Skamil
34641.54Skamil	a *= 4;
34651.54Skamil	b += 3;
34661.54Skamil	c -= 2;
34671.54Skamil	d /= 1;
34681.1Skamil
34691.54Skamil	e = strtol("10", NULL, 10);
34701.54Skamil	f = strtol("20", NULL, 10);
34711.54Skamil	g = strtol("30", NULL, 10);
34721.54Skamil	h = strtol("40", NULL, 10);
34731.1Skamil
34741.54Skamil	return (a + b * c - d) + (e * f - g / h);
34751.1Skamil}
34761.1Skamil
34771.54Skamilstatic void
34781.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
34791.1Skamil{
34801.1Skamil	const int exitval = 5;
34811.1Skamil	const int sigval = SIGSTOP;
34821.1Skamil	pid_t child, wpid;
34831.54Skamil	bool skip = false;
34841.1Skamil
34851.54Skamil	int lookup_me = 0;
34861.54Skamil	uint8_t lookup_me8 = 0;
34871.54Skamil	uint16_t lookup_me16 = 0;
34881.54Skamil	uint32_t lookup_me32 = 0;
34891.54Skamil	uint64_t lookup_me64 = 0;
34901.1Skamil
34911.54Skamil	int magic = 0x13579246;
34921.54Skamil	uint8_t magic8 = 0xab;
34931.54Skamil	uint16_t magic16 = 0x1234;
34941.54Skamil	uint32_t magic32 = 0x98765432;
34951.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
34961.1Skamil
34971.54Skamil	struct ptrace_io_desc io;
34981.1Skamil#if defined(TWAIT_HAVE_STATUS)
34991.1Skamil	int status;
35001.1Skamil#endif
35011.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
35021.60Skre	AuxInfo ai[513], *aip;
35031.55Schristos
35041.55Schristos	ATF_REQUIRE(size < sizeof(ai));
35051.1Skamil
35061.54Skamil	/* Prepare variables for .TEXT transfers */
35071.54Skamil	switch (type) {
35081.54Skamil	case BYTES_TRANSFER_TEXT:
35091.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
35101.54Skamil		break;
35111.54Skamil	case BYTES_TRANSFER_TEXTIO:
35121.54Skamil		switch (size) {
35131.54Skamil		case 8:
35141.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
35151.54Skamil			break;
35161.54Skamil		case 16:
35171.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
35181.54Skamil			break;
35191.54Skamil		case 32:
35201.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
35211.54Skamil			break;
35221.54Skamil		case 64:
35231.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
35241.54Skamil			break;
35251.54Skamil		}
35261.54Skamil		break;
35271.54Skamil	default:
35281.54Skamil		break;
35291.54Skamil	}
35301.1Skamil
35311.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
35321.54Skamil	switch (type) {
35331.54Skamil	case BYTES_TRANSFER_TEXTIO:
35341.54Skamil	case BYTES_TRANSFER_DATAIO:
35351.54Skamil		io.piod_op = operation;
35361.54Skamil		switch (size) {
35371.54Skamil		case 8:
35381.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
35391.54Skamil			               (void *)bytes_transfer_dummy :
35401.54Skamil			               &lookup_me8;
35411.54Skamil			io.piod_addr = &lookup_me8;
35421.54Skamil			io.piod_len = sizeof(lookup_me8);
35431.54Skamil			break;
35441.54Skamil		case 16:
35451.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
35461.54Skamil			               (void *)bytes_transfer_dummy :
35471.54Skamil			               &lookup_me16;
35481.54Skamil			io.piod_addr = &lookup_me16;
35491.54Skamil			io.piod_len = sizeof(lookup_me16);
35501.54Skamil			break;
35511.54Skamil		case 32:
35521.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
35531.54Skamil			               (void *)bytes_transfer_dummy :
35541.54Skamil			               &lookup_me32;
35551.54Skamil			io.piod_addr = &lookup_me32;
35561.54Skamil			io.piod_len = sizeof(lookup_me32);
35571.54Skamil			break;
35581.54Skamil		case 64:
35591.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
35601.54Skamil			               (void *)bytes_transfer_dummy :
35611.54Skamil			               &lookup_me64;
35621.54Skamil			io.piod_addr = &lookup_me64;
35631.54Skamil			io.piod_len = sizeof(lookup_me64);
35641.54Skamil			break;
35651.54Skamil		default:
35661.54Skamil			break;
35671.54Skamil		}
35681.54Skamil		break;
35691.54Skamil	case BYTES_TRANSFER_AUXV:
35701.54Skamil		io.piod_op = operation;
35711.54Skamil		io.piod_offs = 0;
35721.54Skamil		io.piod_addr = ai;
35731.54Skamil		io.piod_len = size;
35741.54Skamil		break;
35751.54Skamil	default:
35761.54Skamil		break;
35771.1Skamil	}
35781.1Skamil
35791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35811.1Skamil	if (child == 0) {
35821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35841.1Skamil
35851.54Skamil		switch (type) {
35861.54Skamil		case BYTES_TRANSFER_DATA:
35871.54Skamil			switch (operation) {
35881.54Skamil			case PT_READ_D:
35891.54Skamil			case PT_READ_I:
35901.54Skamil				lookup_me = magic;
35911.54Skamil				break;
35921.54Skamil			default:
35931.54Skamil				break;
35941.54Skamil			}
35951.54Skamil			break;
35961.54Skamil		case BYTES_TRANSFER_DATAIO:
35971.54Skamil			switch (operation) {
35981.54Skamil			case PIOD_READ_D:
35991.54Skamil			case PIOD_READ_I:
36001.54Skamil				switch (size) {
36011.54Skamil				case 8:
36021.54Skamil					lookup_me8 = magic8;
36031.54Skamil					break;
36041.54Skamil				case 16:
36051.54Skamil					lookup_me16 = magic16;
36061.54Skamil					break;
36071.54Skamil				case 32:
36081.54Skamil					lookup_me32 = magic32;
36091.54Skamil					break;
36101.54Skamil				case 64:
36111.54Skamil					lookup_me64 = magic64;
36121.54Skamil					break;
36131.54Skamil				default:
36141.54Skamil					break;
36151.54Skamil				}
36161.54Skamil				break;
36171.54Skamil			default:
36181.54Skamil				break;
36191.54Skamil			}
36201.54Skamil		default:
36211.54Skamil			break;
36221.54Skamil		}
36231.54Skamil
36241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36261.1Skamil
36271.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
36281.54Skamil		switch (type) {
36291.54Skamil		case BYTES_TRANSFER_DATA:
36301.54Skamil			switch (operation) {
36311.54Skamil			case PT_WRITE_D:
36321.54Skamil			case PT_WRITE_I:
36331.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
36341.54Skamil				break;
36351.54Skamil			default:
36361.54Skamil				break;
36371.54Skamil			}
36381.54Skamil			break;
36391.54Skamil		case BYTES_TRANSFER_DATAIO:
36401.54Skamil			switch (operation) {
36411.54Skamil			case PIOD_WRITE_D:
36421.54Skamil			case PIOD_WRITE_I:
36431.54Skamil				switch (size) {
36441.54Skamil				case 8:
36451.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
36461.54Skamil					break;
36471.54Skamil				case 16:
36481.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
36491.54Skamil					break;
36501.54Skamil				case 32:
36511.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
36521.54Skamil					break;
36531.54Skamil				case 64:
36541.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
36551.54Skamil					break;
36561.54Skamil				default:
36571.54Skamil					break;
36581.54Skamil				}
36591.54Skamil				break;
36601.54Skamil			default:
36611.54Skamil				break;
36621.54Skamil			}
36631.54Skamil			break;
36641.54Skamil		case BYTES_TRANSFER_TEXT:
36651.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
36661.54Skamil			                     sizeof(magic)) == 0);
36671.54Skamil			break;
36681.54Skamil		case BYTES_TRANSFER_TEXTIO:
36691.54Skamil			switch (size) {
36701.54Skamil			case 8:
36711.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
36721.54Skamil				                     bytes_transfer_dummy,
36731.54Skamil				                     sizeof(magic8)) == 0);
36741.54Skamil				break;
36751.54Skamil			case 16:
36761.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
36771.54Skamil				                     bytes_transfer_dummy,
36781.54Skamil				                     sizeof(magic16)) == 0);
36791.54Skamil				break;
36801.54Skamil			case 32:
36811.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
36821.54Skamil				                     bytes_transfer_dummy,
36831.54Skamil				                     sizeof(magic32)) == 0);
36841.54Skamil				break;
36851.54Skamil			case 64:
36861.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
36871.54Skamil				                     bytes_transfer_dummy,
36881.54Skamil				                     sizeof(magic64)) == 0);
36891.54Skamil				break;
36901.54Skamil			}
36911.54Skamil			break;
36921.54Skamil		default:
36931.54Skamil			break;
36941.54Skamil		}
36951.54Skamil
36961.13Schristos		DPRINTF("Before exiting of the child process\n");
36971.1Skamil		_exit(exitval);
36981.1Skamil	}
36991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37001.1Skamil
37011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37031.1Skamil
37041.1Skamil	validate_status_stopped(status, sigval);
37051.1Skamil
37061.54Skamil	/* Check PaX MPROTECT */
37071.54Skamil	if (!can_we_write_to_text(child)) {
37081.54Skamil		switch (type) {
37091.54Skamil		case BYTES_TRANSFER_TEXTIO:
37101.54Skamil			switch (operation) {
37111.54Skamil			case PIOD_WRITE_D:
37121.54Skamil			case PIOD_WRITE_I:
37131.54Skamil				skip = true;
37141.54Skamil				break;
37151.54Skamil			default:
37161.54Skamil				break;
37171.54Skamil			}
37181.54Skamil			break;
37191.54Skamil		case BYTES_TRANSFER_TEXT:
37201.54Skamil			switch (operation) {
37211.54Skamil			case PT_WRITE_D:
37221.54Skamil			case PT_WRITE_I:
37231.54Skamil				skip = true;
37241.54Skamil				break;
37251.54Skamil			default:
37261.54Skamil				break;
37271.54Skamil			}
37281.54Skamil			break;
37291.54Skamil		default:
37301.54Skamil			break;
37311.54Skamil		}
37321.54Skamil	}
37331.1Skamil
37341.54Skamil	/* Bailout cleanly killing the child process */
37351.54Skamil	if (skip) {
37361.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
37371.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37381.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
37391.54Skamil		                      child);
37401.1Skamil
37411.54Skamil		validate_status_signaled(status, SIGKILL, 0);
37421.1Skamil
37431.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
37441.54Skamil	}
37451.1Skamil
37461.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
37471.54Skamil	       "parent=%d\n", child, getpid());
37481.1Skamil
37491.54Skamil	switch (type) {
37501.54Skamil	case BYTES_TRANSFER_TEXTIO:
37511.54Skamil	case BYTES_TRANSFER_DATAIO:
37521.54Skamil	case BYTES_TRANSFER_AUXV:
37531.54Skamil		switch (operation) {
37541.54Skamil		case PIOD_WRITE_D:
37551.54Skamil		case PIOD_WRITE_I:
37561.54Skamil			switch (size) {
37571.54Skamil			case 8:
37581.54Skamil				lookup_me8 = magic8;
37591.54Skamil				break;
37601.54Skamil			case 16:
37611.54Skamil				lookup_me16 = magic16;
37621.54Skamil				break;
37631.54Skamil			case 32:
37641.54Skamil				lookup_me32 = magic32;
37651.54Skamil				break;
37661.54Skamil			case 64:
37671.54Skamil				lookup_me64 = magic64;
37681.54Skamil				break;
37691.54Skamil			default:
37701.54Skamil				break;
37711.54Skamil			}
37721.54Skamil			break;
37731.54Skamil		default:
37741.54Skamil			break;
37751.54Skamil		}
37761.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
37771.54Skamil		switch (operation) {
37781.54Skamil		case PIOD_READ_D:
37791.54Skamil		case PIOD_READ_I:
37801.54Skamil			switch (size) {
37811.54Skamil			case 8:
37821.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
37831.54Skamil				break;
37841.54Skamil			case 16:
37851.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
37861.54Skamil				break;
37871.54Skamil			case 32:
37881.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
37891.54Skamil				break;
37901.54Skamil			case 64:
37911.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
37921.54Skamil				break;
37931.54Skamil			default:
37941.54Skamil				break;
37951.54Skamil			}
37961.54Skamil			break;
37971.54Skamil		case PIOD_READ_AUXV:
37981.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
37991.54Skamil			        io.piod_len);
38001.54Skamil			ATF_REQUIRE(io.piod_len > 0);
38011.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
38021.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
38031.54Skamil				    (long long int)aip->a_type,
38041.54Skamil				    (long long int)aip->a_v);
38051.54Skamil			break;
38061.54Skamil		default:
38071.54Skamil			break;
38081.54Skamil		}
38091.54Skamil		break;
38101.54Skamil	case BYTES_TRANSFER_TEXT:
38111.54Skamil		switch (operation) {
38121.54Skamil		case PT_READ_D:
38131.54Skamil		case PT_READ_I:
38141.54Skamil			errno = 0;
38151.54Skamil			lookup_me = ptrace(operation, child,
38161.54Skamil			                   bytes_transfer_dummy, 0);
38171.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
38181.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
38191.54Skamil			break;
38201.54Skamil		case PT_WRITE_D:
38211.54Skamil		case PT_WRITE_I:
38221.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
38231.54Skamil			                       bytes_transfer_dummy, magic)
38241.54Skamil			                != -1);
38251.54Skamil			break;
38261.54Skamil		default:
38271.54Skamil			break;
38281.54Skamil		}
38291.54Skamil		break;
38301.54Skamil	case BYTES_TRANSFER_DATA:
38311.54Skamil		switch (operation) {
38321.54Skamil		case PT_READ_D:
38331.54Skamil		case PT_READ_I:
38341.54Skamil			errno = 0;
38351.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
38361.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
38371.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
38381.54Skamil			break;
38391.54Skamil		case PT_WRITE_D:
38401.54Skamil		case PT_WRITE_I:
38411.54Skamil			lookup_me = magic;
38421.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
38431.54Skamil			                       magic) != -1);
38441.54Skamil			break;
38451.54Skamil		default:
38461.54Skamil			break;
38471.54Skamil		}
38481.54Skamil		break;
38491.54Skamil	default:
38501.54Skamil		break;
38511.54Skamil	}
38521.1Skamil
38531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38541.1Skamil	    "without signal to be sent\n");
38551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38561.1Skamil
38571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38591.1Skamil
38601.1Skamil	validate_status_exited(status, exitval);
38611.1Skamil
38621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38641.1Skamil}
38651.1Skamil
38661.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
38671.61SkreATF_TC(test);								\
38681.61SkreATF_TC_HEAD(test, tc)							\
38691.61Skre{									\
38701.61Skre	atf_tc_set_md_var(tc, "descr",					\
38711.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
38721.61Skre	    " of type " #type);						\
38731.61Skre}									\
38741.61Skre									\
38751.61SkreATF_TC_BODY(test, tc)							\
38761.61Skre{									\
38771.61Skre									\
38781.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
38791.1Skamil}
38801.1Skamil
38811.54Skamil// DATA
38821.1Skamil
38831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
38841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
38851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
38861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
38871.54Skamil
38881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
38891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
38901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
38911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
38921.54Skamil
38931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
38941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
38951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
38961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
38971.54Skamil
38981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
38991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
39001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
39011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
39021.54Skamil
39031.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
39041.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
39051.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
39061.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
39071.54Skamil
39081.54Skamil// TEXT
39091.54Skamil
39101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
39111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
39121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
39131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
39141.54Skamil
39151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
39161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
39171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
39181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
39191.54Skamil
39201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
39211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
39221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
39231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
39241.54Skamil
39251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
39261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
39271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
39281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
39291.54Skamil
39301.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
39311.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
39321.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
39331.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
39341.1Skamil
39351.54Skamil// AUXV
39361.1Skamil
39371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
39381.1Skamil
39391.54Skamil/// ----------------------------------------------------------------------------
39401.1Skamil
39411.101Skamilstatic void
39421.101Skamilbytes_transfer_alignment(const char *operation)
39431.101Skamil{
39441.101Skamil	const int exitval = 5;
39451.101Skamil	const int sigval = SIGSTOP;
39461.101Skamil	pid_t child, wpid;
39471.101Skamil#if defined(TWAIT_HAVE_STATUS)
39481.101Skamil	int status;
39491.101Skamil#endif
39501.101Skamil	char *buffer;
39511.101Skamil	int vector;
39521.101Skamil	size_t len;
39531.101Skamil	size_t i;
39541.101Skamil	int op;
39551.101Skamil
39561.101Skamil	struct ptrace_io_desc io;
39571.101Skamil	struct ptrace_siginfo info;
39581.101Skamil
39591.101Skamil	memset(&io, 0, sizeof(io));
39601.101Skamil	memset(&info, 0, sizeof(info));
39611.101Skamil
39621.101Skamil	/* Testing misaligned byte transfer crossing page boundaries */
39631.101Skamil	len = sysconf(_SC_PAGESIZE) * 2;
39641.101Skamil	buffer = malloc(len);
39651.101Skamil	ATF_REQUIRE(buffer != NULL);
39661.101Skamil
39671.101Skamil	/* Initialize the buffer with random data */
39681.101Skamil	for (i = 0; i < len; i++)
39691.101Skamil		buffer[i] = i & 0xff;
39701.101Skamil
39711.101Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
39721.101Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
39731.101Skamil	if (child == 0) {
39741.101Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39751.101Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39761.101Skamil
39771.101Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39781.101Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39791.101Skamil
39801.101Skamil		DPRINTF("Before exiting of the child process\n");
39811.101Skamil		_exit(exitval);
39821.101Skamil	}
39831.101Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39841.101Skamil
39851.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39861.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39871.101Skamil
39881.101Skamil	validate_status_stopped(status, sigval);
39891.101Skamil
39901.101Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39911.101Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
39921.101Skamil		!= -1);
39931.101Skamil
39941.101Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
39951.101Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
39961.101Skamil		"si_errno=%#x\n",
39971.101Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
39981.101Skamil		info.psi_siginfo.si_errno);
39991.101Skamil
40001.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
40011.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
40021.101Skamil
40031.101Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
40041.101Skamil	    strcmp(operation, "PT_READ_D") == 0) {
40051.101Skamil		if (strcmp(operation, "PT_READ_I"))
40061.101Skamil			op = PT_READ_I;
40071.101Skamil		else
40081.101Skamil			op = PT_READ_D;
40091.101Skamil
40101.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
40111.101Skamil			errno = 0;
40121.101Skamil			vector = ptrace(op, child, buffer + i, 0);
40131.101Skamil			ATF_REQUIRE_EQ(errno, 0);
40141.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
40151.101Skamil		}
40161.101Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
40171.101Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
40181.101Skamil		if (strcmp(operation, "PT_WRITE_I"))
40191.101Skamil			op = PT_WRITE_I;
40201.101Skamil		else
40211.101Skamil			op = PT_WRITE_D;
40221.101Skamil
40231.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
40241.101Skamil			memcpy(&vector, buffer + i, sizeof(int));
40251.101Skamil			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
40261.101Skamil			    != -1);
40271.101Skamil		}
40281.101Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
40291.101Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
40301.101Skamil		if (strcmp(operation, "PIOD_READ_I"))
40311.101Skamil			op = PIOD_READ_I;
40321.101Skamil		else
40331.101Skamil			op = PIOD_READ_D;
40341.101Skamil
40351.101Skamil		io.piod_op = op;
40361.101Skamil		io.piod_addr = &vector;
40371.101Skamil		io.piod_len = sizeof(int);
40381.101Skamil
40391.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
40401.101Skamil			io.piod_offs = buffer + i;
40411.101Skamil
40421.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
40431.101Skamil			                != -1);
40441.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
40451.101Skamil		}
40461.101Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
40471.101Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
40481.101Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
40491.101Skamil			op = PIOD_WRITE_I;
40501.101Skamil		else
40511.101Skamil			op = PIOD_WRITE_D;
40521.101Skamil
40531.101Skamil		io.piod_op = op;
40541.101Skamil		io.piod_addr = &vector;
40551.101Skamil		io.piod_len = sizeof(int);
40561.101Skamil
40571.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
40581.101Skamil			io.piod_offs = buffer + i;
40591.101Skamil
40601.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
40611.101Skamil			                != -1);
40621.101Skamil		}
40631.101Skamil	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
40641.101Skamil		io.piod_op = PIOD_READ_AUXV;
40651.101Skamil		io.piod_addr = &vector;
40661.101Skamil		io.piod_len = sizeof(int);
40671.101Skamil
40681.101Skamil		errno = 0;
40691.101Skamil		i = 0;
40701.101Skamil		/* Read the whole AUXV vector, it has no clear length */
40711.120Skamil		while (io.piod_len > 0) {
40721.101Skamil			io.piod_offs = (void *)(intptr_t)i;
40731.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
40741.120Skamil			                != -1 || (io.piod_len == 0 && i > 0));
40751.101Skamil			++i;
40761.101Skamil		}
40771.101Skamil	}
40781.101Skamil
40791.101Skamil	DPRINTF("Before resuming the child process where it left off "
40801.101Skamil	    "and without signal to be sent\n");
40811.101Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40821.101Skamil
40831.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40841.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
40851.101Skamil	    child);
40861.101Skamil
40871.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40881.101Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40891.101Skamil}
40901.101Skamil
40911.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
40921.101SkamilATF_TC(test);								\
40931.101SkamilATF_TC_HEAD(test, tc)							\
40941.101Skamil{									\
40951.101Skamil	atf_tc_set_md_var(tc, "descr",					\
40961.101Skamil	    "Verify bytes transfer for potentially misaligned "		\
40971.101Skamil	    "operation " operation);					\
40981.101Skamil}									\
40991.101Skamil									\
41001.101SkamilATF_TC_BODY(test, tc)							\
41011.101Skamil{									\
41021.101Skamil									\
41031.101Skamil	bytes_transfer_alignment(operation);				\
41041.101Skamil}
41051.101Skamil
41061.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
41071.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
41081.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
41091.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
41101.101Skamil
41111.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
41121.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
41131.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
41141.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
41151.101Skamil
41161.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
41171.101Skamil
41181.101Skamil/// ----------------------------------------------------------------------------
41191.101Skamil
41201.115Skamilstatic void
41211.115Skamilbytes_transfer_eof(const char *operation)
41221.115Skamil{
41231.115Skamil	const int exitval = 5;
41241.115Skamil	const int sigval = SIGSTOP;
41251.115Skamil	pid_t child, wpid;
41261.115Skamil#if defined(TWAIT_HAVE_STATUS)
41271.115Skamil	int status;
41281.115Skamil#endif
41291.115Skamil	FILE *fp;
41301.115Skamil	char *p;
41311.115Skamil	int vector;
41321.115Skamil	int op;
41331.115Skamil
41341.115Skamil	struct ptrace_io_desc io;
41351.115Skamil	struct ptrace_siginfo info;
41361.115Skamil
41371.115Skamil	memset(&io, 0, sizeof(io));
41381.115Skamil	memset(&info, 0, sizeof(info));
41391.115Skamil
41401.115Skamil	vector = 0;
41411.115Skamil
41421.115Skamil	fp = tmpfile();
41431.115Skamil	ATF_REQUIRE(fp != NULL);
41441.115Skamil
41451.115Skamil	p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
41461.115Skamil	ATF_REQUIRE(p != MAP_FAILED);
41471.115Skamil
41481.115Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
41491.115Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
41501.115Skamil	if (child == 0) {
41511.115Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41521.115Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41531.115Skamil
41541.115Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41551.115Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41561.115Skamil
41571.115Skamil		DPRINTF("Before exiting of the child process\n");
41581.115Skamil		_exit(exitval);
41591.115Skamil	}
41601.115Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41611.115Skamil
41621.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41631.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41641.115Skamil
41651.115Skamil	validate_status_stopped(status, sigval);
41661.115Skamil
41671.115Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
41681.115Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
41691.115Skamil		!= -1);
41701.115Skamil
41711.115Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
41721.115Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
41731.115Skamil		"si_errno=%#x\n",
41741.115Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41751.115Skamil		info.psi_siginfo.si_errno);
41761.115Skamil
41771.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
41781.115Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
41791.115Skamil
41801.115Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
41811.115Skamil	    strcmp(operation, "PT_READ_D") == 0) {
41821.115Skamil		if (strcmp(operation, "PT_READ_I"))
41831.115Skamil			op = PT_READ_I;
41841.115Skamil		else
41851.115Skamil			op = PT_READ_D;
41861.115Skamil
41871.115Skamil		errno = 0;
41881.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1);
41891.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
41901.115Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
41911.115Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
41921.115Skamil		if (strcmp(operation, "PT_WRITE_I"))
41931.115Skamil			op = PT_WRITE_I;
41941.115Skamil		else
41951.115Skamil			op = PT_WRITE_D;
41961.115Skamil
41971.115Skamil		errno = 0;
41981.115Skamil		SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1);
41991.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42001.115Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
42011.115Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
42021.115Skamil		if (strcmp(operation, "PIOD_READ_I"))
42031.115Skamil			op = PIOD_READ_I;
42041.115Skamil		else
42051.115Skamil			op = PIOD_READ_D;
42061.115Skamil
42071.115Skamil		io.piod_op = op;
42081.115Skamil		io.piod_addr = &vector;
42091.115Skamil		io.piod_len = sizeof(int);
42101.115Skamil		io.piod_offs = p;
42111.115Skamil
42121.115Skamil		errno = 0;
42131.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
42141.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42151.115Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
42161.115Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
42171.115Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
42181.115Skamil			op = PIOD_WRITE_I;
42191.115Skamil		else
42201.115Skamil			op = PIOD_WRITE_D;
42211.115Skamil
42221.115Skamil		io.piod_op = op;
42231.115Skamil		io.piod_addr = &vector;
42241.115Skamil		io.piod_len = sizeof(int);
42251.115Skamil		io.piod_offs = p;
42261.115Skamil
42271.115Skamil		errno = 0;
42281.115Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
42291.115Skamil		ATF_REQUIRE_EQ(errno, EINVAL);
42301.115Skamil	}
42311.115Skamil
42321.115Skamil	DPRINTF("Before resuming the child process where it left off "
42331.115Skamil	    "and without signal to be sent\n");
42341.115Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42351.115Skamil
42361.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42371.115Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
42381.115Skamil	    child);
42391.115Skamil
42401.115Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42411.115Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42421.115Skamil}
42431.115Skamil
42441.115Skamil#define BYTES_TRANSFER_EOF(test, operation)				\
42451.115SkamilATF_TC(test);								\
42461.115SkamilATF_TC_HEAD(test, tc)							\
42471.115Skamil{									\
42481.115Skamil	atf_tc_set_md_var(tc, "descr",					\
42491.115Skamil	    "Verify bytes EOF byte transfer for the " operation		\
42501.115Skamil	    " operation");						\
42511.115Skamil}									\
42521.115Skamil									\
42531.115SkamilATF_TC_BODY(test, tc)							\
42541.115Skamil{									\
42551.115Skamil									\
42561.115Skamil	bytes_transfer_eof(operation);					\
42571.115Skamil}
42581.115Skamil
42591.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I")
42601.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D")
42611.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I")
42621.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D")
42631.115Skamil
42641.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I")
42651.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D")
42661.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I")
42671.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D")
42681.115Skamil
42691.115Skamil/// ----------------------------------------------------------------------------
42701.115Skamil
42711.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
42721.72Skamilstatic void
42731.72Skamilaccess_regs(const char *regset, const char *aux)
42741.1Skamil{
42751.1Skamil	const int exitval = 5;
42761.1Skamil	const int sigval = SIGSTOP;
42771.1Skamil	pid_t child, wpid;
42781.1Skamil#if defined(TWAIT_HAVE_STATUS)
42791.1Skamil	int status;
42801.1Skamil#endif
42811.72Skamil#if defined(HAVE_GPREGS)
42821.72Skamil	struct reg gpr;
42831.76Sscole	register_t rgstr;
42841.1Skamil#endif
42851.72Skamil#if defined(HAVE_FPREGS)
42861.72Skamil	struct fpreg fpr;
42871.1Skamil#endif
42881.76Sscole
42891.72Skamil#if !defined(HAVE_GPREGS)
42901.72Skamil	if (strcmp(regset, "regs") == 0)
42911.72Skamil		atf_tc_fail("Impossible test scenario!");
42921.1Skamil#endif
42931.1Skamil
42941.72Skamil#if !defined(HAVE_FPREGS)
42951.72Skamil	if (strcmp(regset, "fpregs") == 0)
42961.72Skamil		atf_tc_fail("Impossible test scenario!");
42971.1Skamil#endif
42981.1Skamil
42991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43011.1Skamil	if (child == 0) {
43021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43041.1Skamil
43051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43071.1Skamil
43081.13Schristos		DPRINTF("Before exiting of the child process\n");
43091.1Skamil		_exit(exitval);
43101.1Skamil	}
43111.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43121.1Skamil
43131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43151.1Skamil
43161.1Skamil	validate_status_stopped(status, sigval);
43171.1Skamil
43181.1Skamil#if defined(HAVE_GPREGS)
43191.72Skamil	if (strcmp(regset, "regs") == 0) {
43201.72Skamil		DPRINTF("Call GETREGS for the child process\n");
43211.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
43221.72Skamil
43231.72Skamil		if (strcmp(aux, "none") == 0) {
43241.72Skamil			DPRINTF("Retrieved registers\n");
43251.72Skamil		} else if (strcmp(aux, "pc") == 0) {
43261.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
43271.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
43281.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
43291.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
43301.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
43311.72Skamil		} else if (strcmp(aux, "sp") == 0) {
43321.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
43331.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
43341.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
43351.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
43361.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
43371.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
43381.72Skamil			DPRINTF("Call SETREGS for the child process\n");
43391.72Skamil			SYSCALL_REQUIRE(
43401.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
43411.72Skamil		}
43421.72Skamil	}
43431.1Skamil#endif
43441.1Skamil
43451.72Skamil#if defined(HAVE_FPREGS)
43461.72Skamil	if (strcmp(regset, "fpregs") == 0) {
43471.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
43481.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
43491.72Skamil
43501.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
43511.72Skamil			DPRINTF("Retrieved FP registers\n");
43521.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
43531.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
43541.72Skamil			SYSCALL_REQUIRE(
43551.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
43561.72Skamil		}
43571.1Skamil	}
43581.1Skamil#endif
43591.1Skamil
43601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43611.1Skamil	    "without signal to be sent\n");
43621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43631.1Skamil
43641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43661.1Skamil
43671.1Skamil	validate_status_exited(status, exitval);
43681.1Skamil
43691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43711.1Skamil}
43721.1Skamil
43731.72Skamil#define ACCESS_REGS(test, regset, aux)					\
43741.72SkamilATF_TC(test);								\
43751.72SkamilATF_TC_HEAD(test, tc)							\
43761.72Skamil{									\
43771.72Skamil        atf_tc_set_md_var(tc, "descr",					\
43781.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
43791.72Skamil}									\
43801.72Skamil									\
43811.72SkamilATF_TC_BODY(test, tc)							\
43821.72Skamil{									\
43831.72Skamil									\
43841.72Skamil        access_regs(regset, aux);					\
43851.1Skamil}
43861.1Skamil#endif
43871.1Skamil
43881.72Skamil#if defined(HAVE_GPREGS)
43891.72SkamilACCESS_REGS(access_regs1, "regs", "none")
43901.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
43911.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
43921.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
43931.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
43941.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
43951.1Skamil#endif
43961.1Skamil#if defined(HAVE_FPREGS)
43971.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
43981.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
43991.1Skamil#endif
44001.1Skamil
44011.72Skamil/// ----------------------------------------------------------------------------
44021.1Skamil
44031.1Skamil#if defined(PT_STEP)
44041.1Skamilstatic void
44051.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
44061.1Skamil{
44071.1Skamil	const int exitval = 5;
44081.1Skamil	const int sigval = SIGSTOP;
44091.1Skamil	pid_t child, wpid;
44101.1Skamil#if defined(TWAIT_HAVE_STATUS)
44111.1Skamil	int status;
44121.1Skamil#endif
44131.1Skamil	int happy;
44141.95Skamil	struct sigaction sa;
44151.81Skamil	struct ptrace_siginfo info;
44161.95Skamil	sigset_t intmask;
44171.95Skamil	struct kinfo_proc2 kp;
44181.95Skamil	size_t len = sizeof(kp);
44191.95Skamil
44201.95Skamil	int name[6];
44211.95Skamil	const size_t namelen = __arraycount(name);
44221.95Skamil	ki_sigset_t kp_sigmask;
44231.95Skamil	ki_sigset_t kp_sigignore;
44241.1Skamil
44251.1Skamil#if defined(__arm__)
44261.1Skamil	/* PT_STEP not supported on arm 32-bit */
44271.1Skamil	atf_tc_expect_fail("PR kern/52119");
44281.1Skamil#endif
44291.1Skamil
44301.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44311.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44321.1Skamil	if (child == 0) {
44331.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44341.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44351.1Skamil
44361.95Skamil		if (masked) {
44371.95Skamil			sigemptyset(&intmask);
44381.95Skamil			sigaddset(&intmask, SIGTRAP);
44391.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
44401.95Skamil		}
44411.95Skamil
44421.95Skamil		if (ignored) {
44431.95Skamil			memset(&sa, 0, sizeof(sa));
44441.95Skamil			sa.sa_handler = SIG_IGN;
44451.95Skamil			sigemptyset(&sa.sa_mask);
44461.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
44471.95Skamil		}
44481.95Skamil
44491.1Skamil		happy = check_happy(999);
44501.1Skamil
44511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44531.1Skamil
44541.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
44551.1Skamil
44561.13Schristos		DPRINTF("Before exiting of the child process\n");
44571.1Skamil		_exit(exitval);
44581.1Skamil	}
44591.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44601.1Skamil
44611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44631.1Skamil
44641.1Skamil	validate_status_stopped(status, sigval);
44651.1Skamil
44661.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
44671.81Skamil	SYSCALL_REQUIRE(
44681.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
44691.81Skamil
44701.81Skamil	DPRINTF("Before checking siginfo_t\n");
44711.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
44721.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
44731.81Skamil
44741.95Skamil	name[0] = CTL_KERN,
44751.95Skamil	name[1] = KERN_PROC2,
44761.95Skamil	name[2] = KERN_PROC_PID;
44771.95Skamil	name[3] = child;
44781.95Skamil	name[4] = sizeof(kp);
44791.95Skamil	name[5] = 1;
44801.95Skamil
44811.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
44821.95Skamil
44831.95Skamil	if (masked)
44841.95Skamil		kp_sigmask = kp.p_sigmask;
44851.95Skamil
44861.95Skamil	if (ignored)
44871.95Skamil		kp_sigignore = kp.p_sigignore;
44881.95Skamil
44891.1Skamil	while (N --> 0) {
44901.2Skamil		if (setstep) {
44911.13Schristos			DPRINTF("Before resuming the child process where it "
44921.2Skamil			    "left off and without signal to be sent (use "
44931.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
44941.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
44951.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
44961.2Skamil			    != -1);
44971.2Skamil		} else {
44981.13Schristos			DPRINTF("Before resuming the child process where it "
44991.2Skamil			    "left off and without signal to be sent (use "
45001.2Skamil			    "PT_STEP)\n");
45011.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
45021.2Skamil			    != -1);
45031.2Skamil		}
45041.1Skamil
45051.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45061.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
45071.1Skamil		    child);
45081.1Skamil
45091.1Skamil		validate_status_stopped(status, SIGTRAP);
45101.2Skamil
45111.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45121.81Skamil		SYSCALL_REQUIRE(
45131.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45141.81Skamil
45151.81Skamil		DPRINTF("Before checking siginfo_t\n");
45161.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
45171.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
45181.81Skamil
45191.2Skamil		if (setstep) {
45201.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
45211.2Skamil		}
45221.95Skamil
45231.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
45241.95Skamil
45251.95Skamil		if (masked) {
45261.95Skamil			DPRINTF("kp_sigmask="
45271.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
45281.95Skamil			    PRIx32 "\n",
45291.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
45301.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
45311.95Skamil
45321.95Skamil			DPRINTF("kp.p_sigmask="
45331.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
45341.95Skamil			    PRIx32 "\n",
45351.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
45361.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
45371.95Skamil
45381.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
45391.95Skamil			    sizeof(kp_sigmask)));
45401.95Skamil		}
45411.95Skamil
45421.95Skamil		if (ignored) {
45431.95Skamil			DPRINTF("kp_sigignore="
45441.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
45451.95Skamil			    PRIx32 "\n",
45461.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
45471.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
45481.95Skamil
45491.95Skamil			DPRINTF("kp.p_sigignore="
45501.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
45511.95Skamil			    PRIx32 "\n",
45521.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
45531.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
45541.95Skamil
45551.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
45561.95Skamil			    sizeof(kp_sigignore)));
45571.95Skamil		}
45581.1Skamil	}
45591.1Skamil
45601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45611.1Skamil	    "without signal to be sent\n");
45621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45631.1Skamil
45641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45661.1Skamil
45671.1Skamil	validate_status_exited(status, exitval);
45681.1Skamil
45691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45711.1Skamil}
45721.1Skamil
45731.73Skamil#define PTRACE_STEP(test, N, setstep)					\
45741.73SkamilATF_TC(test);								\
45751.73SkamilATF_TC_HEAD(test, tc)							\
45761.73Skamil{									\
45771.73Skamil        atf_tc_set_md_var(tc, "descr",					\
45781.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
45791.73Skamil}									\
45801.73Skamil									\
45811.73SkamilATF_TC_BODY(test, tc)							\
45821.73Skamil{									\
45831.73Skamil									\
45841.95Skamil        ptrace_step(N, setstep, false, false);				\
45851.1Skamil}
45861.1Skamil
45871.73SkamilPTRACE_STEP(step1, 1, 0)
45881.73SkamilPTRACE_STEP(step2, 2, 0)
45891.73SkamilPTRACE_STEP(step3, 3, 0)
45901.73SkamilPTRACE_STEP(step4, 4, 0)
45911.73SkamilPTRACE_STEP(setstep1, 1, 1)
45921.73SkamilPTRACE_STEP(setstep2, 2, 1)
45931.73SkamilPTRACE_STEP(setstep3, 3, 1)
45941.73SkamilPTRACE_STEP(setstep4, 4, 1)
45951.95Skamil
45961.95SkamilATF_TC(step_signalmasked);
45971.95SkamilATF_TC_HEAD(step_signalmasked, tc)
45981.95Skamil{
45991.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
46001.95Skamil}
46011.95Skamil
46021.95SkamilATF_TC_BODY(step_signalmasked, tc)
46031.95Skamil{
46041.95Skamil
46051.95Skamil	ptrace_step(1, 0, true, false);
46061.95Skamil}
46071.95Skamil
46081.95SkamilATF_TC(step_signalignored);
46091.95SkamilATF_TC_HEAD(step_signalignored, tc)
46101.95Skamil{
46111.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
46121.95Skamil}
46131.95Skamil
46141.95SkamilATF_TC_BODY(step_signalignored, tc)
46151.95Skamil{
46161.95Skamil
46171.95Skamil	ptrace_step(1, 0, false, true);
46181.95Skamil}
46191.1Skamil#endif
46201.1Skamil
46211.73Skamil/// ----------------------------------------------------------------------------
46221.1Skamil
46231.75Skamilstatic void
46241.75Skamilptrace_kill(const char *type)
46251.1Skamil{
46261.75Skamil	const int sigval = SIGSTOP;
46271.1Skamil	pid_t child, wpid;
46281.1Skamil#if defined(TWAIT_HAVE_STATUS)
46291.1Skamil	int status;
46301.1Skamil#endif
46311.1Skamil
46321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46341.1Skamil	if (child == 0) {
46351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46371.1Skamil
46381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46401.1Skamil
46411.1Skamil		/* NOTREACHED */
46421.1Skamil		FORKEE_ASSERTX(0 &&
46431.1Skamil		    "Child should be terminated by a signal from its parent");
46441.1Skamil	}
46451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46461.1Skamil
46471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46491.1Skamil
46501.1Skamil	validate_status_stopped(status, sigval);
46511.1Skamil
46521.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
46531.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
46541.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
46551.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
46561.75Skamil		kill(child, SIGKILL);
46571.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
46581.75Skamil		setpgid(child, 0);
46591.75Skamil		killpg(getpgid(child), SIGKILL);
46601.75Skamil	}
46611.1Skamil
46621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46641.1Skamil
46651.75Skamil	validate_status_signaled(status, SIGKILL, 0);
46661.1Skamil
46671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46691.1Skamil}
46701.1Skamil
46711.75Skamil#define PTRACE_KILL(test, type)						\
46721.75SkamilATF_TC(test);								\
46731.75SkamilATF_TC_HEAD(test, tc)							\
46741.75Skamil{									\
46751.75Skamil        atf_tc_set_md_var(tc, "descr",					\
46761.75Skamil            "Verify killing the child with " type);			\
46771.75Skamil}									\
46781.75Skamil									\
46791.75SkamilATF_TC_BODY(test, tc)							\
46801.75Skamil{									\
46811.75Skamil									\
46821.75Skamil        ptrace_kill(type);						\
46831.1Skamil}
46841.1Skamil
46851.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
46861.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
46871.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
46881.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
46891.1Skamil
46901.75Skamil/// ----------------------------------------------------------------------------
46911.1Skamil
46921.77Skamilstatic void
46931.77Skamiltraceme_lwpinfo(const int threads)
46941.1Skamil{
46951.1Skamil	const int sigval = SIGSTOP;
46961.77Skamil	const int sigval2 = SIGINT;
46971.1Skamil	pid_t child, wpid;
46981.1Skamil#if defined(TWAIT_HAVE_STATUS)
46991.1Skamil	int status;
47001.1Skamil#endif
47011.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
47021.77Skamil	struct ptrace_siginfo info;
47031.77Skamil
47041.77Skamil	/* Maximum number of supported threads in this test */
47051.77Skamil	pthread_t t[3];
47061.77Skamil	int n, rv;
47071.77Skamil
47081.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
47091.1Skamil
47101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47121.1Skamil	if (child == 0) {
47131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47151.1Skamil
47161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47181.1Skamil
47191.77Skamil		for (n = 0; n < threads; n++) {
47201.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
47211.77Skamil			FORKEE_ASSERT(rv == 0);
47221.77Skamil		}
47231.77Skamil
47241.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
47251.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
47261.77Skamil
47271.77Skamil		/* NOTREACHED */
47281.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
47291.1Skamil	}
47301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47311.1Skamil
47321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47341.1Skamil
47351.1Skamil	validate_status_stopped(status, sigval);
47361.1Skamil
47371.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
47381.77Skamil	SYSCALL_REQUIRE(
47391.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
47401.77Skamil
47411.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47421.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
47431.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47441.77Skamil	    info.psi_siginfo.si_errno);
47451.77Skamil
47461.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
47471.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
47481.77Skamil
47491.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47501.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
47511.1Skamil
47521.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
47531.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
47541.1Skamil
47551.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
47561.77Skamil	    lwp.pl_lwpid);
47571.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
47581.1Skamil
47591.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47601.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
47611.1Skamil
47621.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
47631.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
47641.1Skamil
47651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47661.1Skamil	    "without signal to be sent\n");
47671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47681.1Skamil
47691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47711.1Skamil
47721.77Skamil	validate_status_stopped(status, sigval2);
47731.77Skamil
47741.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
47751.77Skamil	SYSCALL_REQUIRE(
47761.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
47771.77Skamil
47781.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47791.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
47801.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47811.77Skamil	    info.psi_siginfo.si_errno);
47821.77Skamil
47831.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
47841.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
47851.77Skamil
47861.77Skamil	memset(&lwp, 0, sizeof(lwp));
47871.77Skamil
47881.77Skamil	for (n = 0; n <= threads; n++) {
47891.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47901.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
47911.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
47921.77Skamil
47931.77Skamil		DPRINTF("Assert that the thread exists\n");
47941.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
47951.77Skamil
47961.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
47971.77Skamil		    lwp.pl_lwpid);
47981.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
47991.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
48001.77Skamil	}
48011.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
48021.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
48031.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
48041.77Skamil
48051.77Skamil	DPRINTF("Assert that there are no more threads\n");
48061.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
48071.77Skamil
48081.77Skamil	DPRINTF("Before resuming the child process where it left off and "
48091.77Skamil	    "without signal to be sent\n");
48101.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
48111.77Skamil
48121.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48131.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48141.77Skamil
48151.77Skamil	validate_status_signaled(status, SIGKILL, 0);
48161.1Skamil
48171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48181.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48191.1Skamil}
48201.1Skamil
48211.77Skamil#define TRACEME_LWPINFO(test, threads)					\
48221.77SkamilATF_TC(test);								\
48231.77SkamilATF_TC_HEAD(test, tc)							\
48241.77Skamil{									\
48251.77Skamil	atf_tc_set_md_var(tc, "descr",					\
48261.77Skamil	    "Verify LWPINFO with the child with " #threads		\
48271.77Skamil	    " spawned extra threads");					\
48281.77Skamil}									\
48291.77Skamil									\
48301.77SkamilATF_TC_BODY(test, tc)							\
48311.77Skamil{									\
48321.77Skamil									\
48331.77Skamil	traceme_lwpinfo(threads);					\
48341.1Skamil}
48351.1Skamil
48361.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
48371.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
48381.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
48391.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
48401.77Skamil
48411.77Skamil/// ----------------------------------------------------------------------------
48421.77Skamil
48431.77Skamil#if defined(TWAIT_HAVE_PID)
48441.77Skamilstatic void
48451.77Skamilattach_lwpinfo(const int threads)
48461.1Skamil{
48471.77Skamil	const int sigval = SIGINT;
48481.1Skamil	struct msg_fds parent_tracee, parent_tracer;
48491.1Skamil	const int exitval_tracer = 10;
48501.1Skamil	pid_t tracee, tracer, wpid;
48511.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
48521.1Skamil#if defined(TWAIT_HAVE_STATUS)
48531.1Skamil	int status;
48541.1Skamil#endif
48551.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
48561.77Skamil	struct ptrace_siginfo info;
48571.77Skamil
48581.77Skamil	/* Maximum number of supported threads in this test */
48591.77Skamil	pthread_t t[3];
48601.77Skamil	int n, rv;
48611.1Skamil
48621.13Schristos	DPRINTF("Spawn tracee\n");
48631.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
48641.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
48651.1Skamil	tracee = atf_utils_fork();
48661.1Skamil	if (tracee == 0) {
48671.1Skamil		/* Wait for message from the parent */
48681.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
48691.1Skamil
48701.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
48711.77Skamil
48721.77Skamil		for (n = 0; n < threads; n++) {
48731.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
48741.77Skamil			FORKEE_ASSERT(rv == 0);
48751.77Skamil		}
48761.77Skamil
48771.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
48781.77Skamil
48791.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48801.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48811.77Skamil
48821.77Skamil		/* NOTREACHED */
48831.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
48841.1Skamil	}
48851.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
48861.1Skamil
48871.13Schristos	DPRINTF("Spawn debugger\n");
48881.1Skamil	tracer = atf_utils_fork();
48891.1Skamil	if (tracer == 0) {
48901.1Skamil		/* No IPC to communicate with the child */
48911.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
48921.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
48931.1Skamil
48941.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
48951.1Skamil		FORKEE_REQUIRE_SUCCESS(
48961.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
48971.1Skamil
48981.1Skamil		forkee_status_stopped(status, SIGSTOP);
48991.1Skamil
49001.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
49011.77Skamil		    "tracee");
49021.77Skamil		FORKEE_ASSERT(
49031.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
49041.77Skamil
49051.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49061.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
49071.77Skamil		    "si_errno=%#x\n",
49081.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49091.77Skamil		    info.psi_siginfo.si_errno);
49101.77Skamil
49111.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
49121.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
49131.77Skamil
49141.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
49151.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
49161.1Skamil		    != -1);
49171.1Skamil
49181.13Schristos		DPRINTF("Assert that there exists a thread\n");
49191.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
49201.1Skamil
49211.13Schristos		DPRINTF("Assert that lwp thread %d received event "
49221.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
49231.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
49241.1Skamil
49251.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
49261.77Skamil		    "tracee\n");
49271.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
49281.1Skamil		    != -1);
49291.1Skamil
49301.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
49311.77Skamil		    "tracee\n");
49321.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
49331.1Skamil
49341.1Skamil		/* Resume tracee with PT_CONTINUE */
49351.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
49361.1Skamil
49371.1Skamil		/* Inform parent that tracer has attached to tracee */
49381.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
49391.77Skamil
49401.1Skamil		/* Wait for parent */
49411.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
49421.1Skamil
49431.77Skamil		/* Wait for tracee and assert that it raised a signal */
49441.77Skamil		FORKEE_REQUIRE_SUCCESS(
49451.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
49461.77Skamil
49471.77Skamil		forkee_status_stopped(status, SIGINT);
49481.77Skamil
49491.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
49501.77Skamil		    "child");
49511.77Skamil		FORKEE_ASSERT(
49521.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
49531.77Skamil
49541.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49551.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
49561.77Skamil		    "si_errno=%#x\n",
49571.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49581.77Skamil		    info.psi_siginfo.si_errno);
49591.77Skamil
49601.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
49611.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
49621.77Skamil
49631.77Skamil		memset(&lwp, 0, sizeof(lwp));
49641.77Skamil
49651.77Skamil		for (n = 0; n <= threads; n++) {
49661.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
49671.77Skamil			    "child\n");
49681.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
49691.77Skamil			    sizeof(lwp)) != -1);
49701.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
49711.77Skamil
49721.77Skamil			DPRINTF("Assert that the thread exists\n");
49731.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
49741.77Skamil
49751.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
49761.77Skamil			    "event\n", lwp.pl_lwpid);
49771.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
49781.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
49791.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
49801.77Skamil		}
49811.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
49821.77Skamil		    "tracee\n");
49831.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
49841.77Skamil		    != -1);
49851.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
49861.77Skamil
49871.77Skamil		DPRINTF("Assert that there are no more threads\n");
49881.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
49891.77Skamil
49901.77Skamil		DPRINTF("Before resuming the child process where it left off "
49911.77Skamil		    "and without signal to be sent\n");
49921.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
49931.77Skamil		    != -1);
49941.77Skamil
49951.1Skamil		/* Wait for tracee and assert that it exited */
49961.1Skamil		FORKEE_REQUIRE_SUCCESS(
49971.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
49981.1Skamil
49991.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
50001.1Skamil
50011.13Schristos		DPRINTF("Before exiting of the tracer process\n");
50021.1Skamil		_exit(exitval_tracer);
50031.1Skamil	}
50041.1Skamil
50051.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
50061.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
50071.1Skamil
50081.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
50091.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
50101.77Skamil
50111.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
50121.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
50131.1Skamil
50141.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
50151.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
50161.1Skamil
50171.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
50181.1Skamil	    TWAIT_FNAME);
50191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
50201.1Skamil	    tracer);
50211.1Skamil
50221.1Skamil	validate_status_exited(status, exitval_tracer);
50231.1Skamil
50241.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
50251.1Skamil	    TWAIT_FNAME);
50261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
50271.1Skamil	    tracee);
50281.1Skamil
50291.77Skamil	validate_status_signaled(status, SIGKILL, 0);
50301.1Skamil
50311.1Skamil	msg_close(&parent_tracer);
50321.1Skamil	msg_close(&parent_tracee);
50331.1Skamil}
50341.77Skamil
50351.77Skamil#define ATTACH_LWPINFO(test, threads)					\
50361.77SkamilATF_TC(test);								\
50371.77SkamilATF_TC_HEAD(test, tc)							\
50381.77Skamil{									\
50391.77Skamil	atf_tc_set_md_var(tc, "descr",					\
50401.77Skamil	    "Verify LWPINFO with the child with " #threads		\
50411.77Skamil	    " spawned extra threads (tracer is not the original "	\
50421.77Skamil	    "parent)");							\
50431.77Skamil}									\
50441.77Skamil									\
50451.77SkamilATF_TC_BODY(test, tc)							\
50461.77Skamil{									\
50471.77Skamil									\
50481.77Skamil	attach_lwpinfo(threads);					\
50491.77Skamil}
50501.77Skamil
50511.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
50521.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
50531.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
50541.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
50551.1Skamil#endif
50561.1Skamil
50571.77Skamil/// ----------------------------------------------------------------------------
50581.77Skamil
50591.1Skamilstatic void
50601.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
50611.1Skamil{
50621.1Skamil	const int exitval = 5;
50631.1Skamil	const int sigval = SIGINT;
50641.1Skamil	const int sigfaked = SIGTRAP;
50651.1Skamil	const int sicodefaked = TRAP_BRKPT;
50661.1Skamil	pid_t child, wpid;
50671.1Skamil	struct sigaction sa;
50681.1Skamil#if defined(TWAIT_HAVE_STATUS)
50691.1Skamil	int status;
50701.1Skamil#endif
50711.1Skamil	struct ptrace_siginfo info;
50721.1Skamil	memset(&info, 0, sizeof(info));
50731.1Skamil
50741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50761.1Skamil	if (child == 0) {
50771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50791.1Skamil
50801.79Skamil		sa.sa_sigaction = sah;
50811.1Skamil		sa.sa_flags = SA_SIGINFO;
50821.1Skamil		sigemptyset(&sa.sa_mask);
50831.1Skamil
50841.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
50851.79Skamil		    != -1);
50861.1Skamil
50871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50891.1Skamil
50901.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
50911.1Skamil
50921.13Schristos		DPRINTF("Before exiting of the child process\n");
50931.1Skamil		_exit(exitval);
50941.1Skamil	}
50951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50961.1Skamil
50971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50991.1Skamil
51001.1Skamil	validate_status_stopped(status, sigval);
51011.1Skamil
51021.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51031.61Skre	SYSCALL_REQUIRE(
51041.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51051.1Skamil
51061.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
51071.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
51081.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
51091.1Skamil	    info.psi_siginfo.si_errno);
51101.1Skamil
51111.79Skamil	if (faked) {
51121.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
51131.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
51141.79Skamil		info.psi_siginfo.si_signo = sigfaked;
51151.79Skamil		info.psi_siginfo.si_code = sicodefaked;
51161.79Skamil	}
51171.1Skamil
51181.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
51191.61Skre	SYSCALL_REQUIRE(
51201.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
51211.1Skamil
51221.79Skamil	if (faked) {
51231.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
51241.79Skamil		    "child\n");
51251.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
51261.79Skamil		    sizeof(info)) != -1);
51271.1Skamil
51281.79Skamil		DPRINTF("Before checking siginfo_t\n");
51291.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
51301.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
51311.79Skamil	}
51321.1Skamil
51331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51341.1Skamil	    "without signal to be sent\n");
51351.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
51361.79Skamil	    faked ? sigfaked : sigval) != -1);
51371.1Skamil
51381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51401.1Skamil
51411.1Skamil	validate_status_exited(status, exitval);
51421.1Skamil
51431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51451.1Skamil}
51461.1Skamil
51471.79Skamil#define PTRACE_SIGINFO(test, faked)					\
51481.79SkamilATF_TC(test);								\
51491.79SkamilATF_TC_HEAD(test, tc)							\
51501.79Skamil{									\
51511.79Skamil	atf_tc_set_md_var(tc, "descr",					\
51521.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
51531.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
51541.79Skamil}									\
51551.79Skamil									\
51561.79Skamilstatic int test##_caught = 0;						\
51571.79Skamil									\
51581.79Skamilstatic void								\
51591.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
51601.79Skamil{									\
51611.79Skamil	if (faked) {							\
51621.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
51631.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
51641.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
51651.79Skamil	} else {							\
51661.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
51671.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
51681.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
51691.79Skamil	}								\
51701.79Skamil									\
51711.79Skamil	++ test##_caught;						\
51721.79Skamil}									\
51731.79Skamil									\
51741.79SkamilATF_TC_BODY(test, tc)							\
51751.79Skamil{									\
51761.79Skamil									\
51771.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
51781.79Skamil}
51791.79Skamil
51801.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
51811.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
51821.79Skamil
51831.79Skamil/// ----------------------------------------------------------------------------
51841.79Skamil
51851.97Skamilstatic void
51861.97Skamiltraceme_exec(bool masked, bool ignored)
51871.1Skamil{
51881.1Skamil	const int sigval = SIGTRAP;
51891.1Skamil	pid_t child, wpid;
51901.1Skamil#if defined(TWAIT_HAVE_STATUS)
51911.1Skamil	int status;
51921.1Skamil#endif
51931.97Skamil	struct sigaction sa;
51941.97Skamil	struct ptrace_siginfo info;
51951.97Skamil	sigset_t intmask;
51961.97Skamil	struct kinfo_proc2 kp;
51971.97Skamil	size_t len = sizeof(kp);
51981.97Skamil
51991.97Skamil	int name[6];
52001.97Skamil	const size_t namelen = __arraycount(name);
52011.97Skamil	ki_sigset_t kp_sigmask;
52021.97Skamil	ki_sigset_t kp_sigignore;
52031.1Skamil
52041.1Skamil	memset(&info, 0, sizeof(info));
52051.1Skamil
52061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52081.1Skamil	if (child == 0) {
52091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52111.1Skamil
52121.97Skamil		if (masked) {
52131.97Skamil			sigemptyset(&intmask);
52141.97Skamil			sigaddset(&intmask, sigval);
52151.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
52161.97Skamil		}
52171.97Skamil
52181.97Skamil		if (ignored) {
52191.97Skamil			memset(&sa, 0, sizeof(sa));
52201.97Skamil			sa.sa_handler = SIG_IGN;
52211.97Skamil			sigemptyset(&sa.sa_mask);
52221.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
52231.97Skamil		}
52241.97Skamil
52251.13Schristos		DPRINTF("Before calling execve(2) from child\n");
52261.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
52271.1Skamil
52281.1Skamil		FORKEE_ASSERT(0 && "Not reached");
52291.1Skamil	}
52301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52311.1Skamil
52321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52341.1Skamil
52351.1Skamil	validate_status_stopped(status, sigval);
52361.1Skamil
52371.97Skamil	name[0] = CTL_KERN,
52381.97Skamil	name[1] = KERN_PROC2,
52391.97Skamil	name[2] = KERN_PROC_PID;
52401.97Skamil	name[3] = getpid();
52411.97Skamil	name[4] = sizeof(kp);
52421.97Skamil	name[5] = 1;
52431.97Skamil
52441.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
52451.97Skamil
52461.97Skamil	if (masked)
52471.97Skamil		kp_sigmask = kp.p_sigmask;
52481.97Skamil
52491.97Skamil	if (ignored)
52501.97Skamil		kp_sigignore = kp.p_sigignore;
52511.97Skamil
52521.97Skamil	name[3] = getpid();
52531.97Skamil
52541.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
52551.97Skamil
52561.97Skamil	if (masked) {
52571.97Skamil		DPRINTF("kp_sigmask="
52581.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
52591.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
52601.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
52611.97Skamil
52621.97Skamil		DPRINTF("kp.p_sigmask="
52631.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
52641.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
52651.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
52661.97Skamil
52671.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
52681.97Skamil		    sizeof(kp_sigmask)));
52691.97Skamil	}
52701.97Skamil
52711.97Skamil	if (ignored) {
52721.97Skamil		DPRINTF("kp_sigignore="
52731.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
52741.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
52751.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
52761.97Skamil
52771.97Skamil		DPRINTF("kp.p_sigignore="
52781.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
52791.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
52801.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
52811.97Skamil
52821.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
52831.97Skamil		    sizeof(kp_sigignore)));
52841.97Skamil	}
52851.97Skamil
52861.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52871.61Skre	SYSCALL_REQUIRE(
52881.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52891.1Skamil
52901.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
52911.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
52921.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
52931.1Skamil	    info.psi_siginfo.si_errno);
52941.1Skamil
52951.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
52961.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
52971.1Skamil
52981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52991.1Skamil	    "without signal to be sent\n");
53001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53011.1Skamil
53021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53041.1Skamil
53051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53071.1Skamil}
53081.1Skamil
53091.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
53101.97SkamilATF_TC(test);								\
53111.97SkamilATF_TC_HEAD(test, tc)							\
53121.97Skamil{									\
53131.97Skamil       atf_tc_set_md_var(tc, "descr",					\
53141.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
53151.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
53161.97Skamil           masked ? " with ignored signal" : "");			\
53171.97Skamil}									\
53181.97Skamil									\
53191.97SkamilATF_TC_BODY(test, tc)							\
53201.97Skamil{									\
53211.97Skamil									\
53221.97Skamil       traceme_exec(masked, ignored);					\
53231.97Skamil}
53241.97Skamil
53251.97SkamilTRACEME_EXEC(traceme_exec, false, false)
53261.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
53271.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
53281.97Skamil
53291.82Skamil/// ----------------------------------------------------------------------------
53301.82Skamil
53311.83Skamilstatic volatile int done;
53321.1Skamil
53331.83Skamilstatic void *
53341.83Skamiltrace_threads_cb(void *arg __unused)
53351.1Skamil{
53361.1Skamil
53371.83Skamil	done++;
53381.83Skamil
53391.83Skamil	while (done < 3)
53401.83Skamil		continue;
53411.83Skamil
53421.83Skamil	return NULL;
53431.1Skamil}
53441.1Skamil
53451.83Skamilstatic void
53461.83Skamiltrace_threads(bool trace_create, bool trace_exit)
53471.1Skamil{
53481.1Skamil	const int sigval = SIGSTOP;
53491.1Skamil	pid_t child, wpid;
53501.1Skamil#if defined(TWAIT_HAVE_STATUS)
53511.1Skamil	int status;
53521.1Skamil#endif
53531.1Skamil	ptrace_state_t state;
53541.1Skamil	const int slen = sizeof(state);
53551.1Skamil	ptrace_event_t event;
53561.1Skamil	const int elen = sizeof(event);
53571.83Skamil	struct ptrace_siginfo info;
53581.83Skamil
53591.83Skamil	pthread_t t[3];
53601.83Skamil	int rv;
53611.83Skamil	size_t n;
53621.1Skamil	lwpid_t lid;
53631.83Skamil
53641.83Skamil	/* Track created and exited threads */
53651.83Skamil	bool traced_lwps[__arraycount(t)];
53661.83Skamil
53671.120Skamil	if (trace_create || trace_exit)
53681.119Skamil		atf_tc_skip("PR kern/51995");
53691.1Skamil
53701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53721.1Skamil	if (child == 0) {
53731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53751.1Skamil
53761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53781.1Skamil
53791.83Skamil		for (n = 0; n < __arraycount(t); n++) {
53801.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
53811.83Skamil			    NULL);
53821.83Skamil			FORKEE_ASSERT(rv == 0);
53831.83Skamil		}
53841.1Skamil
53851.83Skamil		for (n = 0; n < __arraycount(t); n++) {
53861.83Skamil			rv = pthread_join(t[n], NULL);
53871.83Skamil			FORKEE_ASSERT(rv == 0);
53881.83Skamil		}
53891.1Skamil
53901.83Skamil		/*
53911.83Skamil		 * There is race between _exit() and pthread_join() detaching
53921.83Skamil		 * a thread. For simplicity kill the process after detecting
53931.83Skamil		 * LWP events.
53941.83Skamil		 */
53951.83Skamil		while (true)
53961.83Skamil			continue;
53971.1Skamil
53981.83Skamil		FORKEE_ASSERT(0 && "Not reached");
53991.1Skamil	}
54001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54011.1Skamil
54021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54041.1Skamil
54051.1Skamil	validate_status_stopped(status, sigval);
54061.1Skamil
54071.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
54081.83Skamil	SYSCALL_REQUIRE(
54091.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
54101.1Skamil
54111.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
54121.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
54131.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
54141.83Skamil	    info.psi_siginfo.si_errno);
54151.1Skamil
54161.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
54171.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
54181.1Skamil
54191.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
54201.83Skamil	memset(&event, 0, sizeof(event));
54211.83Skamil	if (trace_create)
54221.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
54231.83Skamil	if (trace_exit)
54241.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
54251.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
54261.1Skamil
54271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54281.1Skamil	    "without signal to be sent\n");
54291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54301.1Skamil
54311.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
54321.1Skamil
54331.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
54341.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
54351.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
54361.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
54371.83Skamil		    child);
54381.1Skamil
54391.83Skamil		validate_status_stopped(status, SIGTRAP);
54401.1Skamil
54411.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
54421.83Skamil		    "child\n");
54431.83Skamil		SYSCALL_REQUIRE(
54441.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
54451.1Skamil
54461.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
54471.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
54481.83Skamil		    "si_errno=%#x\n",
54491.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
54501.83Skamil		    info.psi_siginfo.si_errno);
54511.1Skamil
54521.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
54531.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
54541.1Skamil
54551.83Skamil		SYSCALL_REQUIRE(
54561.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54571.1Skamil
54581.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
54591.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
54601.1Skamil
54611.83Skamil		lid = state.pe_lwp;
54621.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
54631.1Skamil
54641.83Skamil		traced_lwps[lid - 1] = true;
54651.1Skamil
54661.83Skamil		DPRINTF("Before resuming the child process where it left off "
54671.83Skamil		    "and without signal to be sent\n");
54681.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54691.83Skamil	}
54701.1Skamil
54711.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
54721.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
54731.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
54741.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
54751.83Skamil		    child);
54761.1Skamil
54771.83Skamil		validate_status_stopped(status, SIGTRAP);
54781.1Skamil
54791.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
54801.83Skamil		    "child\n");
54811.83Skamil		SYSCALL_REQUIRE(
54821.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
54831.1Skamil
54841.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
54851.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
54861.83Skamil		    "si_errno=%#x\n",
54871.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
54881.83Skamil		    info.psi_siginfo.si_errno);
54891.1Skamil
54901.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
54911.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
54921.1Skamil
54931.83Skamil		SYSCALL_REQUIRE(
54941.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54951.1Skamil
54961.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
54971.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
54981.1Skamil
54991.83Skamil		lid = state.pe_lwp;
55001.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
55011.1Skamil
55021.83Skamil		if (trace_create) {
55031.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
55041.83Skamil			traced_lwps[lid - 1] = false;
55051.83Skamil		}
55061.1Skamil
55071.83Skamil		DPRINTF("Before resuming the child process where it left off "
55081.83Skamil		    "and without signal to be sent\n");
55091.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55101.83Skamil	}
55111.1Skamil
55121.83Skamil	kill(child, SIGKILL);
55131.1Skamil
55141.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55151.1Skamil	    TWAIT_FNAME);
55161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55171.1Skamil
55181.83Skamil	validate_status_signaled(status, SIGKILL, 0);
55191.1Skamil
55201.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55211.1Skamil	    TWAIT_FNAME);
55221.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55231.1Skamil}
55241.1Skamil
55251.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
55261.83SkamilATF_TC(test);								\
55271.83SkamilATF_TC_HEAD(test, tc)							\
55281.83Skamil{									\
55291.83Skamil        atf_tc_set_md_var(tc, "descr",					\
55301.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
55311.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
55321.83Skamil	    trace_exit ? "" : "out");					\
55331.83Skamil}									\
55341.83Skamil									\
55351.83SkamilATF_TC_BODY(test, tc)							\
55361.83Skamil{									\
55371.83Skamil									\
55381.83Skamil        trace_threads(trace_create, trace_exit);			\
55391.83Skamil}
55401.83Skamil
55411.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false)
55421.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true)
55431.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false)
55441.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true)
55451.83Skamil
55461.83Skamil/// ----------------------------------------------------------------------------
55471.83Skamil
55481.84SkamilATF_TC(signal_mask_unrelated);
55491.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
55501.1Skamil{
55511.1Skamil	atf_tc_set_md_var(tc, "descr",
55521.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
55531.1Skamil	    "from catching other signals");
55541.1Skamil}
55551.1Skamil
55561.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
55571.1Skamil{
55581.1Skamil	const int exitval = 5;
55591.1Skamil	const int sigval = SIGSTOP;
55601.1Skamil	const int sigmasked = SIGTRAP;
55611.1Skamil	const int signotmasked = SIGINT;
55621.1Skamil	pid_t child, wpid;
55631.1Skamil#if defined(TWAIT_HAVE_STATUS)
55641.1Skamil	int status;
55651.1Skamil#endif
55661.1Skamil	sigset_t intmask;
55671.1Skamil
55681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55701.1Skamil	if (child == 0) {
55711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55731.1Skamil
55741.1Skamil		sigemptyset(&intmask);
55751.1Skamil		sigaddset(&intmask, sigmasked);
55761.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
55771.1Skamil
55781.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55791.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55801.1Skamil
55811.13Schristos		DPRINTF("Before raising %s from child\n",
55821.1Skamil		    strsignal(signotmasked));
55831.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
55841.1Skamil
55851.13Schristos		DPRINTF("Before exiting of the child process\n");
55861.1Skamil		_exit(exitval);
55871.1Skamil	}
55881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55891.1Skamil
55901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55921.1Skamil
55931.1Skamil	validate_status_stopped(status, sigval);
55941.1Skamil
55951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55961.1Skamil	    "without signal to be sent\n");
55971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55981.1Skamil
55991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56011.1Skamil
56021.1Skamil	validate_status_stopped(status, signotmasked);
56031.1Skamil
56041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56051.1Skamil	    "without signal to be sent\n");
56061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56071.1Skamil
56081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56101.1Skamil
56111.1Skamil	validate_status_exited(status, exitval);
56121.1Skamil
56131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56151.1Skamil}
56161.1Skamil
56171.84Skamil/// ----------------------------------------------------------------------------
56181.84Skamil
56191.1Skamil#if defined(TWAIT_HAVE_PID)
56201.99Skamilstatic void
56211.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked,
56221.99Skamil           bool ignored)
56231.1Skamil{
56241.1Skamil	const int exitval = 5;
56251.1Skamil	const int exitval2 = 15;
56261.1Skamil	const int sigval = SIGSTOP;
56271.99Skamil	pid_t child, child2 = 0, wpid;
56281.1Skamil#if defined(TWAIT_HAVE_STATUS)
56291.1Skamil	int status;
56301.1Skamil#endif
56311.1Skamil	ptrace_state_t state;
56321.1Skamil	const int slen = sizeof(state);
56331.1Skamil	ptrace_event_t event;
56341.1Skamil	const int elen = sizeof(event);
56351.99Skamil	pid_t (*fn)(void);
56361.99Skamil	struct sigaction sa;
56371.99Skamil	struct ptrace_siginfo info;
56381.99Skamil	sigset_t intmask;
56391.99Skamil	struct kinfo_proc2 kp;
56401.99Skamil	size_t len = sizeof(kp);
56411.99Skamil
56421.99Skamil	int name[6];
56431.99Skamil	const size_t namelen = __arraycount(name);
56441.99Skamil	ki_sigset_t kp_sigmask;
56451.99Skamil	ki_sigset_t kp_sigignore;
56461.1Skamil
56471.99Skamil	if (trackfork)
56481.99Skamil		fn = fork;
56491.99Skamil	if (trackvfork || trackvforkdone)
56501.99Skamil		fn = vfork;
56511.14Schristos
56521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56541.1Skamil	if (child == 0) {
56551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56571.1Skamil
56581.99Skamil		if (masked) {
56591.99Skamil			sigemptyset(&intmask);
56601.99Skamil			sigaddset(&intmask, SIGTRAP);
56611.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
56621.99Skamil		}
56631.99Skamil
56641.99Skamil		if (ignored) {
56651.99Skamil			memset(&sa, 0, sizeof(sa));
56661.99Skamil			sa.sa_handler = SIG_IGN;
56671.99Skamil			sigemptyset(&sa.sa_mask);
56681.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
56691.99Skamil		}
56701.1Skamil
56711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56731.1Skamil
56741.99Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
56751.1Skamil
56761.1Skamil		if (child2 == 0)
56771.1Skamil			_exit(exitval2);
56781.1Skamil
56791.1Skamil		FORKEE_REQUIRE_SUCCESS
56801.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
56811.1Skamil
56821.1Skamil		forkee_status_exited(status, exitval2);
56831.1Skamil
56841.13Schristos		DPRINTF("Before exiting of the child process\n");
56851.1Skamil		_exit(exitval);
56861.1Skamil	}
56871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56881.1Skamil
56891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56911.1Skamil
56921.1Skamil	validate_status_stopped(status, sigval);
56931.1Skamil
56941.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
56951.99Skamil	SYSCALL_REQUIRE(
56961.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
56971.99Skamil
56981.99Skamil	DPRINTF("Before checking siginfo_t\n");
56991.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
57001.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
57011.1Skamil
57021.99Skamil	name[0] = CTL_KERN,
57031.99Skamil	name[1] = KERN_PROC2,
57041.99Skamil	name[2] = KERN_PROC_PID;
57051.99Skamil	name[3] = child;
57061.99Skamil	name[4] = sizeof(kp);
57071.99Skamil	name[5] = 1;
57081.1Skamil
57091.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
57101.1Skamil
57111.99Skamil	if (masked)
57121.99Skamil		kp_sigmask = kp.p_sigmask;
57131.1Skamil
57141.99Skamil	if (ignored)
57151.99Skamil		kp_sigignore = kp.p_sigignore;
57161.1Skamil
57171.99Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
57181.99Skamil	    trackfork ? "|PTRACE_FORK" : "",
57191.99Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
57201.99Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
57211.99Skamil	event.pe_set_event = 0;
57221.99Skamil	if (trackfork)
57231.99Skamil		event.pe_set_event |= PTRACE_FORK;
57241.99Skamil	if (trackvfork)
57251.99Skamil		event.pe_set_event |= PTRACE_VFORK;
57261.99Skamil	if (trackvforkdone)
57271.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
57281.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
57291.1Skamil
57301.99Skamil	DPRINTF("Before resuming the child process where it left off and "
57311.99Skamil	    "without signal to be sent\n");
57321.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57331.1Skamil
57341.99Skamil	if (trackfork || trackvfork) {
57351.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
57361.99Skamil		    child);
57371.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
57381.99Skamil		    child);
57391.1Skamil
57401.99Skamil		validate_status_stopped(status, SIGTRAP);
57411.1Skamil
57421.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
57431.1Skamil
57441.99Skamil		if (masked) {
57451.99Skamil			DPRINTF("kp_sigmask="
57461.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
57471.99Skamil			    PRIx32 "\n",
57481.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
57491.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
57501.1Skamil
57511.99Skamil			DPRINTF("kp.p_sigmask="
57521.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
57531.99Skamil			    PRIx32 "\n",
57541.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
57551.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
57561.1Skamil
57571.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
57581.99Skamil			    sizeof(kp_sigmask)));
57591.99Skamil		}
57601.1Skamil
57611.99Skamil		if (ignored) {
57621.99Skamil			DPRINTF("kp_sigignore="
57631.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
57641.99Skamil			    PRIx32 "\n",
57651.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
57661.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
57671.1Skamil
57681.99Skamil			DPRINTF("kp.p_sigignore="
57691.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
57701.99Skamil			    PRIx32 "\n",
57711.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
57721.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
57731.1Skamil
57741.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
57751.99Skamil			    sizeof(kp_sigignore)));
57761.99Skamil		}
57771.1Skamil
57781.99Skamil		SYSCALL_REQUIRE(
57791.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
57801.99Skamil		if (trackfork) {
57811.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
57821.99Skamil			       PTRACE_FORK);
57831.99Skamil		}
57841.99Skamil		if (trackvfork) {
57851.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
57861.99Skamil			       PTRACE_VFORK);
57871.99Skamil		}
57881.1Skamil
57891.99Skamil		child2 = state.pe_other_pid;
57901.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
57911.1Skamil
57921.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
57931.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
57941.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
57951.99Skamil		    child2);
57961.1Skamil
57971.99Skamil		validate_status_stopped(status, SIGTRAP);
57981.1Skamil
57991.99Skamil		name[3] = child2;
58001.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
58011.1Skamil
58021.99Skamil		if (masked) {
58031.99Skamil			DPRINTF("kp_sigmask="
58041.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58051.99Skamil			    PRIx32 "\n",
58061.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
58071.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
58081.1Skamil
58091.99Skamil			DPRINTF("kp.p_sigmask="
58101.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58111.99Skamil			    PRIx32 "\n",
58121.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
58131.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
58141.14Schristos
58151.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
58161.99Skamil			    sizeof(kp_sigmask)));
58171.99Skamil		}
58181.1Skamil
58191.99Skamil		if (ignored) {
58201.99Skamil			DPRINTF("kp_sigignore="
58211.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58221.99Skamil			    PRIx32 "\n",
58231.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
58241.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
58251.1Skamil
58261.99Skamil			DPRINTF("kp.p_sigignore="
58271.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58281.99Skamil			    PRIx32 "\n",
58291.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
58301.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
58311.1Skamil
58321.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
58331.99Skamil			    sizeof(kp_sigignore)));
58341.99Skamil		}
58351.1Skamil
58361.99Skamil		SYSCALL_REQUIRE(
58371.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
58381.99Skamil		if (trackfork) {
58391.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
58401.99Skamil			       PTRACE_FORK);
58411.99Skamil		}
58421.99Skamil		if (trackvfork) {
58431.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
58441.99Skamil			       PTRACE_VFORK);
58451.99Skamil		}
58461.1Skamil
58471.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
58481.1Skamil
58491.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
58501.99Skamil		    "and without signal to be sent\n");
58511.99Skamil		SYSCALL_REQUIRE(
58521.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
58531.1Skamil
58541.99Skamil		DPRINTF("Before resuming the child process where it left off "
58551.99Skamil		    "and without signal to be sent\n");
58561.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58571.1Skamil	}
58581.1Skamil
58591.99Skamil	if (trackvforkdone) {
58601.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
58611.99Skamil		    child);
58621.99Skamil		TWAIT_REQUIRE_SUCCESS(
58631.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
58641.1Skamil
58651.99Skamil		validate_status_stopped(status, SIGTRAP);
58661.1Skamil
58671.99Skamil		name[3] = child;
58681.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
58691.1Skamil
58701.102Skamil		/*
58711.102Skamil		 * SIGCHLD is now pending in the signal queue and
58721.102Skamil		 * the kernel presents it to userland as a masked signal.
58731.102Skamil		 */
58741.102Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
58751.102Skamil
58761.99Skamil		if (masked) {
58771.99Skamil			DPRINTF("kp_sigmask="
58781.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58791.99Skamil			    PRIx32 "\n",
58801.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
58811.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
58821.1Skamil
58831.99Skamil			DPRINTF("kp.p_sigmask="
58841.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58851.99Skamil			    PRIx32 "\n",
58861.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
58871.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
58881.1Skamil
58891.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
58901.99Skamil			    sizeof(kp_sigmask)));
58911.99Skamil		}
58921.1Skamil
58931.99Skamil		if (ignored) {
58941.99Skamil			DPRINTF("kp_sigignore="
58951.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
58961.99Skamil			    PRIx32 "\n",
58971.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
58981.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
58991.1Skamil
59001.99Skamil			DPRINTF("kp.p_sigignore="
59011.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
59021.99Skamil			    PRIx32 "\n",
59031.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
59041.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
59051.1Skamil
59061.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
59071.99Skamil			    sizeof(kp_sigignore)));
59081.99Skamil		}
59091.1Skamil
59101.99Skamil		SYSCALL_REQUIRE(
59111.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
59121.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
59131.1Skamil
59141.99Skamil		child2 = state.pe_other_pid;
59151.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
59161.99Skamil		    child2);
59171.1Skamil
59181.99Skamil		DPRINTF("Before resuming the child process where it left off "
59191.99Skamil		    "and without signal to be sent\n");
59201.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59211.99Skamil	}
59221.1Skamil
59231.99Skamil	if (trackfork || trackvfork) {
59241.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
59251.99Skamil		    "\n", TWAIT_FNAME);
59261.99Skamil		TWAIT_REQUIRE_SUCCESS(
59271.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
59281.1Skamil
59291.99Skamil		validate_status_exited(status, exitval2);
59301.1Skamil
59311.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
59321.99Skamil		    "process\n", TWAIT_FNAME);
59331.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
59341.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
59351.99Skamil	}
59361.1Skamil
59371.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59381.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
59391.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59401.1Skamil
59411.1Skamil	validate_status_stopped(status, SIGCHLD);
59421.1Skamil
59431.57Skamil	DPRINTF("Before resuming the child process where it left off and "
59441.1Skamil	    "without signal to be sent\n");
59451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59461.1Skamil
59471.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59481.1Skamil	    TWAIT_FNAME);
59491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59501.1Skamil
59511.1Skamil	validate_status_exited(status, exitval);
59521.1Skamil
59531.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59541.57Skamil	    TWAIT_FNAME);
59551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59561.1Skamil}
59571.1Skamil
59581.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone,		\
59591.99Skamil                   masked,ignored)					\
59601.99SkamilATF_TC(name);								\
59611.99SkamilATF_TC_HEAD(name, tc)							\
59621.99Skamil{									\
59631.99Skamil	atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught "	\
59641.99Skamil	    "regardless of signal %s%s", 				\
59651.99Skamil	    trackfork ? "PTRACE_FORK" : "",				\
59661.99Skamil	    trackvfork ? "PTRACE_VFORK" : "",				\
59671.99Skamil	    trackvforkdone ? "PTRACE_VFORK_DONE" : "",			\
59681.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
59691.99Skamil}									\
59701.99Skamil									\
59711.99SkamilATF_TC_BODY(name, tc)							\
59721.99Skamil{									\
59731.99Skamil									\
59741.99Skamil	fork2_body(trackfork, trackvfork, trackvforkdone, masked,	\
59751.99Skamil	           ignored);						\
59761.1Skamil}
59771.1Skamil
59781.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false)
59791.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true)
59801.110Skamil#if TEST_VFORK_ENABLED
59811.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false)
59821.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true)
59831.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false)
59841.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true)
59851.1Skamil#endif
59861.110Skamil#endif
59871.1Skamil
59881.99Skamil/// ----------------------------------------------------------------------------
59891.1Skamil
59901.83Skamilvolatile lwpid_t the_lwp_id = 0;
59911.83Skamil
59921.83Skamilstatic void
59931.83Skamillwp_main_func(void *arg)
59941.83Skamil{
59951.83Skamil	the_lwp_id = _lwp_self();
59961.83Skamil	_lwp_exit();
59971.83Skamil}
59981.83Skamil
59991.1SkamilATF_TC(signal9);
60001.1SkamilATF_TC_HEAD(signal9, tc)
60011.1Skamil{
60021.1Skamil	atf_tc_set_md_var(tc, "descr",
60031.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
60041.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
60051.1Skamil}
60061.1Skamil
60071.1SkamilATF_TC_BODY(signal9, tc)
60081.1Skamil{
60091.1Skamil	const int exitval = 5;
60101.1Skamil	const int sigval = SIGSTOP;
60111.1Skamil	const int sigmasked = SIGTRAP;
60121.1Skamil	pid_t child, wpid;
60131.1Skamil#if defined(TWAIT_HAVE_STATUS)
60141.1Skamil	int status;
60151.1Skamil#endif
60161.1Skamil	sigset_t intmask;
60171.1Skamil	ptrace_state_t state;
60181.1Skamil	const int slen = sizeof(state);
60191.1Skamil	ptrace_event_t event;
60201.1Skamil	const int elen = sizeof(event);
60211.1Skamil	ucontext_t uc;
60221.1Skamil	lwpid_t lid;
60231.1Skamil	static const size_t ssize = 16*1024;
60241.1Skamil	void *stack;
60251.1Skamil
60261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60281.1Skamil	if (child == 0) {
60291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60311.1Skamil
60321.1Skamil		sigemptyset(&intmask);
60331.1Skamil		sigaddset(&intmask, sigmasked);
60341.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
60351.1Skamil
60361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60381.1Skamil
60391.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
60401.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
60411.1Skamil
60421.13Schristos		DPRINTF("Before making context for new lwp in child\n");
60431.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
60441.1Skamil
60451.13Schristos		DPRINTF("Before creating new in child\n");
60461.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
60471.1Skamil
60481.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
60491.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
60501.1Skamil
60511.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
60521.1Skamil		    "are the same\n", lid, the_lwp_id);
60531.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
60541.1Skamil
60551.13Schristos		DPRINTF("Before exiting of the child process\n");
60561.1Skamil		_exit(exitval);
60571.1Skamil	}
60581.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60591.1Skamil
60601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60621.1Skamil
60631.1Skamil	validate_status_stopped(status, sigval);
60641.1Skamil
60651.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
60661.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
60671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
60681.1Skamil
60691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60701.1Skamil	    "without signal to be sent\n");
60711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60721.1Skamil
60731.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60741.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
60751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60761.1Skamil
60771.1Skamil	validate_status_stopped(status, sigmasked);
60781.1Skamil
60791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
60801.1Skamil
60811.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
60821.1Skamil
60831.1Skamil	lid = state.pe_lwp;
60841.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
60851.1Skamil
60861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60871.1Skamil	    "without signal to be sent\n");
60881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60891.1Skamil
60901.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60911.1Skamil	    TWAIT_FNAME);
60921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60931.1Skamil
60941.1Skamil	validate_status_exited(status, exitval);
60951.1Skamil
60961.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60971.1Skamil	    TWAIT_FNAME);
60981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60991.1Skamil}
61001.1Skamil
61011.1SkamilATF_TC(signal10);
61021.1SkamilATF_TC_HEAD(signal10, tc)
61031.1Skamil{
61041.1Skamil	atf_tc_set_md_var(tc, "descr",
61051.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61061.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
61071.1Skamil}
61081.1Skamil
61091.1SkamilATF_TC_BODY(signal10, tc)
61101.1Skamil{
61111.1Skamil	const int exitval = 5;
61121.1Skamil	const int sigval = SIGSTOP;
61131.1Skamil	const int sigmasked = SIGTRAP;
61141.1Skamil	pid_t child, wpid;
61151.1Skamil#if defined(TWAIT_HAVE_STATUS)
61161.1Skamil	int status;
61171.1Skamil#endif
61181.1Skamil	sigset_t intmask;
61191.1Skamil	ptrace_state_t state;
61201.1Skamil	const int slen = sizeof(state);
61211.1Skamil	ptrace_event_t event;
61221.1Skamil	const int elen = sizeof(event);
61231.1Skamil	ucontext_t uc;
61241.1Skamil	lwpid_t lid;
61251.1Skamil	static const size_t ssize = 16*1024;
61261.1Skamil	void *stack;
61271.1Skamil
61281.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61291.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61301.1Skamil	if (child == 0) {
61311.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61321.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61331.1Skamil
61341.1Skamil		sigemptyset(&intmask);
61351.1Skamil		sigaddset(&intmask, sigmasked);
61361.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61371.1Skamil
61381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61401.1Skamil
61411.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
61421.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
61431.1Skamil
61441.13Schristos		DPRINTF("Before making context for new lwp in child\n");
61451.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
61461.1Skamil
61471.13Schristos		DPRINTF("Before creating new in child\n");
61481.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
61491.1Skamil
61501.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
61511.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
61521.1Skamil
61531.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
61541.1Skamil		    "are the same\n", lid, the_lwp_id);
61551.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
61561.1Skamil
61571.13Schristos		DPRINTF("Before exiting of the child process\n");
61581.1Skamil		_exit(exitval);
61591.1Skamil	}
61601.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61611.1Skamil
61621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61641.1Skamil
61651.1Skamil	validate_status_stopped(status, sigval);
61661.1Skamil
61671.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
61681.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
61691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
61701.1Skamil
61711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61721.1Skamil	    "without signal to be sent\n");
61731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61741.1Skamil
61751.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61761.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
61771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61781.1Skamil
61791.1Skamil	validate_status_stopped(status, sigmasked);
61801.1Skamil
61811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
61821.1Skamil
61831.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
61841.1Skamil
61851.1Skamil	lid = state.pe_lwp;
61861.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
61871.1Skamil
61881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61891.1Skamil	    "without signal to be sent\n");
61901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61911.1Skamil
61921.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61931.1Skamil	    TWAIT_FNAME);
61941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61951.1Skamil
61961.1Skamil	validate_status_exited(status, exitval);
61971.1Skamil
61981.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61991.1Skamil	    TWAIT_FNAME);
62001.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62011.1Skamil}
62021.1Skamil
62031.1Skamilstatic void
62041.1Skamillwp_main_stop(void *arg)
62051.1Skamil{
62061.1Skamil	the_lwp_id = _lwp_self();
62071.1Skamil
62081.1Skamil	raise(SIGTRAP);
62091.1Skamil
62101.1Skamil	_lwp_exit();
62111.1Skamil}
62121.1Skamil
62131.1SkamilATF_TC(suspend1);
62141.1SkamilATF_TC_HEAD(suspend1, tc)
62151.1Skamil{
62161.1Skamil	atf_tc_set_md_var(tc, "descr",
62171.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
62181.1Skamil	    "resumed by a tracee");
62191.1Skamil}
62201.1Skamil
62211.1SkamilATF_TC_BODY(suspend1, tc)
62221.1Skamil{
62231.1Skamil	const int exitval = 5;
62241.1Skamil	const int sigval = SIGSTOP;
62251.1Skamil	pid_t child, wpid;
62261.1Skamil#if defined(TWAIT_HAVE_STATUS)
62271.1Skamil	int status;
62281.1Skamil#endif
62291.1Skamil	ucontext_t uc;
62301.1Skamil	lwpid_t lid;
62311.1Skamil	static const size_t ssize = 16*1024;
62321.1Skamil	void *stack;
62331.1Skamil	struct ptrace_lwpinfo pl;
62341.1Skamil	struct ptrace_siginfo psi;
62351.1Skamil	volatile int go = 0;
62361.1Skamil
62371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62391.1Skamil	if (child == 0) {
62401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62421.1Skamil
62431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62451.1Skamil
62461.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62471.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62481.1Skamil
62491.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62501.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
62511.1Skamil
62521.13Schristos		DPRINTF("Before creating new in child\n");
62531.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62541.1Skamil
62551.1Skamil		while (go == 0)
62561.1Skamil			continue;
62571.1Skamil
62581.1Skamil		raise(SIGINT);
62591.1Skamil
62601.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
62611.1Skamil
62621.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62631.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62641.1Skamil
62651.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62661.1Skamil		    "are the same\n", lid, the_lwp_id);
62671.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
62681.1Skamil
62691.13Schristos		DPRINTF("Before exiting of the child process\n");
62701.1Skamil		_exit(exitval);
62711.1Skamil	}
62721.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62731.1Skamil
62741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62761.1Skamil
62771.1Skamil	validate_status_stopped(status, sigval);
62781.1Skamil
62791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62801.1Skamil	    "without signal to be sent\n");
62811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62821.1Skamil
62831.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62841.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
62851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62861.1Skamil
62871.1Skamil	validate_status_stopped(status, SIGTRAP);
62881.1Skamil
62891.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
62901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
62911.1Skamil
62921.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
62931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
62941.1Skamil
62951.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
62961.1Skamil	    child, getpid());
62971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
62981.1Skamil
62991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63001.1Skamil	    "without signal to be sent\n");
63011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63021.1Skamil
63031.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63041.1Skamil	    "SIGINT\n", TWAIT_FNAME);
63051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63061.1Skamil
63071.1Skamil	validate_status_stopped(status, SIGINT);
63081.1Skamil
63091.1Skamil	pl.pl_lwpid = 0;
63101.1Skamil
63111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
63121.1Skamil	while (pl.pl_lwpid != 0) {
63131.1Skamil
63141.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
63151.1Skamil		switch (pl.pl_lwpid) {
63161.1Skamil		case 1:
63171.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
63181.1Skamil			break;
63191.1Skamil		case 2:
63201.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
63211.1Skamil			break;
63221.1Skamil		}
63231.1Skamil	}
63241.1Skamil
63251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63261.1Skamil	    "without signal to be sent\n");
63271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63281.1Skamil
63291.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63301.1Skamil	    TWAIT_FNAME);
63311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63321.1Skamil
63331.1Skamil	validate_status_exited(status, exitval);
63341.1Skamil
63351.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63361.1Skamil	    TWAIT_FNAME);
63371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63381.1Skamil}
63391.1Skamil
63401.1SkamilATF_TC(suspend2);
63411.1SkamilATF_TC_HEAD(suspend2, tc)
63421.1Skamil{
63431.1Skamil	atf_tc_set_md_var(tc, "descr",
63441.1Skamil	    "Verify that the while the only thread within a process is "
63451.1Skamil	    "suspended, the whole process cannot be unstopped");
63461.1Skamil}
63471.1Skamil
63481.1SkamilATF_TC_BODY(suspend2, tc)
63491.1Skamil{
63501.1Skamil	const int exitval = 5;
63511.1Skamil	const int sigval = SIGSTOP;
63521.1Skamil	pid_t child, wpid;
63531.1Skamil#if defined(TWAIT_HAVE_STATUS)
63541.1Skamil	int status;
63551.1Skamil#endif
63561.1Skamil	struct ptrace_siginfo psi;
63571.1Skamil
63581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63601.1Skamil	if (child == 0) {
63611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63631.1Skamil
63641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63661.1Skamil
63671.13Schristos		DPRINTF("Before exiting of the child process\n");
63681.1Skamil		_exit(exitval);
63691.1Skamil	}
63701.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63711.1Skamil
63721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63741.1Skamil
63751.1Skamil	validate_status_stopped(status, sigval);
63761.1Skamil
63771.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
63781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
63791.1Skamil
63801.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
63811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
63821.1Skamil
63831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63841.1Skamil	    "without signal to be sent\n");
63851.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
63861.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
63871.1Skamil
63881.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
63891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
63901.1Skamil
63911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63921.1Skamil	    "without signal to be sent\n");
63931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63941.1Skamil
63951.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63961.1Skamil	    TWAIT_FNAME);
63971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63981.1Skamil
63991.1Skamil	validate_status_exited(status, exitval);
64001.1Skamil
64011.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64021.1Skamil	    TWAIT_FNAME);
64031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64041.1Skamil}
64051.1Skamil
64061.1SkamilATF_TC(resume1);
64071.1SkamilATF_TC_HEAD(resume1, tc)
64081.1Skamil{
64091.1Skamil	atf_tc_set_md_var(tc, "descr",
64101.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
64111.1Skamil	    "resumed by the debugger");
64121.1Skamil}
64131.1Skamil
64141.1SkamilATF_TC_BODY(resume1, tc)
64151.1Skamil{
64161.1Skamil	struct msg_fds fds;
64171.1Skamil	const int exitval = 5;
64181.1Skamil	const int sigval = SIGSTOP;
64191.1Skamil	pid_t child, wpid;
64201.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
64211.1Skamil#if defined(TWAIT_HAVE_STATUS)
64221.1Skamil	int status;
64231.1Skamil#endif
64241.1Skamil	ucontext_t uc;
64251.1Skamil	lwpid_t lid;
64261.1Skamil	static const size_t ssize = 16*1024;
64271.1Skamil	void *stack;
64281.1Skamil	struct ptrace_lwpinfo pl;
64291.1Skamil	struct ptrace_siginfo psi;
64301.1Skamil
64311.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
64321.1Skamil
64331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64351.1Skamil	if (child == 0) {
64361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64381.1Skamil
64391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64411.1Skamil
64421.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
64431.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
64441.1Skamil
64451.13Schristos		DPRINTF("Before making context for new lwp in child\n");
64461.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
64471.1Skamil
64481.13Schristos		DPRINTF("Before creating new in child\n");
64491.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
64501.1Skamil
64511.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
64521.1Skamil
64531.1Skamil		raise(SIGINT);
64541.1Skamil
64551.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
64561.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
64571.1Skamil
64581.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
64591.1Skamil		    "are the same\n", lid, the_lwp_id);
64601.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
64611.1Skamil
64621.13Schristos		DPRINTF("Before exiting of the child process\n");
64631.1Skamil		_exit(exitval);
64641.1Skamil	}
64651.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64661.1Skamil
64671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64691.1Skamil
64701.1Skamil	validate_status_stopped(status, sigval);
64711.1Skamil
64721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64731.1Skamil	    "without signal to be sent\n");
64741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64751.1Skamil
64761.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64771.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
64781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64791.1Skamil
64801.1Skamil	validate_status_stopped(status, SIGTRAP);
64811.1Skamil
64821.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
64831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
64841.1Skamil
64851.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
64861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
64871.1Skamil
64881.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
64891.1Skamil
64901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64911.1Skamil	    "without signal to be sent\n");
64921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64931.1Skamil
64941.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64951.1Skamil	    "SIGINT\n", TWAIT_FNAME);
64961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64971.1Skamil
64981.1Skamil	validate_status_stopped(status, SIGINT);
64991.1Skamil
65001.1Skamil	pl.pl_lwpid = 0;
65011.1Skamil
65021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65031.1Skamil	while (pl.pl_lwpid != 0) {
65041.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65051.1Skamil		switch (pl.pl_lwpid) {
65061.1Skamil		case 1:
65071.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
65081.1Skamil			break;
65091.1Skamil		case 2:
65101.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
65111.1Skamil			break;
65121.1Skamil		}
65131.1Skamil	}
65141.1Skamil
65151.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
65161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
65171.1Skamil
65181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65191.1Skamil	    "without signal to be sent\n");
65201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65211.1Skamil
65221.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65231.1Skamil	    TWAIT_FNAME);
65241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65251.1Skamil
65261.1Skamil	validate_status_exited(status, exitval);
65271.1Skamil
65281.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
65291.1Skamil	    TWAIT_FNAME);
65301.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65311.1Skamil
65321.1Skamil	msg_close(&fds);
65331.1Skamil}
65341.1Skamil
65351.1SkamilATF_TC(syscall1);
65361.1SkamilATF_TC_HEAD(syscall1, tc)
65371.1Skamil{
65381.1Skamil	atf_tc_set_md_var(tc, "descr",
65391.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
65401.1Skamil}
65411.1Skamil
65421.1SkamilATF_TC_BODY(syscall1, tc)
65431.1Skamil{
65441.1Skamil	const int exitval = 5;
65451.1Skamil	const int sigval = SIGSTOP;
65461.1Skamil	pid_t child, wpid;
65471.1Skamil#if defined(TWAIT_HAVE_STATUS)
65481.1Skamil	int status;
65491.1Skamil#endif
65501.1Skamil	struct ptrace_siginfo info;
65511.1Skamil	memset(&info, 0, sizeof(info));
65521.1Skamil
65531.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
65541.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
65551.1Skamil	if (child == 0) {
65561.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65571.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65581.1Skamil
65591.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65601.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65611.1Skamil
65621.1Skamil		syscall(SYS_getpid);
65631.1Skamil
65641.13Schristos		DPRINTF("Before exiting of the child process\n");
65651.1Skamil		_exit(exitval);
65661.1Skamil	}
65671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65681.1Skamil
65691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65711.1Skamil
65721.1Skamil	validate_status_stopped(status, sigval);
65731.1Skamil
65741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65751.1Skamil	    "without signal to be sent\n");
65761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
65771.1Skamil
65781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65801.1Skamil
65811.1Skamil	validate_status_stopped(status, SIGTRAP);
65821.1Skamil
65831.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
65841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
65851.1Skamil
65861.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
65871.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
65881.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
65891.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
65901.1Skamil
65911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65921.1Skamil	    "without signal to be sent\n");
65931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
65941.1Skamil
65951.13Schristos	DPRINTF("Before calling %s() for the child\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 calling ptrace(2) with PT_GET_SIGINFO for child\n");
66011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
66021.1Skamil
66031.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
66041.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
66051.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
66061.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
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\n", TWAIT_FNAME);
66131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66141.1Skamil
66151.1Skamil	validate_status_exited(status, exitval);
66161.1Skamil
66171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66181.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66191.1Skamil}
66201.1Skamil
66211.1SkamilATF_TC(syscallemu1);
66221.1SkamilATF_TC_HEAD(syscallemu1, tc)
66231.1Skamil{
66241.1Skamil	atf_tc_set_md_var(tc, "descr",
66251.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
66261.1Skamil}
66271.1Skamil
66281.1SkamilATF_TC_BODY(syscallemu1, tc)
66291.1Skamil{
66301.1Skamil	const int exitval = 5;
66311.1Skamil	const int sigval = SIGSTOP;
66321.1Skamil	pid_t child, wpid;
66331.1Skamil#if defined(TWAIT_HAVE_STATUS)
66341.1Skamil	int status;
66351.1Skamil#endif
66361.1Skamil
66371.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
66381.6Skamil	/* syscallemu does not work on sparc (32-bit) */
66391.6Skamil	atf_tc_expect_fail("PR kern/52166");
66401.6Skamil#endif
66411.6Skamil
66421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66441.1Skamil	if (child == 0) {
66451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66471.1Skamil
66481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66501.1Skamil
66511.1Skamil		syscall(SYS_exit, 100);
66521.1Skamil
66531.13Schristos		DPRINTF("Before exiting of the child process\n");
66541.1Skamil		_exit(exitval);
66551.1Skamil	}
66561.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66571.1Skamil
66581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66601.1Skamil
66611.1Skamil	validate_status_stopped(status, sigval);
66621.1Skamil
66631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66641.1Skamil	    "without signal to be sent\n");
66651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
66661.1Skamil
66671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66691.1Skamil
66701.1Skamil	validate_status_stopped(status, SIGTRAP);
66711.1Skamil
66721.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
66731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
66741.1Skamil
66751.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66761.1Skamil	    "without signal to be sent\n");
66771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
66781.1Skamil
66791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66811.1Skamil
66821.1Skamil	validate_status_stopped(status, SIGTRAP);
66831.1Skamil
66841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66851.1Skamil	    "without signal to be sent\n");
66861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66871.1Skamil
66881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66901.1Skamil
66911.1Skamil	validate_status_exited(status, exitval);
66921.1Skamil
66931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66951.1Skamil}
66961.1Skamil
66971.103Skamil/// ----------------------------------------------------------------------------
66981.103Skamil
66991.106Skamilstatic void
67001.106Skamilclone_body(int flags, bool trackfork, bool trackvfork,
67011.106Skamil    bool trackvforkdone)
67021.106Skamil{
67031.106Skamil	const int exitval = 5;
67041.106Skamil	const int exitval2 = 15;
67051.106Skamil	const int sigval = SIGSTOP;
67061.106Skamil	pid_t child, child2 = 0, wpid;
67071.106Skamil#if defined(TWAIT_HAVE_STATUS)
67081.106Skamil	int status;
67091.106Skamil#endif
67101.106Skamil	ptrace_state_t state;
67111.106Skamil	const int slen = sizeof(state);
67121.106Skamil	ptrace_event_t event;
67131.106Skamil	const int elen = sizeof(event);
67141.106Skamil
67151.106Skamil	const size_t stack_size = 1024 * 1024;
67161.106Skamil	void *stack, *stack_base;
67171.106Skamil
67181.106Skamil	stack = malloc(stack_size);
67191.106Skamil	ATF_REQUIRE(stack != NULL);
67201.106Skamil
67211.106Skamil#ifdef __MACHINE_STACK_GROWS_UP
67221.106Skamil	stack_base = stack;
67231.106Skamil#else
67241.106Skamil	stack_base = (char *)stack + stack_size;
67251.106Skamil#endif
67261.106Skamil
67271.106Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
67281.106Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
67291.106Skamil	if (child == 0) {
67301.106Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67311.106Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67321.106Skamil
67331.106Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67341.106Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67351.106Skamil
67361.106Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
67371.106Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
67381.106Skamil
67391.106Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
67401.106Skamil		    child2);
67411.106Skamil
67421.106Skamil		// XXX WALLSIG?
67431.106Skamil		FORKEE_REQUIRE_SUCCESS
67441.106Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
67451.106Skamil
67461.106Skamil		forkee_status_exited(status, exitval2);
67471.106Skamil
67481.106Skamil		DPRINTF("Before exiting of the child process\n");
67491.106Skamil		_exit(exitval);
67501.106Skamil	}
67511.106Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67521.106Skamil
67531.106Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67541.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67551.106Skamil
67561.106Skamil	validate_status_stopped(status, sigval);
67571.106Skamil
67581.106Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
67591.106Skamil	    trackfork ? "|PTRACE_FORK" : "",
67601.106Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
67611.106Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
67621.106Skamil	event.pe_set_event = 0;
67631.106Skamil	if (trackfork)
67641.106Skamil		event.pe_set_event |= PTRACE_FORK;
67651.106Skamil	if (trackvfork)
67661.106Skamil		event.pe_set_event |= PTRACE_VFORK;
67671.106Skamil	if (trackvforkdone)
67681.106Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
67691.106Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
67701.106Skamil
67711.106Skamil	DPRINTF("Before resuming the child process where it left off and "
67721.106Skamil	    "without signal to be sent\n");
67731.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67741.106Skamil
67751.106Skamil#if defined(TWAIT_HAVE_PID)
67761.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
67771.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
67781.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
67791.106Skamil		    child);
67801.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
67811.106Skamil		    child);
67821.106Skamil
67831.106Skamil		validate_status_stopped(status, SIGTRAP);
67841.106Skamil
67851.106Skamil		SYSCALL_REQUIRE(
67861.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
67871.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
67881.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
67891.106Skamil			       PTRACE_FORK);
67901.106Skamil		}
67911.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
67921.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
67931.106Skamil			       PTRACE_VFORK);
67941.106Skamil		}
67951.106Skamil
67961.106Skamil		child2 = state.pe_other_pid;
67971.106Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
67981.106Skamil
67991.106Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
68001.106Skamil		    "%d\n", TWAIT_FNAME, child2, child);
68011.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
68021.106Skamil		    child2);
68031.106Skamil
68041.106Skamil		validate_status_stopped(status, SIGTRAP);
68051.106Skamil
68061.106Skamil		SYSCALL_REQUIRE(
68071.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
68081.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
68091.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
68101.106Skamil			       PTRACE_FORK);
68111.106Skamil		}
68121.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
68131.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
68141.106Skamil			       PTRACE_VFORK);
68151.106Skamil		}
68161.106Skamil
68171.106Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
68181.106Skamil
68191.106Skamil		DPRINTF("Before resuming the forkee process where it left off "
68201.106Skamil		    "and without signal to be sent\n");
68211.106Skamil		SYSCALL_REQUIRE(
68221.106Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
68231.106Skamil
68241.106Skamil		DPRINTF("Before resuming the child process where it left off "
68251.106Skamil		    "and without signal to be sent\n");
68261.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68271.106Skamil	}
68281.106Skamil#endif
68291.106Skamil
68301.106Skamil	if (trackvforkdone && (flags & CLONE_VFORK)) {
68311.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
68321.106Skamil		    child);
68331.106Skamil		TWAIT_REQUIRE_SUCCESS(
68341.106Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
68351.106Skamil
68361.106Skamil		validate_status_stopped(status, SIGTRAP);
68371.106Skamil
68381.106Skamil		SYSCALL_REQUIRE(
68391.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
68401.106Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
68411.106Skamil
68421.106Skamil		child2 = state.pe_other_pid;
68431.106Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
68441.106Skamil		    child2);
68451.106Skamil
68461.106Skamil		DPRINTF("Before resuming the child process where it left off "
68471.106Skamil		    "and without signal to be sent\n");
68481.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68491.106Skamil	}
68501.106Skamil
68511.103Skamil#if defined(TWAIT_HAVE_PID)
68521.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
68531.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
68541.106Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
68551.106Skamil		    "\n", TWAIT_FNAME);
68561.106Skamil		TWAIT_REQUIRE_SUCCESS(
68571.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
68581.106Skamil
68591.106Skamil		validate_status_exited(status, exitval2);
68601.106Skamil
68611.106Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
68621.106Skamil		    "process\n", TWAIT_FNAME);
68631.106Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
68641.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
68651.106Skamil	}
68661.106Skamil#endif
68671.106Skamil
68681.106Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
68691.106Skamil	    "SIGCHLD\n", TWAIT_FNAME);
68701.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68711.106Skamil
68721.106Skamil	validate_status_stopped(status, SIGCHLD);
68731.106Skamil
68741.106Skamil	DPRINTF("Before resuming the child process where it left off and "
68751.106Skamil	    "without signal to be sent\n");
68761.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68771.106Skamil
68781.106Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
68791.106Skamil	    TWAIT_FNAME);
68801.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68811.106Skamil
68821.106Skamil	validate_status_exited(status, exitval);
68831.103Skamil
68841.106Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
68851.106Skamil	    TWAIT_FNAME);
68861.106Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68871.106Skamil}
68881.103Skamil
68891.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone)			\
68901.106SkamilATF_TC(name);								\
68911.106SkamilATF_TC_HEAD(name, tc)							\
68921.106Skamil{									\
68931.106Skamil	atf_tc_set_md_var(tc, "descr", "Verify clone(%s) "		\
68941.106Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
68951.106Skamil	    #flags,							\
68961.106Skamil	    tfork ? "|PTRACE_FORK" : "",				\
68971.106Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
68981.106Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
68991.106Skamil}									\
69001.106Skamil									\
69011.106SkamilATF_TC_BODY(name, tc)							\
69021.106Skamil{									\
69031.106Skamil									\
69041.106Skamil	clone_body(flags, tfork, tvfork, tvforkdone);			\
69051.103Skamil}
69061.103Skamil
69071.106SkamilCLONE_TEST(clone1, 0, false, false, false)
69081.106Skamil#if defined(TWAIT_HAVE_PID)
69091.106SkamilCLONE_TEST(clone2, 0, true, false, false)
69101.106SkamilCLONE_TEST(clone3, 0, false, true, false)
69111.106SkamilCLONE_TEST(clone4, 0, true, true, false)
69121.106Skamil#endif
69131.106SkamilCLONE_TEST(clone5, 0, false, false, true)
69141.106Skamil#if defined(TWAIT_HAVE_PID)
69151.106SkamilCLONE_TEST(clone6, 0, true, false, true)
69161.106SkamilCLONE_TEST(clone7, 0, false, true, true)
69171.106SkamilCLONE_TEST(clone8, 0, true, true, true)
69181.106Skamil#endif
69191.106Skamil
69201.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false)
69211.106Skamil#if defined(TWAIT_HAVE_PID)
69221.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false)
69231.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false)
69241.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false)
69251.106Skamil#endif
69261.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true)
69271.106Skamil#if defined(TWAIT_HAVE_PID)
69281.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true)
69291.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true)
69301.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true)
69311.106Skamil#endif
69321.106Skamil
69331.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false)
69341.106Skamil#if defined(TWAIT_HAVE_PID)
69351.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false)
69361.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false)
69371.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false)
69381.106Skamil#endif
69391.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true)
69401.106Skamil#if defined(TWAIT_HAVE_PID)
69411.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true)
69421.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true)
69431.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true)
69441.106Skamil#endif
69451.106Skamil
69461.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false)
69471.106Skamil#if defined(TWAIT_HAVE_PID)
69481.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false)
69491.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false)
69501.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false)
69511.106Skamil#endif
69521.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true)
69531.106Skamil#if defined(TWAIT_HAVE_PID)
69541.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true)
69551.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true)
69561.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true)
69571.106Skamil#endif
69581.106Skamil
69591.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false)
69601.106Skamil#if defined(TWAIT_HAVE_PID)
69611.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false)
69621.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false)
69631.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false)
69641.106Skamil#endif
69651.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true)
69661.106Skamil#if defined(TWAIT_HAVE_PID)
69671.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true)
69681.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true)
69691.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true)
69701.106Skamil#endif
69711.106Skamil
69721.110Skamil#if TEST_VFORK_ENABLED
69731.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false)
69741.106Skamil#if defined(TWAIT_HAVE_PID)
69751.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false)
69761.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false)
69771.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false)
69781.106Skamil#endif
69791.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true)
69801.106Skamil#if defined(TWAIT_HAVE_PID)
69811.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true)
69821.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true)
69831.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true)
69841.106Skamil#endif
69851.110Skamil#endif
69861.106Skamil
69871.106Skamil/// ----------------------------------------------------------------------------
69881.106Skamil
69891.106Skamil#if defined(TWAIT_HAVE_PID)
69901.103Skamilstatic void
69911.106Skamilclone_body2(int flags, bool masked, bool ignored)
69921.103Skamil{
69931.103Skamil	const int exitval = 5;
69941.103Skamil	const int exitval2 = 15;
69951.103Skamil	const int sigval = SIGSTOP;
69961.103Skamil	pid_t child, child2 = 0, wpid;
69971.103Skamil#if defined(TWAIT_HAVE_STATUS)
69981.103Skamil	int status;
69991.103Skamil#endif
70001.103Skamil	ptrace_state_t state;
70011.103Skamil	const int slen = sizeof(state);
70021.103Skamil	ptrace_event_t event;
70031.103Skamil	const int elen = sizeof(event);
70041.103Skamil	struct sigaction sa;
70051.103Skamil	struct ptrace_siginfo info;
70061.103Skamil	sigset_t intmask;
70071.103Skamil	struct kinfo_proc2 kp;
70081.103Skamil	size_t len = sizeof(kp);
70091.103Skamil
70101.103Skamil	int name[6];
70111.103Skamil	const size_t namelen = __arraycount(name);
70121.103Skamil	ki_sigset_t kp_sigmask;
70131.103Skamil	ki_sigset_t kp_sigignore;
70141.103Skamil
70151.103Skamil	const size_t stack_size = 1024 * 1024;
70161.103Skamil	void *stack, *stack_base;
70171.103Skamil
70181.103Skamil	stack = malloc(stack_size);
70191.103Skamil	ATF_REQUIRE(stack != NULL);
70201.103Skamil
70211.103Skamil#ifdef __MACHINE_STACK_GROWS_UP
70221.103Skamil	stack_base = stack;
70231.103Skamil#else
70241.103Skamil	stack_base = (char *)stack + stack_size;
70251.103Skamil#endif
70261.103Skamil
70271.103Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
70281.103Skamil	if (child == 0) {
70291.103Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
70301.103Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
70311.103Skamil
70321.103Skamil		if (masked) {
70331.103Skamil			sigemptyset(&intmask);
70341.103Skamil			sigaddset(&intmask, SIGTRAP);
70351.103Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
70361.103Skamil		}
70371.103Skamil
70381.103Skamil		if (ignored) {
70391.103Skamil			memset(&sa, 0, sizeof(sa));
70401.103Skamil			sa.sa_handler = SIG_IGN;
70411.103Skamil			sigemptyset(&sa.sa_mask);
70421.103Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
70431.103Skamil		}
70441.103Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
70451.103Skamil		FORKEE_ASSERT(raise(sigval) == 0);
70461.103Skamil
70471.103Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
70481.103Skamil		    flags);
70491.103Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
70501.103Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
70511.103Skamil
70521.103Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
70531.103Skamil		    child2);
70541.103Skamil
70551.103Skamil		// XXX WALLSIG?
70561.103Skamil		FORKEE_REQUIRE_SUCCESS
70571.103Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
70581.103Skamil
70591.103Skamil		forkee_status_exited(status, exitval2);
70601.103Skamil
70611.103Skamil		DPRINTF("Before exiting of the child process\n");
70621.103Skamil		_exit(exitval);
70631.103Skamil	}
70641.103Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
70651.103Skamil
70661.103Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
70671.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
70681.103Skamil
70691.103Skamil	validate_status_stopped(status, sigval);
70701.103Skamil
70711.103Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
70721.103Skamil	SYSCALL_REQUIRE(
70731.103Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
70741.103Skamil
70751.103Skamil	DPRINTF("Before checking siginfo_t\n");
70761.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
70771.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
70781.103Skamil
70791.103Skamil	name[0] = CTL_KERN,
70801.103Skamil	name[1] = KERN_PROC2,
70811.103Skamil	name[2] = KERN_PROC_PID;
70821.103Skamil	name[3] = child;
70831.103Skamil	name[4] = sizeof(kp);
70841.103Skamil	name[5] = 1;
70851.103Skamil
70861.103Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
70871.103Skamil
70881.103Skamil	if (masked)
70891.103Skamil		kp_sigmask = kp.p_sigmask;
70901.103Skamil
70911.103Skamil	if (ignored)
70921.103Skamil		kp_sigignore = kp.p_sigignore;
70931.103Skamil
70941.103Skamil	DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in "
70951.103Skamil	    "EVENT_MASK for the child %d\n", child);
70961.103Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
70971.103Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
70981.103Skamil
70991.103Skamil	DPRINTF("Before resuming the child process where it left off and "
71001.103Skamil	    "without signal to be sent\n");
71011.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
71021.103Skamil
71031.103Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
71041.103Skamil	    child);
71051.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
71061.103Skamil	    child);
71071.103Skamil
71081.103Skamil	validate_status_stopped(status, SIGTRAP);
71091.103Skamil
71101.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
71111.103Skamil
71121.103Skamil	if (masked) {
71131.103Skamil		DPRINTF("kp_sigmask="
71141.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71151.103Skamil		    PRIx32 "\n",
71161.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
71171.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
71181.103Skamil
71191.103Skamil		DPRINTF("kp.p_sigmask="
71201.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71211.103Skamil		    PRIx32 "\n",
71221.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
71231.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
71241.103Skamil
71251.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
71261.103Skamil		    sizeof(kp_sigmask)));
71271.103Skamil	}
71281.103Skamil
71291.103Skamil	if (ignored) {
71301.103Skamil		DPRINTF("kp_sigignore="
71311.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71321.103Skamil		    PRIx32 "\n",
71331.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
71341.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
71351.103Skamil
71361.103Skamil		DPRINTF("kp.p_sigignore="
71371.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71381.103Skamil		    PRIx32 "\n",
71391.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
71401.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
71411.103Skamil
71421.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
71431.103Skamil		    sizeof(kp_sigignore)));
71441.103Skamil	}
71451.103Skamil
71461.103Skamil	SYSCALL_REQUIRE(
71471.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
71481.103Skamil	DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event,
71491.103Skamil	    child2);
71501.103Skamil	if (!(flags & CLONE_VFORK)) {
71511.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
71521.103Skamil		       PTRACE_FORK);
71531.103Skamil	} else {
71541.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
71551.103Skamil		       PTRACE_VFORK);
71561.103Skamil	}
71571.103Skamil
71581.103Skamil	child2 = state.pe_other_pid;
71591.103Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
71601.103Skamil
71611.103Skamil	DPRINTF("Before calling %s() for the forkee %d of the child "
71621.103Skamil	    "%d\n", TWAIT_FNAME, child2, child);
71631.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
71641.103Skamil	    child2);
71651.103Skamil
71661.103Skamil	validate_status_stopped(status, SIGTRAP);
71671.103Skamil
71681.103Skamil	name[3] = child2;
71691.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
71701.103Skamil
71711.103Skamil	if (masked) {
71721.103Skamil		DPRINTF("kp_sigmask="
71731.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71741.103Skamil		    PRIx32 "\n",
71751.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
71761.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
71771.103Skamil
71781.103Skamil		DPRINTF("kp.p_sigmask="
71791.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71801.103Skamil		    PRIx32 "\n",
71811.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
71821.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
71831.103Skamil
71841.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
71851.103Skamil		    sizeof(kp_sigmask)));
71861.103Skamil	}
71871.103Skamil
71881.103Skamil	if (ignored) {
71891.103Skamil		DPRINTF("kp_sigignore="
71901.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71911.103Skamil		    PRIx32 "\n",
71921.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
71931.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
71941.103Skamil
71951.103Skamil		DPRINTF("kp.p_sigignore="
71961.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
71971.103Skamil		    PRIx32 "\n",
71981.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
71991.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
72001.103Skamil
72011.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
72021.103Skamil		    sizeof(kp_sigignore)));
72031.103Skamil	}
72041.103Skamil
72051.103Skamil	SYSCALL_REQUIRE(
72061.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
72071.103Skamil	if (!(flags & CLONE_VFORK)) {
72081.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
72091.103Skamil		       PTRACE_FORK);
72101.103Skamil	} else {
72111.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
72121.103Skamil		       PTRACE_VFORK);
72131.103Skamil	}
72141.103Skamil
72151.103Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
72161.103Skamil
72171.103Skamil	DPRINTF("Before resuming the forkee process where it left off "
72181.103Skamil	    "and without signal to be sent\n");
72191.103Skamil	SYSCALL_REQUIRE(
72201.103Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
72211.103Skamil
72221.103Skamil	DPRINTF("Before resuming the child process where it left off "
72231.103Skamil	    "and without signal to be sent\n");
72241.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
72251.103Skamil
72261.103Skamil	if (flags & CLONE_VFORK) {
72271.103Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
72281.103Skamil		    child);
72291.103Skamil		TWAIT_REQUIRE_SUCCESS(
72301.103Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
72311.103Skamil
72321.103Skamil		validate_status_stopped(status, SIGTRAP);
72331.103Skamil
72341.103Skamil		name[3] = child;
72351.103Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
72361.103Skamil
72371.103Skamil		/*
72381.103Skamil		 * SIGCHLD is now pending in the signal queue and
72391.103Skamil		 * the kernel presents it to userland as a masked signal.
72401.103Skamil		 */
72411.103Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
72421.103Skamil
72431.103Skamil		if (masked) {
72441.103Skamil			DPRINTF("kp_sigmask="
72451.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72461.103Skamil			    PRIx32 "\n",
72471.103Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
72481.103Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
72491.103Skamil
72501.103Skamil			DPRINTF("kp.p_sigmask="
72511.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72521.103Skamil			    PRIx32 "\n",
72531.103Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
72541.103Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
72551.103Skamil
72561.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
72571.103Skamil			    sizeof(kp_sigmask)));
72581.103Skamil		}
72591.103Skamil
72601.103Skamil		if (ignored) {
72611.103Skamil			DPRINTF("kp_sigignore="
72621.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72631.103Skamil			    PRIx32 "\n",
72641.103Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
72651.103Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
72661.103Skamil
72671.103Skamil			DPRINTF("kp.p_sigignore="
72681.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
72691.103Skamil			    PRIx32 "\n",
72701.103Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
72711.103Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
72721.103Skamil
72731.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
72741.103Skamil			    sizeof(kp_sigignore)));
72751.103Skamil		}
72761.103Skamil
72771.103Skamil		SYSCALL_REQUIRE(
72781.103Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
72791.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
72801.103Skamil
72811.103Skamil		child2 = state.pe_other_pid;
72821.103Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
72831.103Skamil		    child2);
72841.103Skamil
72851.103Skamil		DPRINTF("Before resuming the child process where it left off "
72861.103Skamil		    "and without signal to be sent\n");
72871.103Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
72881.103Skamil	}
72891.103Skamil
72901.103Skamil	DPRINTF("Before calling %s() for the forkee - expected exited"
72911.103Skamil	    "\n", TWAIT_FNAME);
72921.103Skamil	TWAIT_REQUIRE_SUCCESS(
72931.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
72941.103Skamil
72951.103Skamil	validate_status_exited(status, exitval2);
72961.103Skamil
72971.103Skamil	DPRINTF("Before calling %s() for the forkee - expected no "
72981.103Skamil	    "process\n", TWAIT_FNAME);
72991.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
73001.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
73011.103Skamil
73021.103Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
73031.103Skamil	    "SIGCHLD\n", TWAIT_FNAME);
73041.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
73051.103Skamil
73061.103Skamil	validate_status_stopped(status, SIGCHLD);
73071.103Skamil
73081.103Skamil	DPRINTF("Before resuming the child process where it left off and "
73091.103Skamil	    "without signal to be sent\n");
73101.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
73111.103Skamil
73121.103Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
73131.103Skamil	    TWAIT_FNAME);
73141.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
73151.103Skamil
73161.103Skamil	validate_status_exited(status, exitval);
73171.103Skamil
73181.103Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
73191.103Skamil	    TWAIT_FNAME);
73201.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
73211.103Skamil}
73221.103Skamil
73231.106Skamil#define CLONE_TEST2(name,flags,masked,ignored)				\
73241.103SkamilATF_TC(name);								\
73251.103SkamilATF_TC_HEAD(name, tc)							\
73261.103Skamil{									\
73271.103Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\
73281.103Skamil	    " regardless of signal %s%s", 				\
73291.103Skamil	    #flags, masked ? "masked" : "", ignored ? "ignored" : "");	\
73301.103Skamil}									\
73311.103Skamil									\
73321.103SkamilATF_TC_BODY(name, tc)							\
73331.103Skamil{									\
73341.103Skamil									\
73351.106Skamil	clone_body2(flags, masked, ignored);				\
73361.103Skamil}
73371.103Skamil
73381.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false)
73391.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true)
73401.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false)
73411.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true)
73421.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false)
73431.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true)
73441.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false)
73451.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true)
73461.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX
73471.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true)  // XXX
73481.110Skamil#if TEST_VFORK_ENABLED
73491.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false)
73501.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true)
73511.103Skamil#endif
73521.110Skamil#endif
73531.103Skamil
73541.103Skamil/// ----------------------------------------------------------------------------
73551.103Skamil
73561.111Skamil#if TEST_VFORK_ENABLED
73571.107Skamil#if defined(TWAIT_HAVE_PID)
73581.107Skamilstatic void
73591.107Skamiltraceme_vfork_clone_body(int flags)
73601.107Skamil{
73611.107Skamil	const int exitval = 5;
73621.107Skamil	const int exitval2 = 15;
73631.107Skamil	pid_t child, child2 = 0, wpid;
73641.107Skamil#if defined(TWAIT_HAVE_STATUS)
73651.107Skamil	int status;
73661.107Skamil#endif
73671.107Skamil
73681.107Skamil	const size_t stack_size = 1024 * 1024;
73691.107Skamil	void *stack, *stack_base;
73701.107Skamil
73711.107Skamil	stack = malloc(stack_size);
73721.107Skamil	ATF_REQUIRE(stack != NULL);
73731.107Skamil
73741.107Skamil#ifdef __MACHINE_STACK_GROWS_UP
73751.107Skamil	stack_base = stack;
73761.107Skamil#else
73771.107Skamil	stack_base = (char *)stack + stack_size;
73781.107Skamil#endif
73791.107Skamil
73801.107Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
73811.107Skamil	if (child == 0) {
73821.107Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
73831.107Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
73841.107Skamil
73851.107Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
73861.107Skamil		    flags);
73871.107Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
73881.107Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
73891.107Skamil
73901.107Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
73911.107Skamil		    child2);
73921.107Skamil
73931.107Skamil		// XXX WALLSIG?
73941.107Skamil		FORKEE_REQUIRE_SUCCESS
73951.107Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
73961.107Skamil
73971.107Skamil		forkee_status_exited(status, exitval2);
73981.107Skamil
73991.107Skamil		DPRINTF("Before exiting of the child process\n");
74001.107Skamil		_exit(exitval);
74011.107Skamil	}
74021.107Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
74031.107Skamil
74041.107Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
74051.107Skamil	    TWAIT_FNAME);
74061.107Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
74071.107Skamil
74081.107Skamil	validate_status_exited(status, exitval);
74091.107Skamil
74101.107Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
74111.107Skamil	    TWAIT_FNAME);
74121.107Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
74131.107Skamil}
74141.107Skamil
74151.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags)				\
74161.107SkamilATF_TC(name);								\
74171.107SkamilATF_TC_HEAD(name, tc)							\
74181.107Skamil{									\
74191.107Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is "	\
74201.107Skamil	    "handled correctly with vfork(2)ed tracer", 		\
74211.107Skamil	    #flags);							\
74221.107Skamil}									\
74231.107Skamil									\
74241.107SkamilATF_TC_BODY(name, tc)							\
74251.107Skamil{									\
74261.107Skamil									\
74271.107Skamil	traceme_vfork_clone_body(flags);				\
74281.107Skamil}
74291.107Skamil
74301.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0)
74311.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM)
74321.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS)
74331.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES)
74341.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND)  // XXX
74351.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK)
74361.107Skamil#endif
74371.110Skamil#endif
74381.107Skamil
74391.107Skamil/// ----------------------------------------------------------------------------
74401.107Skamil
74411.1Skamil#include "t_ptrace_amd64_wait.h"
74421.1Skamil#include "t_ptrace_i386_wait.h"
74431.1Skamil#include "t_ptrace_x86_wait.h"
74441.1Skamil
74451.1SkamilATF_TP_ADD_TCS(tp)
74461.1Skamil{
74471.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
74481.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
74491.33Skamil
74501.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
74511.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
74521.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
74531.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
74541.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
74551.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
74561.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
74571.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
74581.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
74591.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
74601.33Skamil
74611.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
74621.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
74631.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
74641.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
74651.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
74661.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
74671.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
74681.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
74691.87Skamil
74701.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
74711.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
74721.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
74731.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
74741.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
74751.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
74761.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
74771.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
74781.86Skamil
74791.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
74801.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
74811.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
74821.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
74831.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
74841.59Skamil
74851.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
74861.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
74871.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
74881.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
74891.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
74901.88Skamil
74911.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
74921.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
74931.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
74941.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
74951.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
74961.88Skamil
74971.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
74981.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
74991.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
75001.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
75011.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
75021.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
75031.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
75041.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
75051.50Skamil
75061.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
75071.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
75081.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
75091.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
75101.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
75111.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
75121.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
75131.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
75141.50Skamil
75151.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
75161.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
75171.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
75181.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
75191.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
75201.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
75211.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
75221.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
75231.50Skamil
75241.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
75251.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
75261.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
75271.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
75281.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
75291.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
75301.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
75311.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
75321.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
75331.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
75341.1Skamil
75351.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
75361.37Skamil
75371.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
75381.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
75391.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
75401.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
75411.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
75421.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
75431.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
75441.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
75451.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
75461.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
75471.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
75481.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
75491.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
75501.40Skamil
75511.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
75521.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
75531.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
75541.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
75551.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
75561.41Skamil
75571.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
75581.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
75591.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
75601.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
75611.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
75621.92Skamil
75631.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
75641.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
75651.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
75661.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
75671.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
75681.92Skamil
75691.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
75701.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
75711.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
75721.43Skamil
75731.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
75741.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
75751.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
75761.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
75771.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
75781.59Skamil
75791.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75801.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
75811.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75821.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
75831.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75841.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
75851.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75861.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
75871.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75881.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
75891.94Skamil
75901.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75911.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
75921.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75931.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
75941.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75951.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
75961.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75971.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
75981.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
75991.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
76001.94Skamil
76011.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
76021.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
76031.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
76041.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
76051.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
76061.51Skamil
76071.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
76081.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
76091.51Skamil
76101.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
76111.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
76121.51Skamil
76131.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
76141.51Skamil		tracee_sees_its_original_parent_getppid);
76151.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
76161.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
76171.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
76181.51Skamil		tracee_sees_its_original_parent_procfs_status);
76191.1Skamil
76201.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
76211.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
76221.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
76231.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
76241.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
76251.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
76261.1Skamil
76271.31Skamil	ATF_TP_ADD_TC(tp, fork1);
76281.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
76291.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
76301.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
76311.31Skamil	ATF_TP_ADD_TC(tp, fork5);
76321.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
76331.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
76341.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
76351.31Skamil
76361.109Skamil#if TEST_VFORK_ENABLED
76371.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
76381.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
76391.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
76401.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
76411.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
76421.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
76431.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
76441.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
76451.116Skamil#endif
76461.1Skamil
76471.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker);
76481.116Skamil#if TEST_VFORK_ENABLED
76491.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker);
76501.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone);
76511.116Skamil#endif
76521.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker);
76531.116Skamil#if TEST_VFORK_ENABLED
76541.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker);
76551.116Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone);
76561.116Skamil#endif
76571.116Skamil
76581.116Skamil#if TEST_VFORK_ENABLED
76591.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_fork);
76601.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_vfork);
76611.109Skamil#endif
76621.108Skamil
76631.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
76641.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
76651.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
76661.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
76671.54Skamil
76681.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
76691.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
76701.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
76711.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
76721.54Skamil
76731.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
76741.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
76751.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
76761.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
76771.54Skamil
76781.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
76791.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
76801.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
76811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
76821.54Skamil
76831.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
76841.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
76851.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
76861.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
76871.54Skamil
76881.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
76891.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
76901.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
76911.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
76921.54Skamil
76931.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
76941.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
76951.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
76961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
76971.54Skamil
76981.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
76991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
77001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
77011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
77021.54Skamil
77031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
77041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
77051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
77061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
77071.54Skamil
77081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
77091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
77101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
77111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
77121.1Skamil
77131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
77141.1Skamil
77151.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i);
77161.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d);
77171.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i);
77181.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d);
77191.101Skamil
77201.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i);
77211.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d);
77221.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i);
77231.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d);
77241.101Skamil
77251.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv);
77261.101Skamil
77271.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i);
77281.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d);
77291.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i);
77301.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d);
77311.115Skamil
77321.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i);
77331.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d);
77341.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i);
77351.115Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d);
77361.115Skamil
77371.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
77381.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
77391.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
77401.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
77411.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
77421.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
77431.1Skamil
77441.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
77451.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
77461.1Skamil
77471.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
77481.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
77491.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
77501.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
77511.1Skamil
77521.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
77531.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
77541.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
77551.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
77561.2Skamil
77571.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
77581.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
77591.95Skamil
77601.1Skamil	ATF_TP_ADD_TC(tp, kill1);
77611.1Skamil	ATF_TP_ADD_TC(tp, kill2);
77621.75Skamil	ATF_TP_ADD_TC(tp, kill3);
77631.1Skamil
77641.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
77651.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
77661.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
77671.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
77681.77Skamil
77691.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
77701.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
77711.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
77721.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
77731.1Skamil
77741.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
77751.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
77761.79Skamil
77771.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
77781.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
77791.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
77801.1Skamil
77811.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_nolwpevents);
77821.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpexit);
77831.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate);
77841.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit);
77851.1Skamil
77861.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
77871.84Skamil
77881.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
77891.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
77901.109Skamil#if TEST_VFORK_ENABLED
77911.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
77921.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
77931.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
77941.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
77951.109Skamil#endif
77961.99Skamil
77971.1Skamil	ATF_TP_ADD_TC(tp, signal9);
77981.1Skamil	ATF_TP_ADD_TC(tp, signal10);
77991.1Skamil
78001.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
78011.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
78021.1Skamil
78031.1Skamil	ATF_TP_ADD_TC(tp, resume1);
78041.1Skamil
78051.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
78061.1Skamil
78071.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
78081.1Skamil
78091.106Skamil	ATF_TP_ADD_TC(tp, clone1);
78101.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone2);
78111.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone3);
78121.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone4);
78131.106Skamil	ATF_TP_ADD_TC(tp, clone5);
78141.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone6);
78151.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone7);
78161.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone8);
78171.106Skamil
78181.106Skamil	ATF_TP_ADD_TC(tp, clone_vm1);
78191.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2);
78201.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3);
78211.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4);
78221.106Skamil	ATF_TP_ADD_TC(tp, clone_vm5);
78231.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6);
78241.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7);
78251.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8);
78261.106Skamil
78271.106Skamil	ATF_TP_ADD_TC(tp, clone_fs1);
78281.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2);
78291.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3);
78301.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4);
78311.106Skamil	ATF_TP_ADD_TC(tp, clone_fs5);
78321.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6);
78331.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7);
78341.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8);
78351.106Skamil
78361.106Skamil	ATF_TP_ADD_TC(tp, clone_files1);
78371.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2);
78381.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3);
78391.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4);
78401.106Skamil	ATF_TP_ADD_TC(tp, clone_files5);
78411.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6);
78421.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7);
78431.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8);
78441.106Skamil
78451.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand1); // XXX
78461.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX
78471.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX
78481.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX
78491.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand5); // XXX
78501.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX
78511.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX
78521.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX
78531.106Skamil
78541.109Skamil#if TEST_VFORK_ENABLED
78551.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork1);
78561.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2);
78571.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3);
78581.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4);
78591.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork5);
78601.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6);
78611.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7);
78621.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8);
78631.109Skamil#endif
78641.106Skamil
78651.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored);
78661.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked);
78671.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored);
78681.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked);
78691.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored);
78701.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked);
78711.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored);
78721.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked);
78731.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX
78741.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX
78751.109Skamil#if TEST_VFORK_ENABLED
78761.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored);
78771.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked);
78781.109Skamil#endif
78791.103Skamil
78801.109Skamil#if TEST_VFORK_ENABLED
78811.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone);
78821.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm);
78831.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs);
78841.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files);
78851.107Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX
78861.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork);
78871.109Skamil#endif
78881.107Skamil
78891.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
78901.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
78911.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
78921.1Skamil
78931.1Skamil	return atf_no_error();
78941.1Skamil}
7895