t_ptrace_wait.c revision 1.99
11.99Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.99 2019/03/02 01:01:20 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc.
51.1Skamil * All rights reserved.
61.1Skamil *
71.1Skamil * Redistribution and use in source and binary forms, with or without
81.1Skamil * modification, are permitted provided that the following conditions
91.1Skamil * are met:
101.1Skamil * 1. Redistributions of source code must retain the above copyright
111.1Skamil *    notice, this list of conditions and the following disclaimer.
121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright
131.1Skamil *    notice, this list of conditions and the following disclaimer in the
141.1Skamil *    documentation and/or other materials provided with the distribution.
151.1Skamil *
161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Skamil * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Skamil * POSSIBILITY OF SUCH DAMAGE.
271.1Skamil */
281.1Skamil
291.1Skamil#include <sys/cdefs.h>
301.99Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.99 2019/03/02 01:01:20 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.77Skamil#include <pthread.h>
471.1Skamil#include <sched.h>
481.1Skamil#include <signal.h>
491.1Skamil#include <stdint.h>
501.1Skamil#include <stdio.h>
511.1Skamil#include <stdlib.h>
521.1Skamil#include <strings.h>
531.26Skamil#include <time.h>
541.1Skamil#include <unistd.h>
551.1Skamil
561.1Skamil#include <atf-c.h>
571.1Skamil
581.1Skamil#include "h_macros.h"
591.1Skamil
601.1Skamil#include "t_ptrace_wait.h"
611.1Skamil#include "msg.h"
621.1Skamil
631.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
641.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
651.61Skre	sizeof(msg)) == 0)
661.1Skamil
671.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
681.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
691.61Skre	sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
721.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
731.61Skre	sizeof(msg)) == 0)
741.1Skamil
751.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
761.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
771.61Skre	sizeof(msg)) == 0)
781.13Schristos
791.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
801.13Schristos    strerror(errno))
811.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
821.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
831.13Schristos
841.13Schristosstatic int debug = 0;
851.13Schristos
861.13Schristos#define DPRINTF(a, ...)	do  \
871.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
881.13Schristos    while (/*CONSTCOND*/0)
891.1Skamil
901.34Skamil/// ----------------------------------------------------------------------------
911.34Skamil
921.33Skamilstatic void
931.33Skamiltraceme_raise(int sigval)
941.1Skamil{
951.1Skamil	const int exitval = 5;
961.1Skamil	pid_t child, wpid;
971.1Skamil#if defined(TWAIT_HAVE_STATUS)
981.1Skamil	int status;
991.1Skamil#endif
1001.1Skamil
1011.45Skamil	struct ptrace_siginfo info;
1021.45Skamil	memset(&info, 0, sizeof(info));
1031.45Skamil
1041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1061.1Skamil	if (child == 0) {
1071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1091.1Skamil
1101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1121.1Skamil
1131.36Skamil		switch (sigval) {
1141.36Skamil		case SIGKILL:
1151.36Skamil			/* NOTREACHED */
1161.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1171.70Smrg			__unreachable();
1181.36Skamil		default:
1191.36Skamil			DPRINTF("Before exiting of the child process\n");
1201.36Skamil			_exit(exitval);
1211.36Skamil		}
1221.1Skamil	}
1231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1241.1Skamil
1251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1271.1Skamil
1281.36Skamil	switch (sigval) {
1291.36Skamil	case SIGKILL:
1301.36Skamil		validate_status_signaled(status, sigval, 0);
1311.36Skamil		break;
1321.36Skamil	default:
1331.36Skamil		validate_status_stopped(status, sigval);
1341.1Skamil
1351.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1361.61Skre			"child\n");
1371.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1381.61Skre			sizeof(info)) != -1);
1391.45Skamil
1401.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1411.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1421.61Skre			"si_errno=%#x\n",
1431.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1441.61Skre			info.psi_siginfo.si_errno);
1451.45Skamil
1461.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1471.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1481.45Skamil
1491.36Skamil		DPRINTF("Before resuming the child process where it left off "
1501.36Skamil		    "and without signal to be sent\n");
1511.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1521.1Skamil
1531.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1541.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1551.61Skre		    child);
1561.36Skamil		break;
1571.36Skamil	}
1581.1Skamil
1591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1611.1Skamil}
1621.1Skamil
1631.61Skre#define TRACEME_RAISE(test, sig)					\
1641.61SkreATF_TC(test);								\
1651.61SkreATF_TC_HEAD(test, tc)							\
1661.61Skre{									\
1671.61Skre	atf_tc_set_md_var(tc, "descr",					\
1681.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1691.61Skre}									\
1701.61Skre									\
1711.61SkreATF_TC_BODY(test, tc)							\
1721.61Skre{									\
1731.61Skre									\
1741.61Skre	traceme_raise(sig);						\
1751.33Skamil}
1761.33Skamil
1771.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1781.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1791.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1801.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1811.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1821.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1831.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1841.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1851.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
1861.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
1871.33Skamil
1881.34Skamil/// ----------------------------------------------------------------------------
1891.1Skamil
1901.1Skamilstatic void
1911.87Skamiltraceme_raisesignal_ignored(int sigignored)
1921.87Skamil{
1931.87Skamil	const int exitval = 5;
1941.87Skamil	const int sigval = SIGSTOP;
1951.87Skamil	pid_t child, wpid;
1961.87Skamil	struct sigaction sa;
1971.87Skamil#if defined(TWAIT_HAVE_STATUS)
1981.87Skamil	int status;
1991.87Skamil#endif
2001.87Skamil	struct ptrace_siginfo info;
2011.87Skamil
2021.87Skamil	memset(&info, 0, sizeof(info));
2031.87Skamil
2041.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2051.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2061.87Skamil	if (child == 0) {
2071.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2081.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2091.87Skamil
2101.87Skamil		memset(&sa, 0, sizeof(sa));
2111.87Skamil		sa.sa_handler = SIG_IGN;
2121.87Skamil		sigemptyset(&sa.sa_mask);
2131.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2141.87Skamil
2151.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2161.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2171.87Skamil
2181.87Skamil		DPRINTF("Before raising %s from child\n",
2191.87Skamil		    strsignal(sigignored));
2201.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2211.87Skamil
2221.87Skamil		DPRINTF("Before exiting of the child process\n");
2231.87Skamil		_exit(exitval);
2241.87Skamil	}
2251.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2261.87Skamil
2271.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2281.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2291.87Skamil
2301.87Skamil	validate_status_stopped(status, sigval);
2311.87Skamil
2321.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2331.87Skamil	SYSCALL_REQUIRE(
2341.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2351.87Skamil
2361.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2371.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2381.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2391.87Skamil	    info.psi_siginfo.si_errno);
2401.87Skamil
2411.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2421.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2431.87Skamil
2441.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2451.87Skamil	    "without signal to be sent\n");
2461.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2471.87Skamil
2481.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2491.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2501.87Skamil
2511.87Skamil	validate_status_stopped(status, sigignored);
2521.87Skamil
2531.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2541.87Skamil	SYSCALL_REQUIRE(
2551.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2561.87Skamil
2571.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2581.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2591.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2601.87Skamil	    info.psi_siginfo.si_errno);
2611.87Skamil
2621.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2631.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2641.87Skamil
2651.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2661.87Skamil	    "without signal to be sent\n");
2671.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2681.87Skamil
2691.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2701.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2711.87Skamil
2721.87Skamil	validate_status_exited(status, exitval);
2731.87Skamil
2741.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2751.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2761.87Skamil}
2771.87Skamil
2781.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2791.87SkamilATF_TC(test);								\
2801.87SkamilATF_TC_HEAD(test, tc)							\
2811.87Skamil{									\
2821.87Skamil	atf_tc_set_md_var(tc, "descr",					\
2831.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
2841.87Skamil	    "does not stop tracer from catching this raised signal");	\
2851.87Skamil}									\
2861.87Skamil									\
2871.87SkamilATF_TC_BODY(test, tc)							\
2881.87Skamil{									\
2891.87Skamil									\
2901.87Skamil	traceme_raisesignal_ignored(sig);				\
2911.87Skamil}
2921.87Skamil
2931.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
2941.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
2951.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
2961.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
2971.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
2981.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
2991.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3001.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3011.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3021.87Skamil
3031.87Skamil/// ----------------------------------------------------------------------------
3041.87Skamil
3051.87Skamilstatic void
3061.86Skamiltraceme_raisesignal_masked(int sigmasked)
3071.86Skamil{
3081.86Skamil	const int exitval = 5;
3091.86Skamil	const int sigval = SIGSTOP;
3101.86Skamil	pid_t child, wpid;
3111.86Skamil#if defined(TWAIT_HAVE_STATUS)
3121.86Skamil	int status;
3131.86Skamil#endif
3141.86Skamil	sigset_t intmask;
3151.86Skamil	struct ptrace_siginfo info;
3161.86Skamil
3171.86Skamil	memset(&info, 0, sizeof(info));
3181.86Skamil
3191.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3201.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3211.86Skamil	if (child == 0) {
3221.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3231.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3241.86Skamil
3251.86Skamil		sigemptyset(&intmask);
3261.86Skamil		sigaddset(&intmask, sigmasked);
3271.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3281.86Skamil
3291.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3301.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3311.86Skamil
3321.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3331.86Skamil		    strsignal(sigmasked));
3341.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3351.86Skamil
3361.86Skamil		DPRINTF("Before exiting of the child process\n");
3371.86Skamil		_exit(exitval);
3381.86Skamil	}
3391.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3401.86Skamil
3411.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3421.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3431.86Skamil
3441.86Skamil	validate_status_stopped(status, sigval);
3451.86Skamil
3461.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3471.86Skamil	SYSCALL_REQUIRE(
3481.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3491.86Skamil
3501.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3511.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3521.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3531.86Skamil	    info.psi_siginfo.si_errno);
3541.86Skamil
3551.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3561.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3571.86Skamil
3581.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3591.86Skamil	    "without signal to be sent\n");
3601.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3611.86Skamil
3621.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3631.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3641.86Skamil
3651.86Skamil	validate_status_exited(status, exitval);
3661.86Skamil
3671.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3681.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3691.86Skamil}
3701.86Skamil
3711.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3721.86SkamilATF_TC(test);								\
3731.86SkamilATF_TC_HEAD(test, tc)							\
3741.86Skamil{									\
3751.86Skamil	atf_tc_set_md_var(tc, "descr",					\
3761.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3771.86Skamil	    "stops tracer from catching this raised signal");		\
3781.86Skamil}									\
3791.86Skamil									\
3801.86SkamilATF_TC_BODY(test, tc)							\
3811.86Skamil{									\
3821.86Skamil									\
3831.86Skamil	traceme_raisesignal_masked(sig);				\
3841.86Skamil}
3851.86Skamil
3861.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
3871.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
3881.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
3891.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
3901.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
3911.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
3921.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
3931.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
3941.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
3951.86Skamil
3961.86Skamil/// ----------------------------------------------------------------------------
3971.86Skamil
3981.86Skamilstatic void
3991.59Skamiltraceme_crash(int sig)
4001.59Skamil{
4011.59Skamil	pid_t child, wpid;
4021.59Skamil#if defined(TWAIT_HAVE_STATUS)
4031.59Skamil	int status;
4041.59Skamil#endif
4051.59Skamil	struct ptrace_siginfo info;
4061.61Skre
4071.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4081.71Skamil	if (sig == SIGILL)
4091.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4101.71Skamil#endif
4111.71Skamil
4121.59Skamil	memset(&info, 0, sizeof(info));
4131.59Skamil
4141.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4151.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4161.59Skamil	if (child == 0) {
4171.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4181.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4191.59Skamil
4201.59Skamil		DPRINTF("Before executing a trap\n");
4211.59Skamil		switch (sig) {
4221.59Skamil		case SIGTRAP:
4231.59Skamil			trigger_trap();
4241.59Skamil			break;
4251.59Skamil		case SIGSEGV:
4261.59Skamil			trigger_segv();
4271.59Skamil			break;
4281.59Skamil		case SIGILL:
4291.59Skamil			trigger_ill();
4301.59Skamil			break;
4311.59Skamil		case SIGFPE:
4321.59Skamil			trigger_fpe();
4331.59Skamil			break;
4341.59Skamil		case SIGBUS:
4351.59Skamil			trigger_bus();
4361.59Skamil			break;
4371.59Skamil		default:
4381.59Skamil			/* NOTREACHED */
4391.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4401.59Skamil		}
4411.59Skamil
4421.59Skamil		/* NOTREACHED */
4431.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4441.59Skamil	}
4451.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4461.59Skamil
4471.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4481.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4491.59Skamil
4501.59Skamil	validate_status_stopped(status, sig);
4511.59Skamil
4521.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4531.61Skre	SYSCALL_REQUIRE(
4541.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4551.59Skamil
4561.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4571.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4581.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4591.61Skre	    info.psi_siginfo.si_errno);
4601.59Skamil
4611.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4621.59Skamil	switch (sig) {
4631.59Skamil	case SIGTRAP:
4641.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4651.59Skamil		break;
4661.59Skamil	case SIGSEGV:
4671.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4681.59Skamil		break;
4691.71Skamil	case SIGILL:
4701.71Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
4711.71Skamil		break;
4721.59Skamil	case SIGFPE:
4731.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4741.59Skamil		break;
4751.59Skamil	case SIGBUS:
4761.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
4771.59Skamil		break;
4781.59Skamil	}
4791.59Skamil
4801.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
4811.59Skamil
4821.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4831.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4841.59Skamil
4851.59Skamil	validate_status_signaled(status, SIGKILL, 0);
4861.59Skamil
4871.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4881.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4891.59Skamil}
4901.59Skamil
4911.61Skre#define TRACEME_CRASH(test, sig)					\
4921.61SkreATF_TC(test);								\
4931.61SkreATF_TC_HEAD(test, tc)							\
4941.61Skre{									\
4951.61Skre	atf_tc_set_md_var(tc, "descr",					\
4961.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
4971.61Skre}									\
4981.61Skre									\
4991.61SkreATF_TC_BODY(test, tc)							\
5001.61Skre{									\
5011.61Skre									\
5021.61Skre	traceme_crash(sig);						\
5031.59Skamil}
5041.59Skamil
5051.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5061.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5071.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5081.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5091.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5101.59Skamil
5111.59Skamil/// ----------------------------------------------------------------------------
5121.59Skamil
5131.59Skamilstatic void
5141.88Skamiltraceme_signalmasked_crash(int sig)
5151.88Skamil{
5161.89Skamil	const int sigval = SIGSTOP;
5171.88Skamil	pid_t child, wpid;
5181.88Skamil#if defined(TWAIT_HAVE_STATUS)
5191.88Skamil	int status;
5201.88Skamil#endif
5211.88Skamil	struct ptrace_siginfo info;
5221.88Skamil	sigset_t intmask;
5231.89Skamil	struct kinfo_proc2 kp;
5241.89Skamil	size_t len = sizeof(kp);
5251.89Skamil
5261.89Skamil	int name[6];
5271.89Skamil	const size_t namelen = __arraycount(name);
5281.89Skamil	ki_sigset_t kp_sigmask;
5291.88Skamil
5301.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5311.88Skamil	if (sig == SIGILL)
5321.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5331.88Skamil#endif
5341.88Skamil
5351.88Skamil	memset(&info, 0, sizeof(info));
5361.88Skamil
5371.89Skamil	atf_tc_expect_fail("Unexpected sigmask reset on crash under debugger");
5381.89Skamil
5391.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5401.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5411.88Skamil	if (child == 0) {
5421.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5431.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5441.88Skamil
5451.88Skamil		sigemptyset(&intmask);
5461.88Skamil		sigaddset(&intmask, sig);
5471.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5481.88Skamil
5491.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5501.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5511.89Skamil
5521.88Skamil		DPRINTF("Before executing a trap\n");
5531.88Skamil		switch (sig) {
5541.88Skamil		case SIGTRAP:
5551.88Skamil			trigger_trap();
5561.88Skamil			break;
5571.88Skamil		case SIGSEGV:
5581.88Skamil			trigger_segv();
5591.88Skamil			break;
5601.88Skamil		case SIGILL:
5611.88Skamil			trigger_ill();
5621.88Skamil			break;
5631.88Skamil		case SIGFPE:
5641.88Skamil			trigger_fpe();
5651.88Skamil			break;
5661.88Skamil		case SIGBUS:
5671.88Skamil			trigger_bus();
5681.88Skamil			break;
5691.88Skamil		default:
5701.88Skamil			/* NOTREACHED */
5711.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5721.88Skamil		}
5731.88Skamil
5741.88Skamil		/* NOTREACHED */
5751.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5761.88Skamil	}
5771.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5781.88Skamil
5791.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5801.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5811.88Skamil
5821.89Skamil	validate_status_stopped(status, sigval);
5831.89Skamil
5841.89Skamil	name[0] = CTL_KERN,
5851.89Skamil	name[1] = KERN_PROC2,
5861.89Skamil	name[2] = KERN_PROC_PID;
5871.89Skamil	name[3] = child;
5881.89Skamil	name[4] = sizeof(kp);
5891.89Skamil	name[5] = 1;
5901.89Skamil
5911.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
5921.89Skamil
5931.89Skamil	kp_sigmask = kp.p_sigmask;
5941.89Skamil
5951.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5961.89Skamil	SYSCALL_REQUIRE(
5971.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5981.89Skamil
5991.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6001.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6011.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6021.89Skamil	    info.psi_siginfo.si_errno);
6031.89Skamil
6041.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6051.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6061.89Skamil
6071.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6081.89Skamil	    "without signal to be sent\n");
6091.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6101.89Skamil
6111.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6121.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6131.89Skamil
6141.88Skamil	validate_status_stopped(status, sig);
6151.88Skamil
6161.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6171.88Skamil	SYSCALL_REQUIRE(
6181.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6191.88Skamil
6201.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6211.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6221.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6231.88Skamil	    info.psi_siginfo.si_errno);
6241.88Skamil
6251.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6261.89Skamil
6271.89Skamil	DPRINTF("kp_sigmask="
6281.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6291.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6301.89Skamil	    kp_sigmask.__bits[3]);
6311.89Skamil
6321.89Skamil	DPRINTF("kp.p_sigmask="
6331.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6341.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6351.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6361.89Skamil
6371.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6381.89Skamil
6391.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6401.88Skamil	switch (sig) {
6411.88Skamil	case SIGTRAP:
6421.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6431.88Skamil		break;
6441.88Skamil	case SIGSEGV:
6451.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6461.88Skamil		break;
6471.88Skamil	case SIGILL:
6481.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
6491.88Skamil		break;
6501.88Skamil	case SIGFPE:
6511.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6521.88Skamil		break;
6531.88Skamil	case SIGBUS:
6541.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6551.88Skamil		break;
6561.88Skamil	}
6571.88Skamil
6581.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6591.88Skamil
6601.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6611.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6621.88Skamil
6631.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6641.88Skamil
6651.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6661.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6671.88Skamil}
6681.88Skamil
6691.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6701.88SkamilATF_TC(test);								\
6711.88SkamilATF_TC_HEAD(test, tc)							\
6721.88Skamil{									\
6731.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6741.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6751.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6761.88Skamil}									\
6771.88Skamil									\
6781.88SkamilATF_TC_BODY(test, tc)							\
6791.88Skamil{									\
6801.88Skamil									\
6811.88Skamil	traceme_signalmasked_crash(sig);				\
6821.88Skamil}
6831.88Skamil
6841.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
6851.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
6861.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
6871.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
6881.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
6891.88Skamil
6901.88Skamil/// ----------------------------------------------------------------------------
6911.88Skamil
6921.88Skamilstatic void
6931.88Skamiltraceme_signalignored_crash(int sig)
6941.88Skamil{
6951.90Skamil	const int sigval = SIGSTOP;
6961.88Skamil	pid_t child, wpid;
6971.88Skamil#if defined(TWAIT_HAVE_STATUS)
6981.88Skamil	int status;
6991.88Skamil#endif
7001.88Skamil	struct sigaction sa;
7011.88Skamil	struct ptrace_siginfo info;
7021.90Skamil	struct kinfo_proc2 kp;
7031.90Skamil	size_t len = sizeof(kp);
7041.90Skamil
7051.90Skamil	int name[6];
7061.90Skamil	const size_t namelen = __arraycount(name);
7071.90Skamil	ki_sigset_t kp_sigignore;
7081.88Skamil
7091.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7101.88Skamil	if (sig == SIGILL)
7111.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7121.88Skamil#endif
7131.88Skamil
7141.90Skamil	atf_tc_expect_fail("Unexpected sigmask reset on crash under debugger");
7151.90Skamil
7161.88Skamil	memset(&info, 0, sizeof(info));
7171.88Skamil
7181.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7191.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7201.88Skamil	if (child == 0) {
7211.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7221.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7231.88Skamil
7241.88Skamil		memset(&sa, 0, sizeof(sa));
7251.88Skamil		sa.sa_handler = SIG_IGN;
7261.88Skamil		sigemptyset(&sa.sa_mask);
7271.88Skamil
7281.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7291.88Skamil
7301.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7311.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7321.90Skamil
7331.88Skamil		DPRINTF("Before executing a trap\n");
7341.88Skamil		switch (sig) {
7351.88Skamil		case SIGTRAP:
7361.88Skamil			trigger_trap();
7371.88Skamil			break;
7381.88Skamil		case SIGSEGV:
7391.88Skamil			trigger_segv();
7401.88Skamil			break;
7411.88Skamil		case SIGILL:
7421.88Skamil			trigger_ill();
7431.88Skamil			break;
7441.88Skamil		case SIGFPE:
7451.88Skamil			trigger_fpe();
7461.88Skamil			break;
7471.88Skamil		case SIGBUS:
7481.88Skamil			trigger_bus();
7491.88Skamil			break;
7501.88Skamil		default:
7511.88Skamil			/* NOTREACHED */
7521.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7531.88Skamil		}
7541.88Skamil
7551.88Skamil		/* NOTREACHED */
7561.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7571.88Skamil	}
7581.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7591.88Skamil
7601.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7611.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7621.88Skamil
7631.90Skamil	validate_status_stopped(status, sigval);
7641.90Skamil
7651.90Skamil	name[0] = CTL_KERN,
7661.90Skamil	name[1] = KERN_PROC2,
7671.90Skamil	name[2] = KERN_PROC_PID;
7681.90Skamil	name[3] = child;
7691.90Skamil	name[4] = sizeof(kp);
7701.90Skamil	name[5] = 1;
7711.90Skamil
7721.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
7731.90Skamil
7741.90Skamil	kp_sigignore = kp.p_sigignore;
7751.90Skamil
7761.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7771.90Skamil	SYSCALL_REQUIRE(
7781.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7791.90Skamil
7801.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7811.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7821.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7831.90Skamil	    info.psi_siginfo.si_errno);
7841.90Skamil
7851.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
7861.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
7871.90Skamil
7881.90Skamil	DPRINTF("Before resuming the child process where it left off and "
7891.90Skamil	    "without signal to be sent\n");
7901.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
7911.90Skamil
7921.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7931.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7941.90Skamil
7951.88Skamil	validate_status_stopped(status, sig);
7961.88Skamil
7971.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
7981.88Skamil	SYSCALL_REQUIRE(
7991.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8001.88Skamil
8011.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8021.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8031.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8041.88Skamil	    info.psi_siginfo.si_errno);
8051.88Skamil
8061.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8071.90Skamil
8081.90Skamil	DPRINTF("kp_sigignore="
8091.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8101.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8111.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8121.90Skamil
8131.90Skamil	DPRINTF("kp.p_sigignore="
8141.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8151.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8161.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8171.90Skamil
8181.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8191.90Skamil
8201.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8211.88Skamil	switch (sig) {
8221.88Skamil	case SIGTRAP:
8231.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8241.88Skamil		break;
8251.88Skamil	case SIGSEGV:
8261.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8271.88Skamil		break;
8281.88Skamil	case SIGILL:
8291.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
8301.88Skamil		break;
8311.88Skamil	case SIGFPE:
8321.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8331.88Skamil		break;
8341.88Skamil	case SIGBUS:
8351.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8361.88Skamil		break;
8371.88Skamil	}
8381.88Skamil
8391.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8401.88Skamil
8411.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8421.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8431.88Skamil
8441.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8451.88Skamil
8461.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8471.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8481.88Skamil}
8491.88Skamil
8501.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8511.88SkamilATF_TC(test);								\
8521.88SkamilATF_TC_HEAD(test, tc)							\
8531.88Skamil{									\
8541.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8551.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8561.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8571.88Skamil}									\
8581.88Skamil									\
8591.88SkamilATF_TC_BODY(test, tc)							\
8601.88Skamil{									\
8611.88Skamil									\
8621.88Skamil	traceme_signalignored_crash(sig);				\
8631.88Skamil}
8641.88Skamil
8651.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8661.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8671.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8681.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8691.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8701.88Skamil
8711.88Skamil/// ----------------------------------------------------------------------------
8721.88Skamil
8731.88Skamilstatic void
8741.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
8751.1Skamil{
8761.1Skamil	const int exitval = 5;
8771.34Skamil	const int sigval = SIGSTOP;
8781.1Skamil	pid_t child, wpid;
8791.1Skamil	struct sigaction sa;
8801.1Skamil#if defined(TWAIT_HAVE_STATUS)
8811.1Skamil	int status;
8821.1Skamil#endif
8831.61Skre	struct ptrace_siginfo info;
8841.1Skamil
8851.45Skamil	memset(&info, 0, sizeof(info));
8861.45Skamil
8871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
8881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
8891.1Skamil	if (child == 0) {
8901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8921.1Skamil
8931.34Skamil		sa.sa_handler = sah;
8941.1Skamil		sa.sa_flags = SA_SIGINFO;
8951.1Skamil		sigemptyset(&sa.sa_mask);
8961.1Skamil
8971.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
8981.1Skamil
8991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9011.1Skamil
9021.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9031.1Skamil
9041.13Schristos		DPRINTF("Before exiting of the child process\n");
9051.1Skamil		_exit(exitval);
9061.1Skamil	}
9071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9081.1Skamil
9091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9111.1Skamil
9121.1Skamil	validate_status_stopped(status, sigval);
9131.1Skamil
9141.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9151.61Skre	SYSCALL_REQUIRE(
9161.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9171.45Skamil
9181.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9191.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9201.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9211.45Skamil	    info.psi_siginfo.si_errno);
9221.45Skamil
9231.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9241.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9251.45Skamil
9261.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9271.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9291.1Skamil
9301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9321.1Skamil
9331.1Skamil	validate_status_exited(status, exitval);
9341.1Skamil
9351.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9371.1Skamil}
9381.1Skamil
9391.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9401.61SkreATF_TC(test);								\
9411.61SkreATF_TC_HEAD(test, tc)							\
9421.61Skre{									\
9431.61Skre	atf_tc_set_md_var(tc, "descr",					\
9441.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9451.61Skre	    "handled correctly and caught by a signal handler");	\
9461.61Skre}									\
9471.61Skre									\
9481.61Skrestatic int test##_caught = 0;						\
9491.61Skre									\
9501.61Skrestatic void								\
9511.61Skretest##_sighandler(int arg)						\
9521.61Skre{									\
9531.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9541.61Skre									\
9551.61Skre	++ test##_caught;						\
9561.61Skre}									\
9571.61Skre									\
9581.61SkreATF_TC_BODY(test, tc)							\
9591.61Skre{									\
9601.61Skre									\
9611.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9621.34Skamil}
9631.34Skamil
9641.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9651.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9661.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9671.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9681.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9691.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9701.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9711.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
9721.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
9731.34Skamil
9741.34Skamil/// ----------------------------------------------------------------------------
9751.34Skamil
9761.35Skamilstatic void
9771.50Skamiltraceme_sendsignal_masked(int sigsent)
9781.50Skamil{
9791.50Skamil	const int exitval = 5;
9801.50Skamil	const int sigval = SIGSTOP;
9811.50Skamil	pid_t child, wpid;
9821.50Skamil	sigset_t set;
9831.50Skamil#if defined(TWAIT_HAVE_STATUS)
9841.50Skamil	int status;
9851.50Skamil#endif
9861.61Skre	struct ptrace_siginfo info;
9871.50Skamil
9881.50Skamil	memset(&info, 0, sizeof(info));
9891.50Skamil
9901.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9911.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
9921.50Skamil	if (child == 0) {
9931.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9941.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9951.50Skamil
9961.50Skamil		sigemptyset(&set);
9971.50Skamil		sigaddset(&set, sigsent);
9981.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
9991.50Skamil
10001.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10011.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10021.50Skamil
10031.50Skamil		_exit(exitval);
10041.50Skamil	}
10051.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10061.50Skamil
10071.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10081.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10091.50Skamil
10101.50Skamil	validate_status_stopped(status, sigval);
10111.50Skamil
10121.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10131.61Skre	SYSCALL_REQUIRE(
10141.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10151.50Skamil
10161.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10171.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10181.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10191.50Skamil	    info.psi_siginfo.si_errno);
10201.50Skamil
10211.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10221.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10231.50Skamil
10241.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10251.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10261.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10271.50Skamil
10281.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10291.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10301.50Skamil
10311.50Skamil	validate_status_exited(status, exitval);
10321.50Skamil
10331.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10341.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10351.50Skamil}
10361.50Skamil
10371.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10381.61SkreATF_TC(test);								\
10391.61SkreATF_TC_HEAD(test, tc)							\
10401.61Skre{									\
10411.61Skre	atf_tc_set_md_var(tc, "descr",					\
10421.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10431.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10441.61Skre}									\
10451.61Skre									\
10461.61SkreATF_TC_BODY(test, tc)							\
10471.61Skre{									\
10481.61Skre									\
10491.61Skre	traceme_sendsignal_masked(sig);					\
10501.50Skamil}
10511.50Skamil
10521.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10531.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10541.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10551.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10561.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10571.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10581.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10591.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10601.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10611.50Skamil
10621.50Skamil/// ----------------------------------------------------------------------------
10631.50Skamil
10641.50Skamilstatic void
10651.50Skamiltraceme_sendsignal_ignored(int sigsent)
10661.50Skamil{
10671.50Skamil	const int exitval = 5;
10681.50Skamil	const int sigval = SIGSTOP;
10691.50Skamil	pid_t child, wpid;
10701.50Skamil	struct sigaction sa;
10711.50Skamil#if defined(TWAIT_HAVE_STATUS)
10721.50Skamil	int status;
10731.50Skamil#endif
10741.61Skre	struct ptrace_siginfo info;
10751.50Skamil
10761.50Skamil	memset(&info, 0, sizeof(info));
10771.50Skamil
10781.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10791.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10801.50Skamil	if (child == 0) {
10811.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10821.61Skre
10831.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10841.50Skamil
10851.50Skamil		memset(&sa, 0, sizeof(sa));
10861.50Skamil		sa.sa_handler = SIG_IGN;
10871.50Skamil		sigemptyset(&sa.sa_mask);
10881.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
10891.50Skamil
10901.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10911.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10921.50Skamil
10931.50Skamil		_exit(exitval);
10941.50Skamil	}
10951.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10961.50Skamil
10971.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10981.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10991.50Skamil
11001.50Skamil	validate_status_stopped(status, sigval);
11011.50Skamil
11021.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11031.61Skre	SYSCALL_REQUIRE(
11041.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11051.50Skamil
11061.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11071.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11081.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11091.50Skamil	    info.psi_siginfo.si_errno);
11101.50Skamil
11111.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11121.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11131.50Skamil
11141.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11151.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11161.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11171.50Skamil
11181.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11191.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11201.50Skamil
11211.50Skamil	validate_status_exited(status, exitval);
11221.50Skamil
11231.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11241.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11251.50Skamil}
11261.50Skamil
11271.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11281.61SkreATF_TC(test);								\
11291.61SkreATF_TC_HEAD(test, tc)							\
11301.61Skre{									\
11311.61Skre	atf_tc_set_md_var(tc, "descr",					\
11321.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11331.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11341.61Skre}									\
11351.61Skre									\
11361.61SkreATF_TC_BODY(test, tc)							\
11371.61Skre{									\
11381.61Skre									\
11391.61Skre	traceme_sendsignal_ignored(sig);				\
11401.50Skamil}
11411.50Skamil
11421.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11431.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11441.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11451.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11461.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11471.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11481.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11491.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11501.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11511.50Skamil
11521.50Skamil/// ----------------------------------------------------------------------------
11531.50Skamil
11541.50Skamilstatic void
11551.50Skamiltraceme_sendsignal_simple(int sigsent)
11561.1Skamil{
11571.35Skamil	const int sigval = SIGSTOP;
11581.35Skamil	int exitval = 0;
11591.1Skamil	pid_t child, wpid;
11601.1Skamil#if defined(TWAIT_HAVE_STATUS)
11611.1Skamil	int status;
11621.85Skamil	int expect_core;
11631.85Skamil
11641.85Skamil	switch (sigsent) {
11651.85Skamil	case SIGABRT:
11661.85Skamil	case SIGTRAP:
11671.85Skamil	case SIGBUS:
11681.85Skamil	case SIGILL:
11691.85Skamil	case SIGFPE:
11701.85Skamil	case SIGSEGV:
11711.85Skamil		expect_core = 1;
11721.85Skamil		break;
11731.85Skamil	default:
11741.85Skamil		expect_core = 0;
11751.85Skamil		break;
11761.85Skamil	}
11771.1Skamil#endif
11781.61Skre	struct ptrace_siginfo info;
11791.1Skamil
11801.45Skamil	memset(&info, 0, sizeof(info));
11811.45Skamil
11821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
11831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
11841.1Skamil	if (child == 0) {
11851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11871.1Skamil
11881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11901.1Skamil
11911.35Skamil		switch (sigsent) {
11921.35Skamil		case SIGCONT:
11931.48Skamil		case SIGSTOP:
11941.35Skamil			_exit(exitval);
11951.35Skamil		default:
11961.35Skamil			/* NOTREACHED */
11971.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
11981.35Skamil		}
11991.1Skamil	}
12001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12011.1Skamil
12021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12041.1Skamil
12051.1Skamil	validate_status_stopped(status, sigval);
12061.1Skamil
12071.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12081.61Skre	SYSCALL_REQUIRE(
12091.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12101.45Skamil
12111.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12121.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12131.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12141.45Skamil	    info.psi_siginfo.si_errno);
12151.45Skamil
12161.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12171.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12181.45Skamil
12191.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12201.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12221.1Skamil
12231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12251.1Skamil
12261.35Skamil	switch (sigsent) {
12271.48Skamil	case SIGSTOP:
12281.48Skamil		validate_status_stopped(status, sigsent);
12291.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12301.61Skre		    "child\n");
12311.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12321.61Skre		    sizeof(info)) != -1);
12331.48Skamil
12341.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12351.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12361.61Skre		    "si_errno=%#x\n",
12371.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12381.61Skre		    info.psi_siginfo.si_errno);
12391.48Skamil
12401.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12411.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12421.48Skamil
12431.48Skamil		DPRINTF("Before resuming the child process where it left off "
12441.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12451.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12461.48Skamil
12471.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12481.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12491.61Skre		    child);
12501.48Skamil		/* FALLTHROUGH */
12511.35Skamil	case SIGCONT:
12521.35Skamil		validate_status_exited(status, exitval);
12531.35Skamil		break;
12541.35Skamil	default:
12551.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12561.35Skamil		break;
12571.35Skamil	}
12581.1Skamil
12591.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12611.1Skamil}
12621.1Skamil
12631.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12641.61SkreATF_TC(test);								\
12651.61SkreATF_TC_HEAD(test, tc)							\
12661.61Skre{									\
12671.61Skre	atf_tc_set_md_var(tc, "descr",					\
12681.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12691.61Skre	    "handled correctly in a child without a signal handler");	\
12701.61Skre}									\
12711.61Skre									\
12721.61SkreATF_TC_BODY(test, tc)							\
12731.61Skre{									\
12741.61Skre									\
12751.61Skre	traceme_sendsignal_simple(sig);					\
12761.35Skamil}
12771.35Skamil
12781.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
12791.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
12801.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
12811.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
12821.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
12831.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
12841.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
12851.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
12861.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
12871.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
12881.35Skamil
12891.35Skamil/// ----------------------------------------------------------------------------
12901.35Skamil
12911.37SkamilATF_TC(traceme_pid1_parent);
12921.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
12931.37Skamil{
12941.37Skamil	atf_tc_set_md_var(tc, "descr",
12951.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
12961.37Skamil}
12971.37Skamil
12981.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
12991.37Skamil{
13001.37Skamil	struct msg_fds parent_child;
13011.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13021.37Skamil	pid_t child1, child2, wpid;
13031.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13041.37Skamil#if defined(TWAIT_HAVE_STATUS)
13051.37Skamil	int status;
13061.37Skamil#endif
13071.37Skamil
13081.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13091.37Skamil
13101.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13111.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13121.37Skamil	if (child1 == 0) {
13131.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13141.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13151.37Skamil		if (child2 != 0) {
13161.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13171.61Skre			    getpid(), child2);
13181.37Skamil			_exit(exitval_child1);
13191.37Skamil		}
13201.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13211.37Skamil
13221.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13231.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13241.37Skamil
13251.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13261.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13271.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13281.37Skamil
13291.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13301.37Skamil
13311.37Skamil		_exit(exitval_child2);
13321.37Skamil	}
13331.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13341.37Skamil
13351.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13361.61Skre	TWAIT_REQUIRE_SUCCESS(
13371.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13381.37Skamil
13391.37Skamil	validate_status_exited(status, exitval_child1);
13401.37Skamil
13411.37Skamil	DPRINTF("Notify that child1 is dead\n");
13421.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13431.37Skamil
13441.37Skamil	DPRINTF("Wait for exiting of child2\n");
13451.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13461.37Skamil}
13471.37Skamil
13481.37Skamil/// ----------------------------------------------------------------------------
13491.37Skamil
13501.40Skamilstatic void
13511.40Skamiltraceme_vfork_raise(int sigval)
13521.40Skamil{
13531.46Skamil	const int exitval = 5, exitval_watcher = 10;
13541.46Skamil	pid_t child, parent, watcher, wpid;
13551.46Skamil	int rv;
13561.40Skamil#if defined(TWAIT_HAVE_STATUS)
13571.40Skamil	int status;
13581.85Skamil
13591.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13601.85Skamil	volatile int expect_core;
13611.85Skamil
13621.85Skamil	switch (sigval) {
13631.85Skamil	case SIGABRT:
13641.85Skamil	case SIGTRAP:
13651.85Skamil	case SIGBUS:
13661.85Skamil	case SIGILL:
13671.85Skamil	case SIGFPE:
13681.85Skamil	case SIGSEGV:
13691.85Skamil		expect_core = 1;
13701.85Skamil		break;
13711.85Skamil	default:
13721.85Skamil		expect_core = 0;
13731.85Skamil		break;
13741.85Skamil	}
13751.40Skamil#endif
13761.40Skamil
13771.46Skamil	/*
13781.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
13791.46Skamil	 * the SIGKILL signal to it.
13801.46Skamil	 *
13811.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
13821.46Skamil	 * simpler to reparent this process to initproc and forget about it.
13831.46Skamil	 */
13841.46Skamil	if (sigval == SIGSTOP) {
13851.46Skamil		parent = getpid();
13861.46Skamil
13871.46Skamil		watcher = fork();
13881.46Skamil		ATF_REQUIRE(watcher != 1);
13891.46Skamil		if (watcher == 0) {
13901.46Skamil			/* Double fork(2) trick to reparent to initproc */
13911.46Skamil			watcher = fork();
13921.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
13931.46Skamil			if (watcher != 0)
13941.46Skamil				_exit(exitval_watcher);
13951.46Skamil
13961.46Skamil			child = await_stopped_child(parent);
13971.46Skamil
13981.46Skamil			errno = 0;
13991.46Skamil			rv = kill(child, SIGKILL);
14001.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
14011.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14021.46Skamil
14031.46Skamil			/* This exit value will be collected by initproc */
14041.46Skamil			_exit(0);
14051.46Skamil		}
14061.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14071.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14081.61Skre		    watcher);
14091.46Skamil
14101.46Skamil		validate_status_exited(status, exitval_watcher);
14111.46Skamil
14121.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14131.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14141.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14151.46Skamil	}
14161.46Skamil
14171.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14181.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14191.40Skamil	if (child == 0) {
14201.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14211.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14221.40Skamil
14231.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14241.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14251.40Skamil
14261.40Skamil		switch (sigval) {
14271.46Skamil		case SIGSTOP:
14281.40Skamil		case SIGKILL:
14291.40Skamil		case SIGABRT:
14301.40Skamil		case SIGHUP:
14311.85Skamil		case SIGTRAP:
14321.85Skamil		case SIGBUS:
14331.85Skamil		case SIGILL:
14341.85Skamil		case SIGFPE:
14351.85Skamil		case SIGSEGV:
14361.40Skamil			/* NOTREACHED */
14371.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14381.70Smrg			__unreachable();
14391.40Skamil		default:
14401.40Skamil			DPRINTF("Before exiting of the child process\n");
14411.40Skamil			_exit(exitval);
14421.40Skamil		}
14431.40Skamil	}
14441.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14451.40Skamil
14461.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14471.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14481.40Skamil
14491.40Skamil	switch (sigval) {
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		validate_status_signaled(status, sigval, expect_core);
14591.40Skamil		break;
14601.40Skamil	case SIGSTOP:
14611.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14621.46Skamil		break;
14631.40Skamil	case SIGCONT:
14641.47Skamil	case SIGTSTP:
14651.47Skamil	case SIGTTIN:
14661.47Skamil	case SIGTTOU:
14671.40Skamil		validate_status_exited(status, exitval);
14681.40Skamil		break;
14691.40Skamil	default:
14701.40Skamil		/* NOTREACHED */
14711.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
14721.40Skamil		break;
14731.40Skamil	}
14741.40Skamil
14751.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14761.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14771.40Skamil}
14781.40Skamil
14791.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
14801.61SkreATF_TC(test);								\
14811.61SkreATF_TC_HEAD(test, tc)							\
14821.61Skre{									\
14831.61Skre	atf_tc_set_md_var(tc, "descr",					\
14841.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
14851.61Skre	    "vfork(2)ed child");					\
14861.61Skre}									\
14871.61Skre									\
14881.61SkreATF_TC_BODY(test, tc)							\
14891.61Skre{									\
14901.61Skre									\
14911.61Skre	traceme_vfork_raise(sig);					\
14921.40Skamil}
14931.40Skamil
14941.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
14951.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
14961.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
14971.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
14981.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
14991.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
15001.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
15011.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15021.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15031.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15041.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15051.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15061.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15071.40Skamil
15081.40Skamil/// ----------------------------------------------------------------------------
15091.40Skamil
15101.52Skamilstatic void
15111.52Skamiltraceme_vfork_crash(int sig)
15121.41Skamil{
15131.41Skamil	pid_t child, wpid;
15141.41Skamil#if defined(TWAIT_HAVE_STATUS)
15151.41Skamil	int status;
15161.41Skamil#endif
15171.41Skamil
15181.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15191.71Skamil	if (sig == SIGILL)
15201.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15211.71Skamil#endif
15221.71Skamil
15231.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15241.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15251.41Skamil	if (child == 0) {
15261.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15271.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15281.41Skamil
15291.52Skamil		DPRINTF("Before executing a trap\n");
15301.52Skamil		switch (sig) {
15311.52Skamil		case SIGTRAP:
15321.52Skamil			trigger_trap();
15331.52Skamil			break;
15341.52Skamil		case SIGSEGV:
15351.52Skamil			trigger_segv();
15361.52Skamil			break;
15371.52Skamil		case SIGILL:
15381.52Skamil			trigger_ill();
15391.52Skamil			break;
15401.52Skamil		case SIGFPE:
15411.52Skamil			trigger_fpe();
15421.52Skamil			break;
15431.52Skamil		case SIGBUS:
15441.52Skamil			trigger_bus();
15451.52Skamil			break;
15461.52Skamil		default:
15471.52Skamil			/* NOTREACHED */
15481.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15491.52Skamil		}
15501.41Skamil
15511.41Skamil		/* NOTREACHED */
15521.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15531.41Skamil	}
15541.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15551.41Skamil
15561.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15571.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15581.41Skamil
15591.52Skamil	validate_status_signaled(status, sig, 1);
15601.41Skamil
15611.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15621.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15631.41Skamil}
15641.41Skamil
15651.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15661.61SkreATF_TC(test);								\
15671.61SkreATF_TC_HEAD(test, tc)							\
15681.61Skre{									\
15691.61Skre	atf_tc_set_md_var(tc, "descr",					\
15701.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
15711.61Skre	    "vfork(2)ed child");					\
15721.61Skre}									\
15731.61Skre									\
15741.61SkreATF_TC_BODY(test, tc)							\
15751.61Skre{									\
15761.61Skre									\
15771.61Skre	traceme_vfork_crash(sig);					\
15781.52Skamil}
15791.52Skamil
15801.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
15811.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
15821.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
15831.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
15841.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
15851.52Skamil
15861.41Skamil/// ----------------------------------------------------------------------------
15871.41Skamil
15881.92Skamilstatic void
15891.92Skamiltraceme_vfork_signalmasked_crash(int sig)
15901.92Skamil{
15911.92Skamil	pid_t child, wpid;
15921.92Skamil#if defined(TWAIT_HAVE_STATUS)
15931.92Skamil	int status;
15941.92Skamil#endif
15951.92Skamil	sigset_t intmask;
15961.92Skamil
15971.92Skamil#ifndef PTRACE_ILLEGAL_ASM
15981.92Skamil	if (sig == SIGILL)
15991.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16001.92Skamil#endif
16011.92Skamil
16021.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16031.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16041.92Skamil	if (child == 0) {
16051.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16061.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16071.92Skamil
16081.92Skamil		sigemptyset(&intmask);
16091.92Skamil		sigaddset(&intmask, sig);
16101.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16111.92Skamil
16121.92Skamil		DPRINTF("Before executing a trap\n");
16131.92Skamil		switch (sig) {
16141.92Skamil		case SIGTRAP:
16151.92Skamil			trigger_trap();
16161.92Skamil			break;
16171.92Skamil		case SIGSEGV:
16181.92Skamil			trigger_segv();
16191.92Skamil			break;
16201.92Skamil		case SIGILL:
16211.92Skamil			trigger_ill();
16221.92Skamil			break;
16231.92Skamil		case SIGFPE:
16241.92Skamil			trigger_fpe();
16251.92Skamil			break;
16261.92Skamil		case SIGBUS:
16271.92Skamil			trigger_bus();
16281.92Skamil			break;
16291.92Skamil		default:
16301.92Skamil			/* NOTREACHED */
16311.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16321.92Skamil		}
16331.92Skamil
16341.92Skamil		/* NOTREACHED */
16351.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16361.92Skamil	}
16371.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16381.92Skamil
16391.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16401.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16411.92Skamil
16421.92Skamil	validate_status_signaled(status, sig, 1);
16431.92Skamil
16441.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16451.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16461.92Skamil}
16471.92Skamil
16481.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16491.92SkamilATF_TC(test);								\
16501.92SkamilATF_TC_HEAD(test, tc)							\
16511.92Skamil{									\
16521.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16531.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16541.92Skamil	    "vfork(2)ed child with a masked signal");			\
16551.92Skamil}									\
16561.92Skamil									\
16571.92SkamilATF_TC_BODY(test, tc)							\
16581.92Skamil{									\
16591.92Skamil									\
16601.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16611.92Skamil}
16621.92Skamil
16631.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16641.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16651.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
16661.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
16671.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
16681.92Skamil
16691.92Skamil/// ----------------------------------------------------------------------------
16701.92Skamil
16711.92Skamilstatic void
16721.92Skamiltraceme_vfork_signalignored_crash(int sig)
16731.92Skamil{
16741.92Skamil	pid_t child, wpid;
16751.92Skamil#if defined(TWAIT_HAVE_STATUS)
16761.92Skamil	int status;
16771.92Skamil#endif
16781.92Skamil	struct sigaction sa;
16791.92Skamil
16801.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16811.92Skamil	if (sig == SIGILL)
16821.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16831.92Skamil#endif
16841.92Skamil
16851.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16861.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16871.92Skamil	if (child == 0) {
16881.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16891.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16901.92Skamil
16911.92Skamil		memset(&sa, 0, sizeof(sa));
16921.92Skamil		sa.sa_handler = SIG_IGN;
16931.92Skamil		sigemptyset(&sa.sa_mask);
16941.92Skamil
16951.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
16961.92Skamil
16971.92Skamil		DPRINTF("Before executing a trap\n");
16981.92Skamil		switch (sig) {
16991.92Skamil		case SIGTRAP:
17001.92Skamil			trigger_trap();
17011.92Skamil			break;
17021.92Skamil		case SIGSEGV:
17031.92Skamil			trigger_segv();
17041.92Skamil			break;
17051.92Skamil		case SIGILL:
17061.92Skamil			trigger_ill();
17071.92Skamil			break;
17081.92Skamil		case SIGFPE:
17091.92Skamil			trigger_fpe();
17101.92Skamil			break;
17111.92Skamil		case SIGBUS:
17121.92Skamil			trigger_bus();
17131.92Skamil			break;
17141.92Skamil		default:
17151.92Skamil			/* NOTREACHED */
17161.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17171.92Skamil		}
17181.92Skamil
17191.92Skamil		/* NOTREACHED */
17201.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17211.92Skamil	}
17221.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17231.92Skamil
17241.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17251.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17261.92Skamil
17271.92Skamil	validate_status_signaled(status, sig, 1);
17281.92Skamil
17291.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17301.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17311.92Skamil}
17321.92Skamil
17331.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17341.92SkamilATF_TC(test);								\
17351.92SkamilATF_TC_HEAD(test, tc)							\
17361.92Skamil{									\
17371.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17381.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17391.92Skamil	    "vfork(2)ed child with ignored signal");			\
17401.92Skamil}									\
17411.92Skamil									\
17421.92SkamilATF_TC_BODY(test, tc)							\
17431.92Skamil{									\
17441.92Skamil									\
17451.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17461.92Skamil}
17471.92Skamil
17481.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17491.92Skamil    SIGTRAP)
17501.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17511.92Skamil    SIGSEGV)
17521.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17531.92Skamil    SIGILL)
17541.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17551.92Skamil    SIGFPE)
17561.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17571.92Skamil    SIGBUS)
17581.92Skamil
17591.92Skamil/// ----------------------------------------------------------------------------
17601.92Skamil
17611.96Skamilstatic void
17621.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
17631.43Skamil{
17641.43Skamil	const int sigval = SIGTRAP;
17651.43Skamil	pid_t child, wpid;
17661.43Skamil#if defined(TWAIT_HAVE_STATUS)
17671.43Skamil	int status;
17681.43Skamil#endif
17691.96Skamil	struct sigaction sa;
17701.61Skre	struct ptrace_siginfo info;
17711.96Skamil	sigset_t intmask;
17721.96Skamil	struct kinfo_proc2 kp;
17731.96Skamil	size_t len = sizeof(kp);
17741.96Skamil
17751.96Skamil	int name[6];
17761.96Skamil	const size_t namelen = __arraycount(name);
17771.96Skamil	ki_sigset_t kp_sigmask;
17781.96Skamil	ki_sigset_t kp_sigignore;
17791.43Skamil
17801.43Skamil	memset(&info, 0, sizeof(info));
17811.43Skamil
17821.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17831.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17841.43Skamil	if (child == 0) {
17851.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17861.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17871.43Skamil
17881.96Skamil		if (masked) {
17891.96Skamil			sigemptyset(&intmask);
17901.96Skamil			sigaddset(&intmask, sigval);
17911.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
17921.96Skamil		}
17931.96Skamil
17941.96Skamil		if (ignored) {
17951.96Skamil			memset(&sa, 0, sizeof(sa));
17961.96Skamil			sa.sa_handler = SIG_IGN;
17971.96Skamil			sigemptyset(&sa.sa_mask);
17981.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
17991.96Skamil		}
18001.96Skamil
18011.43Skamil		DPRINTF("Before calling execve(2) from child\n");
18021.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
18031.43Skamil
18041.43Skamil		/* NOTREACHED */
18051.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18061.43Skamil	}
18071.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18081.43Skamil
18091.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18101.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18111.43Skamil
18121.43Skamil	validate_status_stopped(status, sigval);
18131.43Skamil
18141.96Skamil	name[0] = CTL_KERN,
18151.96Skamil	name[1] = KERN_PROC2,
18161.96Skamil	name[2] = KERN_PROC_PID;
18171.96Skamil	name[3] = getpid();
18181.96Skamil	name[4] = sizeof(kp);
18191.96Skamil	name[5] = 1;
18201.96Skamil
18211.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18221.96Skamil
18231.96Skamil	if (masked)
18241.96Skamil		kp_sigmask = kp.p_sigmask;
18251.96Skamil
18261.96Skamil	if (ignored)
18271.96Skamil		kp_sigignore = kp.p_sigignore;
18281.96Skamil
18291.96Skamil	name[3] = getpid();
18301.96Skamil
18311.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18321.96Skamil
18331.96Skamil	if (masked) {
18341.96Skamil		DPRINTF("kp_sigmask="
18351.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18361.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18371.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18381.96Skamil
18391.96Skamil	        DPRINTF("kp.p_sigmask="
18401.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18411.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18421.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18431.96Skamil
18441.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18451.96Skamil		    sizeof(kp_sigmask)));
18461.96Skamil	}
18471.96Skamil
18481.96Skamil	if (ignored) {
18491.96Skamil		DPRINTF("kp_sigignore="
18501.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18511.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18521.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18531.96Skamil
18541.96Skamil	        DPRINTF("kp.p_sigignore="
18551.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18561.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
18571.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
18581.96Skamil
18591.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
18601.96Skamil		    sizeof(kp_sigignore)));
18611.96Skamil	}
18621.96Skamil
18631.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
18641.61Skre	SYSCALL_REQUIRE(
18651.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
18661.43Skamil
18671.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
18681.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
18691.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
18701.43Skamil	    info.psi_siginfo.si_errno);
18711.43Skamil
18721.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
18731.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
18741.43Skamil
18751.43Skamil	DPRINTF("Before resuming the child process where it left off and "
18761.43Skamil	    "without signal to be sent\n");
18771.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18781.43Skamil
18791.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18801.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18811.43Skamil
18821.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18831.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18841.43Skamil}
18851.43Skamil
18861.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
18871.96SkamilATF_TC(test);								\
18881.96SkamilATF_TC_HEAD(test, tc)							\
18891.96Skamil{									\
18901.96Skamil	atf_tc_set_md_var(tc, "descr",					\
18911.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
18921.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
18931.96Skamil	    masked ? " with ignored signal" : "");			\
18941.96Skamil}									\
18951.96Skamil									\
18961.96SkamilATF_TC_BODY(test, tc)							\
18971.96Skamil{									\
18981.96Skamil									\
18991.96Skamil	traceme_vfork_exec(masked, ignored);				\
19001.96Skamil}
19011.96Skamil
19021.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
19031.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19041.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19051.96Skamil
19061.43Skamil/// ----------------------------------------------------------------------------
19071.43Skamil
19081.1Skamil#if defined(TWAIT_HAVE_PID)
19091.51Skamilstatic void
19101.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19111.59Skamil{
19121.94Skamil	const int sigval = SIGSTOP;
19131.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19141.59Skamil	const int exitval = 10;
19151.59Skamil	pid_t tracee, tracer, wpid;
19161.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19171.59Skamil#if defined(TWAIT_HAVE_STATUS)
19181.59Skamil	int status;
19191.59Skamil#endif
19201.94Skamil	struct sigaction sa;
19211.59Skamil	struct ptrace_siginfo info;
19221.94Skamil	sigset_t intmask;
19231.94Skamil	struct kinfo_proc2 kp;
19241.94Skamil	size_t len = sizeof(kp);
19251.94Skamil
19261.94Skamil	int name[6];
19271.94Skamil	const size_t namelen = __arraycount(name);
19281.94Skamil	ki_sigset_t kp_sigmask;
19291.94Skamil	ki_sigset_t kp_sigignore;
19301.61Skre
19311.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19321.71Skamil	if (sig == SIGILL)
19331.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19341.71Skamil#endif
19351.71Skamil
19361.59Skamil	memset(&info, 0, sizeof(info));
19371.59Skamil
19381.94Skamil	if (masked || ignored)
19391.94Skamil		atf_tc_expect_fail("Unexpected sigmask reset on crash under "
19401.94Skamil		    "debugger");
19411.94Skamil
19421.59Skamil	DPRINTF("Spawn tracee\n");
19431.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19441.59Skamil	tracee = atf_utils_fork();
19451.59Skamil	if (tracee == 0) {
19461.59Skamil		// Wait for parent to let us crash
19471.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19481.61Skre
19491.94Skamil		if (masked) {
19501.94Skamil			sigemptyset(&intmask);
19511.94Skamil			sigaddset(&intmask, sig);
19521.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19531.94Skamil		}
19541.94Skamil
19551.94Skamil		if (ignored) {
19561.94Skamil			memset(&sa, 0, sizeof(sa));
19571.94Skamil			sa.sa_handler = SIG_IGN;
19581.94Skamil			sigemptyset(&sa.sa_mask);
19591.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
19601.94Skamil		}
19611.94Skamil
19621.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19631.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19641.94Skamil
19651.59Skamil		DPRINTF("Before executing a trap\n");
19661.59Skamil		switch (sig) {
19671.59Skamil		case SIGTRAP:
19681.59Skamil			trigger_trap();
19691.59Skamil			break;
19701.59Skamil		case SIGSEGV:
19711.59Skamil			trigger_segv();
19721.59Skamil			break;
19731.59Skamil		case SIGILL:
19741.59Skamil			trigger_ill();
19751.59Skamil			break;
19761.59Skamil		case SIGFPE:
19771.59Skamil			trigger_fpe();
19781.59Skamil			break;
19791.59Skamil		case SIGBUS:
19801.59Skamil			trigger_bus();
19811.59Skamil			break;
19821.59Skamil		default:
19831.59Skamil			/* NOTREACHED */
19841.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
19851.59Skamil		}
19861.59Skamil
19871.59Skamil		/* NOTREACHED */
19881.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
19891.59Skamil	}
19901.59Skamil
19911.59Skamil	DPRINTF("Spawn debugger\n");
19921.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
19931.59Skamil	tracer = atf_utils_fork();
19941.59Skamil	if (tracer == 0) {
19951.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
19961.59Skamil		tracer = atf_utils_fork();
19971.59Skamil		if (tracer != 0)
19981.61Skre			_exit(exitval);
19991.59Skamil
20001.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
20011.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
20021.59Skamil
20031.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
20041.59Skamil		FORKEE_REQUIRE_SUCCESS(
20051.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20061.59Skamil
20071.59Skamil		forkee_status_stopped(status, SIGSTOP);
20081.59Skamil
20091.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20101.94Skamil		    "traced process\n");
20111.94Skamil		SYSCALL_REQUIRE(
20121.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20131.94Skamil
20141.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20151.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20161.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20171.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20181.94Skamil
20191.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20201.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20211.94Skamil
20221.59Skamil		/* Resume tracee with PT_CONTINUE */
20231.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20241.59Skamil
20251.59Skamil		/* Inform parent that tracer has attached to tracee */
20261.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20271.59Skamil
20281.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20291.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20301.59Skamil
20311.59Skamil		/* Wait for tracee and assert that it exited */
20321.59Skamil		FORKEE_REQUIRE_SUCCESS(
20331.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20341.59Skamil
20351.94Skamil		forkee_status_stopped(status, sigval);
20361.94Skamil
20371.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20381.94Skamil		    "traced process\n");
20391.94Skamil		SYSCALL_REQUIRE(
20401.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20411.94Skamil
20421.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20431.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20441.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20451.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20461.94Skamil
20471.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20481.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20491.94Skamil
20501.94Skamil		name[0] = CTL_KERN,
20511.94Skamil		name[1] = KERN_PROC2,
20521.94Skamil		name[2] = KERN_PROC_PID;
20531.94Skamil		name[3] = tracee;
20541.94Skamil		name[4] = sizeof(kp);
20551.94Skamil		name[5] = 1;
20561.94Skamil
20571.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20581.94Skamil
20591.94Skamil		if (masked)
20601.94Skamil			kp_sigmask = kp.p_sigmask;
20611.94Skamil
20621.94Skamil		if (ignored)
20631.94Skamil			kp_sigignore = kp.p_sigignore;
20641.94Skamil
20651.94Skamil		/* Resume tracee with PT_CONTINUE */
20661.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20671.94Skamil
20681.94Skamil		/* Wait for tracee and assert that it exited */
20691.94Skamil		FORKEE_REQUIRE_SUCCESS(
20701.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20711.94Skamil
20721.93Skamil		forkee_status_stopped(status, sig);
20731.59Skamil
20741.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20751.61Skre		    "traced process\n");
20761.61Skre		SYSCALL_REQUIRE(
20771.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20781.59Skamil
20791.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20801.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20811.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20821.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20831.59Skamil
20841.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
20851.94Skamil
20861.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20871.94Skamil
20881.94Skamil		if (masked) {
20891.94Skamil			DPRINTF("kp_sigmask="
20901.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
20911.94Skamil			    PRIx32 "\n",
20921.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
20931.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
20941.94Skamil
20951.94Skamil			DPRINTF("kp.p_sigmask="
20961.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
20971.94Skamil			    PRIx32 "\n",
20981.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
20991.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
21001.94Skamil
21011.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
21021.94Skamil			    sizeof(kp_sigmask)));
21031.94Skamil		}
21041.94Skamil
21051.94Skamil		if (ignored) {
21061.94Skamil			DPRINTF("kp_sigignore="
21071.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21081.94Skamil			    PRIx32 "\n",
21091.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21101.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21111.94Skamil
21121.94Skamil			DPRINTF("kp.p_sigignore="
21131.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21141.94Skamil			    PRIx32 "\n",
21151.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21161.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21171.94Skamil
21181.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21191.94Skamil			    sizeof(kp_sigignore)));
21201.94Skamil		}
21211.94Skamil
21221.59Skamil		switch (sig) {
21231.59Skamil		case SIGTRAP:
21241.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21251.59Skamil			break;
21261.59Skamil		case SIGSEGV:
21271.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21281.59Skamil			break;
21291.71Skamil		case SIGILL:
21301.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
21311.71Skamil			break;
21321.59Skamil		case SIGFPE:
21331.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21341.59Skamil			break;
21351.59Skamil		case SIGBUS:
21361.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21371.59Skamil			break;
21381.59Skamil		}
21391.59Skamil
21401.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21411.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21421.93Skamil		FORKEE_REQUIRE_SUCCESS(
21431.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21441.59Skamil
21451.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21461.59Skamil
21471.71Skamil		/* Inform parent that tracer is exiting normally */
21481.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21491.71Skamil
21501.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21511.59Skamil		_exit(0 /* collect by initproc */);
21521.59Skamil	}
21531.59Skamil
21541.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21551.59Skamil	    "calling %s()\n", TWAIT_FNAME);
21561.59Skamil	TWAIT_REQUIRE_SUCCESS(
21571.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21581.59Skamil
21591.59Skamil	validate_status_exited(status, exitval);
21601.59Skamil
21611.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
21621.59Skamil	    TWAIT_FNAME);
21631.59Skamil	TWAIT_REQUIRE_SUCCESS(
21641.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
21651.59Skamil
21661.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
21671.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
21681.59Skamil
21691.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
21701.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
21711.59Skamil
21721.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
21731.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
21741.59Skamil
21751.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
21761.59Skamil	    TWAIT_FNAME);
21771.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21781.59Skamil
21791.59Skamil	validate_status_signaled(status, SIGKILL, 0);
21801.59Skamil
21811.71Skamil	DPRINTF("Await normal exit of tracer\n");
21821.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
21831.71Skamil
21841.59Skamil	msg_close(&parent_tracer);
21851.59Skamil	msg_close(&parent_tracee);
21861.59Skamil}
21871.59Skamil
21881.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
21891.61SkreATF_TC(test);								\
21901.61SkreATF_TC_HEAD(test, tc)							\
21911.61Skre{									\
21921.61Skre	atf_tc_set_md_var(tc, "descr",					\
21931.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
21941.94Skamil	    "the debuggee");						\
21951.61Skre}									\
21961.61Skre									\
21971.61SkreATF_TC_BODY(test, tc)							\
21981.61Skre{									\
21991.61Skre									\
22001.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
22011.59Skamil}
22021.59Skamil
22031.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
22041.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
22051.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
22061.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
22071.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22081.94Skamil
22091.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22101.94SkamilATF_TC(test);								\
22111.94SkamilATF_TC_HEAD(test, tc)							\
22121.94Skamil{									\
22131.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22141.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22151.94Skamil	    "the debuggee with masked signal");				\
22161.94Skamil}									\
22171.94Skamil									\
22181.94SkamilATF_TC_BODY(test, tc)							\
22191.94Skamil{									\
22201.94Skamil									\
22211.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22221.94Skamil}
22231.94Skamil
22241.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22251.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22261.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22271.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22281.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22291.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22301.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22311.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22321.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22331.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22341.94Skamil
22351.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22361.94SkamilATF_TC(test);								\
22371.94SkamilATF_TC_HEAD(test, tc)							\
22381.94Skamil{									\
22391.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22401.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22411.94Skamil	    "the debuggee with signal ignored");			\
22421.94Skamil}									\
22431.94Skamil									\
22441.94SkamilATF_TC_BODY(test, tc)							\
22451.94Skamil{									\
22461.94Skamil									\
22471.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22481.94Skamil}
22491.94Skamil
22501.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22511.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22521.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22531.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22541.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22551.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
22561.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22571.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
22581.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22591.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
22601.59Skamil#endif
22611.59Skamil
22621.59Skamil/// ----------------------------------------------------------------------------
22631.59Skamil
22641.59Skamil#if defined(TWAIT_HAVE_PID)
22651.59Skamilstatic void
22661.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
22671.67Skamil                                             bool stopped)
22681.1Skamil{
22691.51Skamil	/*
22701.51Skamil	 * notimeout - disable timeout in await zombie function
22711.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
22721.67Skamil	 * stopped - attach to a stopped process
22731.51Skamil	 */
22741.1Skamil
22751.1Skamil	struct msg_fds parent_tracee, parent_tracer;
22761.1Skamil	const int exitval_tracee = 5;
22771.1Skamil	const int exitval_tracer = 10;
22781.1Skamil	pid_t tracee, tracer, wpid;
22791.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
22801.1Skamil#if defined(TWAIT_HAVE_STATUS)
22811.1Skamil	int status;
22821.1Skamil#endif
22831.1Skamil
22841.67Skamil	/*
22851.67Skamil	 * Only a subset of options are supported.
22861.67Skamil	 */
22871.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
22881.67Skamil	            (!notimeout && unrelated && !stopped) ||
22891.67Skamil	            (notimeout && !unrelated && !stopped) ||
22901.67Skamil	            (!notimeout && unrelated && stopped));
22911.67Skamil
22921.13Schristos	DPRINTF("Spawn tracee\n");
22931.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
22941.1Skamil	tracee = atf_utils_fork();
22951.1Skamil	if (tracee == 0) {
22961.67Skamil		if (stopped) {
22971.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
22981.67Skamil			raise(SIGSTOP);
22991.67Skamil		}
23001.67Skamil
23011.1Skamil		// Wait for parent to let us exit
23021.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
23031.1Skamil		_exit(exitval_tracee);
23041.1Skamil	}
23051.1Skamil
23061.13Schristos	DPRINTF("Spawn debugger\n");
23071.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23081.1Skamil	tracer = atf_utils_fork();
23091.1Skamil	if (tracer == 0) {
23101.51Skamil		if(unrelated) {
23111.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23121.51Skamil			tracer = atf_utils_fork();
23131.51Skamil			if (tracer != 0)
23141.51Skamil				_exit(exitval_tracer);
23151.51Skamil		}
23161.51Skamil
23171.67Skamil		if (stopped) {
23181.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23191.67Skamil			await_stopped(tracee);
23201.67Skamil		}
23211.67Skamil
23221.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23231.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23241.1Skamil
23251.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23261.1Skamil		FORKEE_REQUIRE_SUCCESS(
23271.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23281.1Skamil
23291.1Skamil		forkee_status_stopped(status, SIGSTOP);
23301.1Skamil
23311.1Skamil		/* Resume tracee with PT_CONTINUE */
23321.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23331.1Skamil
23341.1Skamil		/* Inform parent that tracer has attached to tracee */
23351.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23361.1Skamil
23371.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23381.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23391.1Skamil
23401.1Skamil		/* Wait for tracee and assert that it exited */
23411.1Skamil		FORKEE_REQUIRE_SUCCESS(
23421.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23431.1Skamil
23441.1Skamil		forkee_status_exited(status, exitval_tracee);
23451.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23461.1Skamil
23471.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23481.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23491.51Skamil	}
23501.51Skamil
23511.51Skamil	if (unrelated) {
23521.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23531.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23541.51Skamil		TWAIT_REQUIRE_SUCCESS(
23551.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23561.51Skamil
23571.51Skamil		validate_status_exited(status, exitval_tracer);
23581.51Skamil
23591.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
23601.51Skamil		    TWAIT_FNAME);
23611.51Skamil		TWAIT_REQUIRE_SUCCESS(
23621.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
23631.1Skamil	}
23641.1Skamil
23651.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
23661.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
23671.1Skamil
23681.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
23691.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
23701.1Skamil
23711.13Schristos	DPRINTF("Detect that tracee is zombie\n");
23721.51Skamil	if (notimeout)
23731.26Skamil		await_zombie_raw(tracee, 0);
23741.26Skamil	else
23751.26Skamil		await_zombie(tracee);
23761.1Skamil
23771.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
23781.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
23791.1Skamil	    TWAIT_FNAME);
23801.1Skamil	TWAIT_REQUIRE_SUCCESS(
23811.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
23821.1Skamil
23831.51Skamil	if (unrelated) {
23841.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
23851.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
23861.51Skamil	} else {
23871.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
23881.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
23891.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
23901.59Skamil			"%s()\n", TWAIT_FNAME);
23911.51Skamil
23921.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
23931.59Skamil			"tracee\n");
23941.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
23951.51Skamil		    tracer);
23961.1Skamil
23971.51Skamil		validate_status_exited(status, exitval_tracer);
23981.51Skamil	}
23991.1Skamil
24001.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
24011.1Skamil	    TWAIT_FNAME);
24021.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
24031.1Skamil
24041.1Skamil	validate_status_exited(status, exitval_tracee);
24051.1Skamil
24061.1Skamil	msg_close(&parent_tracer);
24071.1Skamil	msg_close(&parent_tracee);
24081.1Skamil}
24091.26Skamil
24101.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24111.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24121.51Skamil{
24131.51Skamil	atf_tc_set_md_var(tc, "descr",
24141.51Skamil	    "Assert that tracer sees process termination before the parent");
24151.51Skamil}
24161.51Skamil
24171.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24181.26Skamil{
24191.26Skamil
24201.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24211.26Skamil}
24221.26Skamil
24231.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24241.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24251.1Skamil{
24261.1Skamil	atf_tc_set_md_var(tc, "descr",
24271.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24281.51Skamil	    "process and no other error is reported");
24291.1Skamil}
24301.1Skamil
24311.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24321.1Skamil{
24331.51Skamil	time_t start, end;
24341.51Skamil	double diff;
24351.51Skamil	unsigned long N = 0;
24361.1Skamil
24371.51Skamil	/*
24381.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24391.51Skamil	 * This test body isn't specific to this race, however it's just good
24401.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24411.51Skamil	 */
24421.1Skamil
24431.51Skamil	start = time(NULL);
24441.51Skamil	while (true) {
24451.51Skamil		DPRINTF("Step: %lu\n", N);
24461.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24471.67Skamil		                                             false);
24481.51Skamil		end = time(NULL);
24491.51Skamil		diff = difftime(end, start);
24501.51Skamil		if (diff >= 5.0)
24511.51Skamil			break;
24521.51Skamil		++N;
24531.1Skamil	}
24541.51Skamil	DPRINTF("Iterations: %lu\n", N);
24551.51Skamil}
24561.1Skamil
24571.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
24581.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24591.51Skamil{
24601.51Skamil	atf_tc_set_md_var(tc, "descr",
24611.51Skamil	    "Assert that tracer sees process termination before the parent");
24621.51Skamil}
24631.1Skamil
24641.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24651.51Skamil{
24661.1Skamil
24671.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
24681.67Skamil}
24691.67Skamil
24701.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
24711.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
24721.67Skamil{
24731.67Skamil	atf_tc_set_md_var(tc, "descr",
24741.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
24751.67Skamil}
24761.67Skamil
24771.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
24781.67Skamil{
24791.67Skamil
24801.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
24811.1Skamil}
24821.1Skamil#endif
24831.1Skamil
24841.51Skamil/// ----------------------------------------------------------------------------
24851.51Skamil
24861.66Skamilstatic void
24871.66Skamilparent_attach_to_its_child(bool stopped)
24881.1Skamil{
24891.1Skamil	struct msg_fds parent_tracee;
24901.1Skamil	const int exitval_tracee = 5;
24911.1Skamil	pid_t tracee, wpid;
24921.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
24931.1Skamil#if defined(TWAIT_HAVE_STATUS)
24941.1Skamil	int status;
24951.1Skamil#endif
24961.1Skamil
24971.13Schristos	DPRINTF("Spawn tracee\n");
24981.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
24991.1Skamil	tracee = atf_utils_fork();
25001.1Skamil	if (tracee == 0) {
25011.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25021.13Schristos		DPRINTF("Parent should now attach to tracee\n");
25031.1Skamil
25041.66Skamil		if (stopped) {
25051.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
25061.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
25071.66Skamil		}
25081.66Skamil
25091.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25101.1Skamil		/* Wait for message from the parent */
25111.1Skamil		_exit(exitval_tracee);
25121.1Skamil	}
25131.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25141.57Skamil
25151.66Skamil	if (stopped) {
25161.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25171.66Skamil		await_stopped(tracee);
25181.66Skamil	}
25191.66Skamil
25201.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25221.1Skamil
25231.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25241.1Skamil	    TWAIT_FNAME);
25251.1Skamil	TWAIT_REQUIRE_SUCCESS(
25261.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25271.1Skamil
25281.1Skamil	validate_status_stopped(status, SIGSTOP);
25291.1Skamil
25301.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25321.1Skamil
25331.13Schristos	DPRINTF("Let the tracee exit now\n");
25341.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25351.1Skamil
25361.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25371.1Skamil	TWAIT_REQUIRE_SUCCESS(
25381.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25391.1Skamil
25401.1Skamil	validate_status_exited(status, exitval_tracee);
25411.1Skamil
25421.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25441.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25451.1Skamil
25461.1Skamil	msg_close(&parent_tracee);
25471.1Skamil}
25481.1Skamil
25491.66SkamilATF_TC(parent_attach_to_its_child);
25501.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25511.66Skamil{
25521.66Skamil	atf_tc_set_md_var(tc, "descr",
25531.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25541.66Skamil}
25551.66Skamil
25561.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
25571.66Skamil{
25581.66Skamil
25591.66Skamil	parent_attach_to_its_child(false);
25601.66Skamil}
25611.66Skamil
25621.66SkamilATF_TC(parent_attach_to_its_stopped_child);
25631.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
25641.66Skamil{
25651.66Skamil	atf_tc_set_md_var(tc, "descr",
25661.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
25671.66Skamil}
25681.66Skamil
25691.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
25701.66Skamil{
25711.66Skamil
25721.66Skamil	parent_attach_to_its_child(true);
25731.66Skamil}
25741.66Skamil
25751.51Skamil/// ----------------------------------------------------------------------------
25761.51Skamil
25771.65Skamilstatic void
25781.65Skamilchild_attach_to_its_parent(bool stopped)
25791.1Skamil{
25801.1Skamil	struct msg_fds parent_tracee;
25811.1Skamil	const int exitval_tracer = 5;
25821.1Skamil	pid_t tracer, wpid;
25831.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25841.1Skamil#if defined(TWAIT_HAVE_STATUS)
25851.1Skamil	int status;
25861.1Skamil#endif
25871.1Skamil
25881.13Schristos	DPRINTF("Spawn tracer\n");
25891.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25901.1Skamil	tracer = atf_utils_fork();
25911.1Skamil	if (tracer == 0) {
25921.1Skamil		/* Wait for message from the parent */
25931.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25941.1Skamil
25951.65Skamil		if (stopped) {
25961.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
25971.65Skamil			        getppid());
25981.65Skamil			await_stopped(getppid());
25991.65Skamil		}
26001.65Skamil
26011.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
26021.1Skamil		    getppid());
26031.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
26041.1Skamil
26051.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
26061.1Skamil		    TWAIT_FNAME);
26071.1Skamil		FORKEE_REQUIRE_SUCCESS(
26081.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26091.1Skamil
26101.1Skamil		forkee_status_stopped(status, SIGSTOP);
26111.1Skamil
26121.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26131.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26141.1Skamil		    != -1);
26151.1Skamil
26161.1Skamil		/* Tell parent we are ready */
26171.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26181.1Skamil
26191.1Skamil		_exit(exitval_tracer);
26201.1Skamil	}
26211.1Skamil
26221.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26231.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26241.65Skamil
26251.65Skamil	if (stopped) {
26261.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26271.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26281.65Skamil	}
26291.65Skamil
26301.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26311.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26321.1Skamil
26331.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26341.1Skamil	TWAIT_REQUIRE_SUCCESS(
26351.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26361.1Skamil
26371.1Skamil	validate_status_exited(status, exitval_tracer);
26381.1Skamil
26391.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26411.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26421.1Skamil
26431.1Skamil	msg_close(&parent_tracee);
26441.1Skamil}
26451.1Skamil
26461.65SkamilATF_TC(child_attach_to_its_parent);
26471.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26481.65Skamil{
26491.65Skamil	atf_tc_set_md_var(tc, "descr",
26501.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26511.65Skamil}
26521.65Skamil
26531.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26541.65Skamil{
26551.65Skamil
26561.65Skamil	child_attach_to_its_parent(false);
26571.65Skamil}
26581.65Skamil
26591.65SkamilATF_TC(child_attach_to_its_stopped_parent);
26601.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
26611.65Skamil{
26621.65Skamil	atf_tc_set_md_var(tc, "descr",
26631.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
26641.65Skamil}
26651.65Skamil
26661.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
26671.65Skamil{
26681.65Skamil	/*
26691.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
26701.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
26711.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
26721.65Skamil	 *
26731.65Skamil	 * As a workaround spawn this test as a subprocess.
26741.65Skamil	 */
26751.65Skamil
26761.65Skamil	const int exitval = 15;
26771.65Skamil	pid_t child, wpid;
26781.65Skamil#if defined(TWAIT_HAVE_STATUS)
26791.65Skamil	int status;
26801.65Skamil#endif
26811.65Skamil
26821.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
26831.65Skamil	if (child == 0) {
26841.65Skamil		child_attach_to_its_parent(true);
26851.65Skamil		_exit(exitval);
26861.65Skamil	} else {
26871.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26881.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26891.65Skamil
26901.65Skamil		validate_status_exited(status, exitval);
26911.65Skamil
26921.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
26931.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26941.65Skamil	}
26951.65Skamil}
26961.65Skamil
26971.51Skamil/// ----------------------------------------------------------------------------
26981.51Skamil
26991.1Skamil#if defined(TWAIT_HAVE_PID)
27001.1Skamil
27011.51Skamilenum tracee_sees_its_original_parent_type {
27021.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
27031.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
27041.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
27051.51Skamil};
27061.51Skamil
27071.51Skamilstatic void
27081.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27091.1Skamil{
27101.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27111.1Skamil	const int exitval_tracee = 5;
27121.1Skamil	const int exitval_tracer = 10;
27131.1Skamil	pid_t parent, tracee, tracer, wpid;
27141.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27151.1Skamil#if defined(TWAIT_HAVE_STATUS)
27161.1Skamil	int status;
27171.1Skamil#endif
27181.51Skamil	/* sysctl(3) - kinfo_proc2 */
27191.51Skamil	int name[CTL_MAXNAME];
27201.51Skamil	struct kinfo_proc2 kp;
27211.51Skamil	size_t len = sizeof(kp);
27221.51Skamil	unsigned int namelen;
27231.51Skamil
27241.51Skamil	/* procfs - status  */
27251.51Skamil	FILE *fp;
27261.51Skamil	struct stat st;
27271.51Skamil	const char *fname = "/proc/curproc/status";
27281.51Skamil	char s_executable[MAXPATHLEN];
27291.51Skamil	int s_pid, s_ppid;
27301.51Skamil	int rv;
27311.51Skamil
27321.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27331.61Skre		SYSCALL_REQUIRE(
27341.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27351.61Skre		if (rv != 0)
27361.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27371.51Skamil	}
27381.1Skamil
27391.13Schristos	DPRINTF("Spawn tracee\n");
27401.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27411.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27421.1Skamil	tracee = atf_utils_fork();
27431.1Skamil	if (tracee == 0) {
27441.1Skamil		parent = getppid();
27451.1Skamil
27461.1Skamil		/* Emit message to the parent */
27471.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27481.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27491.1Skamil
27501.51Skamil		switch (type) {
27511.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27521.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27531.51Skamil			break;
27541.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27551.51Skamil			namelen = 0;
27561.51Skamil			name[namelen++] = CTL_KERN;
27571.51Skamil			name[namelen++] = KERN_PROC2;
27581.51Skamil			name[namelen++] = KERN_PROC_PID;
27591.51Skamil			name[namelen++] = getpid();
27601.51Skamil			name[namelen++] = len;
27611.51Skamil			name[namelen++] = 1;
27621.51Skamil
27631.61Skre			FORKEE_ASSERT_EQ(
27641.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
27651.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
27661.51Skamil			break;
27671.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
27681.51Skamil			/*
27691.51Skamil			 * Format:
27701.51Skamil			 *  EXECUTABLE PID PPID ...
27711.51Skamil			 */
27721.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
27731.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
27741.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
27751.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
27761.51Skamil			break;
27771.51Skamil		}
27781.1Skamil
27791.1Skamil		_exit(exitval_tracee);
27801.1Skamil	}
27811.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
27821.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
27831.1Skamil
27841.13Schristos	DPRINTF("Spawn debugger\n");
27851.1Skamil	tracer = atf_utils_fork();
27861.1Skamil	if (tracer == 0) {
27871.1Skamil		/* No IPC to communicate with the child */
27881.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
27891.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
27901.1Skamil
27911.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
27921.1Skamil		FORKEE_REQUIRE_SUCCESS(
27931.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
27941.1Skamil
27951.1Skamil		forkee_status_stopped(status, SIGSTOP);
27961.1Skamil
27971.1Skamil		/* Resume tracee with PT_CONTINUE */
27981.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
27991.1Skamil
28001.1Skamil		/* Inform parent that tracer has attached to tracee */
28011.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
28021.1Skamil
28031.1Skamil		/* Wait for parent to tell use that tracee should have exited */
28041.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
28051.1Skamil
28061.1Skamil		/* Wait for tracee and assert that it exited */
28071.1Skamil		FORKEE_REQUIRE_SUCCESS(
28081.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28091.1Skamil
28101.1Skamil		forkee_status_exited(status, exitval_tracee);
28111.1Skamil
28121.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28131.1Skamil		_exit(exitval_tracer);
28141.1Skamil	}
28151.1Skamil
28161.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28171.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28181.1Skamil
28191.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28201.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28211.1Skamil
28221.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28231.1Skamil	await_zombie(tracee);
28241.1Skamil
28251.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28261.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28271.1Skamil	TWAIT_REQUIRE_SUCCESS(
28281.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28291.1Skamil
28301.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28311.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28321.1Skamil
28331.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28351.1Skamil	    tracer);
28361.1Skamil
28371.1Skamil	validate_status_exited(status, exitval_tracer);
28381.1Skamil
28391.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28401.1Skamil	    TWAIT_FNAME);
28411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28421.1Skamil	    tracee);
28431.1Skamil
28441.1Skamil	validate_status_exited(status, exitval_tracee);
28451.1Skamil
28461.1Skamil	msg_close(&parent_tracer);
28471.1Skamil	msg_close(&parent_tracee);
28481.1Skamil}
28491.1Skamil
28501.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28511.61SkreATF_TC(test);								\
28521.61SkreATF_TC_HEAD(test, tc)							\
28531.61Skre{									\
28541.61Skre	atf_tc_set_md_var(tc, "descr",					\
28551.61Skre	    "Assert that tracee sees its original parent when being traced " \
28561.61Skre	    "(check " descr ")");					\
28571.61Skre}									\
28581.61Skre									\
28591.61SkreATF_TC_BODY(test, tc)							\
28601.61Skre{									\
28611.61Skre									\
28621.61Skre	tracee_sees_its_original_parent(type);				\
28631.1Skamil}
28641.1Skamil
28651.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28661.51Skamil	tracee_sees_its_original_parent_getppid,
28671.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
28681.51Skamil	"getppid(2)");
28691.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28701.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
28711.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
28721.51Skamil	"sysctl(3) and kinfo_proc2");
28731.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28741.51Skamil	tracee_sees_its_original_parent_procfs_status,
28751.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
28761.51Skamil	"the status file in procfs");
28771.1Skamil#endif
28781.1Skamil
28791.51Skamil/// ----------------------------------------------------------------------------
28801.1Skamil
28811.53Skamilstatic void
28821.53Skamileventmask_preserved(int event)
28831.1Skamil{
28841.1Skamil	const int exitval = 5;
28851.1Skamil	const int sigval = SIGSTOP;
28861.1Skamil	pid_t child, wpid;
28871.1Skamil#if defined(TWAIT_HAVE_STATUS)
28881.1Skamil	int status;
28891.1Skamil#endif
28901.1Skamil	ptrace_event_t set_event, get_event;
28911.1Skamil	const int len = sizeof(ptrace_event_t);
28921.1Skamil
28931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28951.1Skamil	if (child == 0) {
28961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28981.1Skamil
28991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29011.1Skamil
29021.13Schristos		DPRINTF("Before exiting of the child process\n");
29031.1Skamil		_exit(exitval);
29041.1Skamil	}
29051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29061.1Skamil
29071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29091.1Skamil
29101.1Skamil	validate_status_stopped(status, sigval);
29111.1Skamil
29121.53Skamil	set_event.pe_set_event = event;
29131.61Skre	SYSCALL_REQUIRE(
29141.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29151.61Skre	SYSCALL_REQUIRE(
29161.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29171.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29181.1Skamil
29191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29201.1Skamil	    "without signal to be sent\n");
29211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29221.1Skamil
29231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29251.1Skamil
29261.1Skamil	validate_status_exited(status, exitval);
29271.1Skamil
29281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29301.1Skamil}
29311.1Skamil
29321.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29331.61SkreATF_TC(test);								\
29341.61SkreATF_TC_HEAD(test, tc)							\
29351.61Skre{									\
29361.61Skre	atf_tc_set_md_var(tc, "descr",					\
29371.61Skre	    "Verify that eventmask " #event " is preserved");		\
29381.61Skre}									\
29391.61Skre									\
29401.61SkreATF_TC_BODY(test, tc)							\
29411.61Skre{									\
29421.61Skre									\
29431.61Skre	eventmask_preserved(event);					\
29441.1Skamil}
29451.1Skamil
29461.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29471.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29481.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29491.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29501.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29511.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29521.1Skamil
29531.53Skamil/// ----------------------------------------------------------------------------
29541.1Skamil
29551.28Skamilstatic void
29561.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
29571.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
29581.1Skamil{
29591.1Skamil	const int exitval = 5;
29601.1Skamil	const int exitval2 = 15;
29611.1Skamil	const int sigval = SIGSTOP;
29621.31Skamil	pid_t child, child2 = 0, wpid;
29631.1Skamil#if defined(TWAIT_HAVE_STATUS)
29641.1Skamil	int status;
29651.1Skamil#endif
29661.1Skamil	ptrace_state_t state;
29671.1Skamil	const int slen = sizeof(state);
29681.1Skamil	ptrace_event_t event;
29691.1Skamil	const int elen = sizeof(event);
29701.1Skamil
29711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29731.1Skamil	if (child == 0) {
29741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29761.1Skamil
29771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29791.1Skamil
29801.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
29811.1Skamil
29821.1Skamil		if (child2 == 0)
29831.1Skamil			_exit(exitval2);
29841.1Skamil
29851.1Skamil		FORKEE_REQUIRE_SUCCESS
29861.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
29871.1Skamil
29881.1Skamil		forkee_status_exited(status, exitval2);
29891.1Skamil
29901.13Schristos		DPRINTF("Before exiting of the child process\n");
29911.1Skamil		_exit(exitval);
29921.1Skamil	}
29931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29941.1Skamil
29951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29971.1Skamil
29981.1Skamil	validate_status_stopped(status, sigval);
29991.1Skamil
30001.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
30011.61Skre	    trackfork ? "|PTRACE_FORK" : "",
30021.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
30031.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
30041.30Skamil	event.pe_set_event = 0;
30051.30Skamil	if (trackfork)
30061.30Skamil		event.pe_set_event |= PTRACE_FORK;
30071.30Skamil	if (trackvfork)
30081.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30091.30Skamil	if (trackvforkdone)
30101.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30121.1Skamil
30131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30141.1Skamil	    "without signal to be sent\n");
30151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30161.1Skamil
30171.29Skamil#if defined(TWAIT_HAVE_PID)
30181.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30191.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30201.61Skre		    child);
30211.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30221.61Skre		    child);
30231.1Skamil
30241.29Skamil		validate_status_stopped(status, SIGTRAP);
30251.1Skamil
30261.61Skre		SYSCALL_REQUIRE(
30271.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30281.31Skamil		if (trackfork && fn == fork) {
30291.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30301.30Skamil			       PTRACE_FORK);
30311.30Skamil		}
30321.31Skamil		if (trackvfork && fn == vfork) {
30331.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30341.30Skamil			       PTRACE_VFORK);
30351.30Skamil		}
30361.29Skamil
30371.29Skamil		child2 = state.pe_other_pid;
30381.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
30391.29Skamil
30401.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
30411.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
30421.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
30431.29Skamil		    child2);
30441.1Skamil
30451.29Skamil		validate_status_stopped(status, SIGTRAP);
30461.1Skamil
30471.61Skre		SYSCALL_REQUIRE(
30481.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
30491.31Skamil		if (trackfork && fn == fork) {
30501.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30511.30Skamil			       PTRACE_FORK);
30521.30Skamil		}
30531.31Skamil		if (trackvfork && fn == vfork) {
30541.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30551.30Skamil			       PTRACE_VFORK);
30561.30Skamil		}
30571.30Skamil
30581.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
30591.29Skamil
30601.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
30611.29Skamil		    "and without signal to be sent\n");
30621.61Skre		SYSCALL_REQUIRE(
30631.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
30641.29Skamil
30651.29Skamil		DPRINTF("Before resuming the child process where it left off "
30661.61Skre		    "and without signal to be sent\n");
30671.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30681.30Skamil	}
30691.30Skamil#endif
30701.30Skamil
30711.31Skamil	if (trackvforkdone && fn == vfork) {
30721.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30731.61Skre		    child);
30741.61Skre		TWAIT_REQUIRE_SUCCESS(
30751.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
30761.30Skamil
30771.30Skamil		validate_status_stopped(status, SIGTRAP);
30781.30Skamil
30791.61Skre		SYSCALL_REQUIRE(
30801.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30811.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
30821.30Skamil
30831.30Skamil		child2 = state.pe_other_pid;
30841.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
30851.61Skre		    child2);
30861.30Skamil
30871.30Skamil		DPRINTF("Before resuming the child process where it left off "
30881.61Skre		    "and without signal to be sent\n");
30891.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30901.30Skamil	}
30911.29Skamil
30921.30Skamil#if defined(TWAIT_HAVE_PID)
30931.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30941.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
30951.61Skre		    "\n", TWAIT_FNAME);
30961.61Skre		TWAIT_REQUIRE_SUCCESS(
30971.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30981.29Skamil
30991.29Skamil		validate_status_exited(status, exitval2);
31001.29Skamil
31011.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
31021.61Skre		    "process\n", TWAIT_FNAME);
31031.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
31041.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
31051.29Skamil	}
31061.29Skamil#endif
31071.1Skamil
31081.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31091.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31111.1Skamil
31121.1Skamil	validate_status_stopped(status, SIGCHLD);
31131.1Skamil
31141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31151.1Skamil	    "without signal to be sent\n");
31161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31171.1Skamil
31181.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31191.1Skamil	    TWAIT_FNAME);
31201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31211.1Skamil
31221.1Skamil	validate_status_exited(status, exitval);
31231.1Skamil
31241.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31251.1Skamil	    TWAIT_FNAME);
31261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31271.1Skamil}
31281.28Skamil
31291.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
31301.61SkreATF_TC(name);								\
31311.61SkreATF_TC_HEAD(name, tc)							\
31321.61Skre{									\
31331.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
31341.61Skre}									\
31351.61Skre									\
31361.61SkreATF_TC_BODY(name, tc)							\
31371.61Skre{									\
31381.61Skre									\
31391.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
31401.32Skamil}
31411.32Skamil
31421.32Skamil#define F false
31431.32Skamil#define T true
31441.32Skamil
31451.32Skamil#define F_IF__0(x)
31461.32Skamil#define F_IF__1(x) x
31471.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
31481.32Skamil#define F_IF_(x,y) F_IF__(x,y)
31491.32Skamil#define F_IF(x,y) F_IF_(x,y)
31501.32Skamil
31511.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
31521.61Skre	"Verify " #function "(2) called with 0"				\
31531.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
31541.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
31551.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
31561.61Skre	" in EVENT_MASK."						\
31571.61Skre	F_IF(dchildbit," Detach child in this test.")			\
31581.61Skre	F_IF(dparentbit," Detach parent in this test.")
31591.1Skamil
31601.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
31611.31Skamil#if defined(TWAIT_HAVE_PID)
31621.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
31631.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
31641.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
31651.31Skamil#endif
31661.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
31671.31Skamil#if defined(TWAIT_HAVE_PID)
31681.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
31691.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
31701.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
31711.31Skamil#endif
31721.1Skamil
31731.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
31741.31Skamil#if defined(TWAIT_HAVE_PID)
31751.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
31761.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
31771.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
31781.31Skamil#endif
31791.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
31801.31Skamil#if defined(TWAIT_HAVE_PID)
31811.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
31821.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
31831.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
31841.31Skamil#endif
31851.31Skamil
31861.54Skamil/// ----------------------------------------------------------------------------
31871.31Skamil
31881.54Skamilenum bytes_transfer_type {
31891.54Skamil	BYTES_TRANSFER_DATA,
31901.54Skamil	BYTES_TRANSFER_DATAIO,
31911.54Skamil	BYTES_TRANSFER_TEXT,
31921.54Skamil	BYTES_TRANSFER_TEXTIO,
31931.54Skamil	BYTES_TRANSFER_AUXV
31941.54Skamil};
31951.31Skamil
31961.54Skamilstatic int __used
31971.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
31981.54Skamil{
31991.54Skamil	int e, f, g, h;
32001.1Skamil
32011.54Skamil	a *= 4;
32021.54Skamil	b += 3;
32031.54Skamil	c -= 2;
32041.54Skamil	d /= 1;
32051.1Skamil
32061.54Skamil	e = strtol("10", NULL, 10);
32071.54Skamil	f = strtol("20", NULL, 10);
32081.54Skamil	g = strtol("30", NULL, 10);
32091.54Skamil	h = strtol("40", NULL, 10);
32101.1Skamil
32111.54Skamil	return (a + b * c - d) + (e * f - g / h);
32121.1Skamil}
32131.1Skamil
32141.54Skamilstatic void
32151.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
32161.1Skamil{
32171.1Skamil	const int exitval = 5;
32181.1Skamil	const int sigval = SIGSTOP;
32191.1Skamil	pid_t child, wpid;
32201.54Skamil	bool skip = false;
32211.1Skamil
32221.54Skamil	int lookup_me = 0;
32231.54Skamil	uint8_t lookup_me8 = 0;
32241.54Skamil	uint16_t lookup_me16 = 0;
32251.54Skamil	uint32_t lookup_me32 = 0;
32261.54Skamil	uint64_t lookup_me64 = 0;
32271.1Skamil
32281.54Skamil	int magic = 0x13579246;
32291.54Skamil	uint8_t magic8 = 0xab;
32301.54Skamil	uint16_t magic16 = 0x1234;
32311.54Skamil	uint32_t magic32 = 0x98765432;
32321.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
32331.1Skamil
32341.54Skamil	struct ptrace_io_desc io;
32351.1Skamil#if defined(TWAIT_HAVE_STATUS)
32361.1Skamil	int status;
32371.1Skamil#endif
32381.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
32391.60Skre	AuxInfo ai[513], *aip;
32401.55Schristos
32411.55Schristos	ATF_REQUIRE(size < sizeof(ai));
32421.1Skamil
32431.54Skamil	/* Prepare variables for .TEXT transfers */
32441.54Skamil	switch (type) {
32451.54Skamil	case BYTES_TRANSFER_TEXT:
32461.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
32471.54Skamil		break;
32481.54Skamil	case BYTES_TRANSFER_TEXTIO:
32491.54Skamil		switch (size) {
32501.54Skamil		case 8:
32511.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
32521.54Skamil			break;
32531.54Skamil		case 16:
32541.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
32551.54Skamil			break;
32561.54Skamil		case 32:
32571.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
32581.54Skamil			break;
32591.54Skamil		case 64:
32601.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
32611.54Skamil			break;
32621.54Skamil		}
32631.54Skamil		break;
32641.54Skamil	default:
32651.54Skamil		break;
32661.54Skamil	}
32671.1Skamil
32681.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
32691.54Skamil	switch (type) {
32701.54Skamil	case BYTES_TRANSFER_TEXTIO:
32711.54Skamil	case BYTES_TRANSFER_DATAIO:
32721.54Skamil		io.piod_op = operation;
32731.54Skamil		switch (size) {
32741.54Skamil		case 8:
32751.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
32761.54Skamil			               (void *)bytes_transfer_dummy :
32771.54Skamil			               &lookup_me8;
32781.54Skamil			io.piod_addr = &lookup_me8;
32791.54Skamil			io.piod_len = sizeof(lookup_me8);
32801.54Skamil			break;
32811.54Skamil		case 16:
32821.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
32831.54Skamil			               (void *)bytes_transfer_dummy :
32841.54Skamil			               &lookup_me16;
32851.54Skamil			io.piod_addr = &lookup_me16;
32861.54Skamil			io.piod_len = sizeof(lookup_me16);
32871.54Skamil			break;
32881.54Skamil		case 32:
32891.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
32901.54Skamil			               (void *)bytes_transfer_dummy :
32911.54Skamil			               &lookup_me32;
32921.54Skamil			io.piod_addr = &lookup_me32;
32931.54Skamil			io.piod_len = sizeof(lookup_me32);
32941.54Skamil			break;
32951.54Skamil		case 64:
32961.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
32971.54Skamil			               (void *)bytes_transfer_dummy :
32981.54Skamil			               &lookup_me64;
32991.54Skamil			io.piod_addr = &lookup_me64;
33001.54Skamil			io.piod_len = sizeof(lookup_me64);
33011.54Skamil			break;
33021.54Skamil		default:
33031.54Skamil			break;
33041.54Skamil		}
33051.54Skamil		break;
33061.54Skamil	case BYTES_TRANSFER_AUXV:
33071.54Skamil		io.piod_op = operation;
33081.54Skamil		io.piod_offs = 0;
33091.54Skamil		io.piod_addr = ai;
33101.54Skamil		io.piod_len = size;
33111.54Skamil		break;
33121.54Skamil	default:
33131.54Skamil		break;
33141.1Skamil	}
33151.1Skamil
33161.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33171.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33181.1Skamil	if (child == 0) {
33191.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33201.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33211.1Skamil
33221.54Skamil		switch (type) {
33231.54Skamil		case BYTES_TRANSFER_DATA:
33241.54Skamil			switch (operation) {
33251.54Skamil			case PT_READ_D:
33261.54Skamil			case PT_READ_I:
33271.54Skamil				lookup_me = magic;
33281.54Skamil				break;
33291.54Skamil			default:
33301.54Skamil				break;
33311.54Skamil			}
33321.54Skamil			break;
33331.54Skamil		case BYTES_TRANSFER_DATAIO:
33341.54Skamil			switch (operation) {
33351.54Skamil			case PIOD_READ_D:
33361.54Skamil			case PIOD_READ_I:
33371.54Skamil				switch (size) {
33381.54Skamil				case 8:
33391.54Skamil					lookup_me8 = magic8;
33401.54Skamil					break;
33411.54Skamil				case 16:
33421.54Skamil					lookup_me16 = magic16;
33431.54Skamil					break;
33441.54Skamil				case 32:
33451.54Skamil					lookup_me32 = magic32;
33461.54Skamil					break;
33471.54Skamil				case 64:
33481.54Skamil					lookup_me64 = magic64;
33491.54Skamil					break;
33501.54Skamil				default:
33511.54Skamil					break;
33521.54Skamil				}
33531.54Skamil				break;
33541.54Skamil			default:
33551.54Skamil				break;
33561.54Skamil			}
33571.54Skamil		default:
33581.54Skamil			break;
33591.54Skamil		}
33601.54Skamil
33611.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33621.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33631.1Skamil
33641.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
33651.54Skamil		switch (type) {
33661.54Skamil		case BYTES_TRANSFER_DATA:
33671.54Skamil			switch (operation) {
33681.54Skamil			case PT_WRITE_D:
33691.54Skamil			case PT_WRITE_I:
33701.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
33711.54Skamil				break;
33721.54Skamil			default:
33731.54Skamil				break;
33741.54Skamil			}
33751.54Skamil			break;
33761.54Skamil		case BYTES_TRANSFER_DATAIO:
33771.54Skamil			switch (operation) {
33781.54Skamil			case PIOD_WRITE_D:
33791.54Skamil			case PIOD_WRITE_I:
33801.54Skamil				switch (size) {
33811.54Skamil				case 8:
33821.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
33831.54Skamil					break;
33841.54Skamil				case 16:
33851.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
33861.54Skamil					break;
33871.54Skamil				case 32:
33881.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
33891.54Skamil					break;
33901.54Skamil				case 64:
33911.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
33921.54Skamil					break;
33931.54Skamil				default:
33941.54Skamil					break;
33951.54Skamil				}
33961.54Skamil				break;
33971.54Skamil			default:
33981.54Skamil				break;
33991.54Skamil			}
34001.54Skamil			break;
34011.54Skamil		case BYTES_TRANSFER_TEXT:
34021.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
34031.54Skamil			                     sizeof(magic)) == 0);
34041.54Skamil			break;
34051.54Skamil		case BYTES_TRANSFER_TEXTIO:
34061.54Skamil			switch (size) {
34071.54Skamil			case 8:
34081.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
34091.54Skamil				                     bytes_transfer_dummy,
34101.54Skamil				                     sizeof(magic8)) == 0);
34111.54Skamil				break;
34121.54Skamil			case 16:
34131.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
34141.54Skamil				                     bytes_transfer_dummy,
34151.54Skamil				                     sizeof(magic16)) == 0);
34161.54Skamil				break;
34171.54Skamil			case 32:
34181.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
34191.54Skamil				                     bytes_transfer_dummy,
34201.54Skamil				                     sizeof(magic32)) == 0);
34211.54Skamil				break;
34221.54Skamil			case 64:
34231.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
34241.54Skamil				                     bytes_transfer_dummy,
34251.54Skamil				                     sizeof(magic64)) == 0);
34261.54Skamil				break;
34271.54Skamil			}
34281.54Skamil			break;
34291.54Skamil		default:
34301.54Skamil			break;
34311.54Skamil		}
34321.54Skamil
34331.13Schristos		DPRINTF("Before exiting of the child process\n");
34341.1Skamil		_exit(exitval);
34351.1Skamil	}
34361.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34371.1Skamil
34381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34401.1Skamil
34411.1Skamil	validate_status_stopped(status, sigval);
34421.1Skamil
34431.54Skamil	/* Check PaX MPROTECT */
34441.54Skamil	if (!can_we_write_to_text(child)) {
34451.54Skamil		switch (type) {
34461.54Skamil		case BYTES_TRANSFER_TEXTIO:
34471.54Skamil			switch (operation) {
34481.54Skamil			case PIOD_WRITE_D:
34491.54Skamil			case PIOD_WRITE_I:
34501.54Skamil				skip = true;
34511.54Skamil				break;
34521.54Skamil			default:
34531.54Skamil				break;
34541.54Skamil			}
34551.54Skamil			break;
34561.54Skamil		case BYTES_TRANSFER_TEXT:
34571.54Skamil			switch (operation) {
34581.54Skamil			case PT_WRITE_D:
34591.54Skamil			case PT_WRITE_I:
34601.54Skamil				skip = true;
34611.54Skamil				break;
34621.54Skamil			default:
34631.54Skamil				break;
34641.54Skamil			}
34651.54Skamil			break;
34661.54Skamil		default:
34671.54Skamil			break;
34681.54Skamil		}
34691.54Skamil	}
34701.1Skamil
34711.54Skamil	/* Bailout cleanly killing the child process */
34721.54Skamil	if (skip) {
34731.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
34741.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34751.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
34761.54Skamil		                      child);
34771.1Skamil
34781.54Skamil		validate_status_signaled(status, SIGKILL, 0);
34791.1Skamil
34801.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
34811.54Skamil	}
34821.1Skamil
34831.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
34841.54Skamil	       "parent=%d\n", child, getpid());
34851.1Skamil
34861.54Skamil	switch (type) {
34871.54Skamil	case BYTES_TRANSFER_TEXTIO:
34881.54Skamil	case BYTES_TRANSFER_DATAIO:
34891.54Skamil	case BYTES_TRANSFER_AUXV:
34901.54Skamil		switch (operation) {
34911.54Skamil		case PIOD_WRITE_D:
34921.54Skamil		case PIOD_WRITE_I:
34931.54Skamil			switch (size) {
34941.54Skamil			case 8:
34951.54Skamil				lookup_me8 = magic8;
34961.54Skamil				break;
34971.54Skamil			case 16:
34981.54Skamil				lookup_me16 = magic16;
34991.54Skamil				break;
35001.54Skamil			case 32:
35011.54Skamil				lookup_me32 = magic32;
35021.54Skamil				break;
35031.54Skamil			case 64:
35041.54Skamil				lookup_me64 = magic64;
35051.54Skamil				break;
35061.54Skamil			default:
35071.54Skamil				break;
35081.54Skamil			}
35091.54Skamil			break;
35101.54Skamil		default:
35111.54Skamil			break;
35121.54Skamil		}
35131.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35141.54Skamil		switch (operation) {
35151.54Skamil		case PIOD_READ_D:
35161.54Skamil		case PIOD_READ_I:
35171.54Skamil			switch (size) {
35181.54Skamil			case 8:
35191.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
35201.54Skamil				break;
35211.54Skamil			case 16:
35221.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
35231.54Skamil				break;
35241.54Skamil			case 32:
35251.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
35261.54Skamil				break;
35271.54Skamil			case 64:
35281.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
35291.54Skamil				break;
35301.54Skamil			default:
35311.54Skamil				break;
35321.54Skamil			}
35331.54Skamil			break;
35341.54Skamil		case PIOD_READ_AUXV:
35351.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
35361.54Skamil			        io.piod_len);
35371.54Skamil			ATF_REQUIRE(io.piod_len > 0);
35381.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
35391.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
35401.54Skamil				    (long long int)aip->a_type,
35411.54Skamil				    (long long int)aip->a_v);
35421.54Skamil			break;
35431.54Skamil		default:
35441.54Skamil			break;
35451.54Skamil		}
35461.54Skamil		break;
35471.54Skamil	case BYTES_TRANSFER_TEXT:
35481.54Skamil		switch (operation) {
35491.54Skamil		case PT_READ_D:
35501.54Skamil		case PT_READ_I:
35511.54Skamil			errno = 0;
35521.54Skamil			lookup_me = ptrace(operation, child,
35531.54Skamil			                   bytes_transfer_dummy, 0);
35541.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
35551.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
35561.54Skamil			break;
35571.54Skamil		case PT_WRITE_D:
35581.54Skamil		case PT_WRITE_I:
35591.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
35601.54Skamil			                       bytes_transfer_dummy, magic)
35611.54Skamil			                != -1);
35621.54Skamil			break;
35631.54Skamil		default:
35641.54Skamil			break;
35651.54Skamil		}
35661.54Skamil		break;
35671.54Skamil	case BYTES_TRANSFER_DATA:
35681.54Skamil		switch (operation) {
35691.54Skamil		case PT_READ_D:
35701.54Skamil		case PT_READ_I:
35711.54Skamil			errno = 0;
35721.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
35731.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
35741.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
35751.54Skamil			break;
35761.54Skamil		case PT_WRITE_D:
35771.54Skamil		case PT_WRITE_I:
35781.54Skamil			lookup_me = magic;
35791.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
35801.54Skamil			                       magic) != -1);
35811.54Skamil			break;
35821.54Skamil		default:
35831.54Skamil			break;
35841.54Skamil		}
35851.54Skamil		break;
35861.54Skamil	default:
35871.54Skamil		break;
35881.54Skamil	}
35891.1Skamil
35901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35911.1Skamil	    "without signal to be sent\n");
35921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35931.1Skamil
35941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35961.1Skamil
35971.1Skamil	validate_status_exited(status, exitval);
35981.1Skamil
35991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36001.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36011.1Skamil}
36021.1Skamil
36031.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
36041.61SkreATF_TC(test);								\
36051.61SkreATF_TC_HEAD(test, tc)							\
36061.61Skre{									\
36071.61Skre	atf_tc_set_md_var(tc, "descr",					\
36081.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
36091.61Skre	    " of type " #type);						\
36101.61Skre}									\
36111.61Skre									\
36121.61SkreATF_TC_BODY(test, tc)							\
36131.61Skre{									\
36141.61Skre									\
36151.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
36161.1Skamil}
36171.1Skamil
36181.54Skamil// DATA
36191.1Skamil
36201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
36211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
36221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
36231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
36241.54Skamil
36251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
36261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
36271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
36281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
36291.54Skamil
36301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
36311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
36321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
36331.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
36341.54Skamil
36351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
36361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
36371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
36381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
36391.54Skamil
36401.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
36411.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
36421.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
36431.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
36441.54Skamil
36451.54Skamil// TEXT
36461.54Skamil
36471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
36481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
36491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
36501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
36511.54Skamil
36521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
36531.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
36541.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
36551.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
36561.54Skamil
36571.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
36581.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
36591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
36601.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
36611.54Skamil
36621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
36631.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
36641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
36651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
36661.54Skamil
36671.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
36681.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
36691.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
36701.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
36711.1Skamil
36721.54Skamil// AUXV
36731.1Skamil
36741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
36751.1Skamil
36761.54Skamil/// ----------------------------------------------------------------------------
36771.1Skamil
36781.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
36791.72Skamilstatic void
36801.72Skamilaccess_regs(const char *regset, const char *aux)
36811.1Skamil{
36821.1Skamil	const int exitval = 5;
36831.1Skamil	const int sigval = SIGSTOP;
36841.1Skamil	pid_t child, wpid;
36851.1Skamil#if defined(TWAIT_HAVE_STATUS)
36861.1Skamil	int status;
36871.1Skamil#endif
36881.72Skamil#if defined(HAVE_GPREGS)
36891.72Skamil	struct reg gpr;
36901.76Sscole	register_t rgstr;
36911.1Skamil#endif
36921.72Skamil#if defined(HAVE_FPREGS)
36931.72Skamil	struct fpreg fpr;
36941.1Skamil#endif
36951.76Sscole
36961.72Skamil#if !defined(HAVE_GPREGS)
36971.72Skamil	if (strcmp(regset, "regs") == 0)
36981.72Skamil		atf_tc_fail("Impossible test scenario!");
36991.1Skamil#endif
37001.1Skamil
37011.72Skamil#if !defined(HAVE_FPREGS)
37021.72Skamil	if (strcmp(regset, "fpregs") == 0)
37031.72Skamil		atf_tc_fail("Impossible test scenario!");
37041.1Skamil#endif
37051.1Skamil
37061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37081.1Skamil	if (child == 0) {
37091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37111.1Skamil
37121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37141.1Skamil
37151.13Schristos		DPRINTF("Before exiting of the child process\n");
37161.1Skamil		_exit(exitval);
37171.1Skamil	}
37181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37191.1Skamil
37201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37221.1Skamil
37231.1Skamil	validate_status_stopped(status, sigval);
37241.1Skamil
37251.1Skamil#if defined(HAVE_GPREGS)
37261.72Skamil	if (strcmp(regset, "regs") == 0) {
37271.72Skamil		DPRINTF("Call GETREGS for the child process\n");
37281.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
37291.72Skamil
37301.72Skamil		if (strcmp(aux, "none") == 0) {
37311.72Skamil			DPRINTF("Retrieved registers\n");
37321.72Skamil		} else if (strcmp(aux, "pc") == 0) {
37331.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
37341.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
37351.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
37361.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
37371.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
37381.72Skamil		} else if (strcmp(aux, "sp") == 0) {
37391.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
37401.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
37411.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
37421.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
37431.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
37441.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
37451.72Skamil			DPRINTF("Call SETREGS for the child process\n");
37461.72Skamil			SYSCALL_REQUIRE(
37471.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
37481.72Skamil		}
37491.72Skamil	}
37501.1Skamil#endif
37511.1Skamil
37521.72Skamil#if defined(HAVE_FPREGS)
37531.72Skamil	if (strcmp(regset, "fpregs") == 0) {
37541.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
37551.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
37561.72Skamil
37571.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
37581.72Skamil			DPRINTF("Retrieved FP registers\n");
37591.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
37601.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
37611.72Skamil			SYSCALL_REQUIRE(
37621.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
37631.72Skamil		}
37641.1Skamil	}
37651.1Skamil#endif
37661.1Skamil
37671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37681.1Skamil	    "without signal to be sent\n");
37691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37701.1Skamil
37711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37731.1Skamil
37741.1Skamil	validate_status_exited(status, exitval);
37751.1Skamil
37761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37781.1Skamil}
37791.1Skamil
37801.72Skamil#define ACCESS_REGS(test, regset, aux)					\
37811.72SkamilATF_TC(test);								\
37821.72SkamilATF_TC_HEAD(test, tc)							\
37831.72Skamil{									\
37841.72Skamil        atf_tc_set_md_var(tc, "descr",					\
37851.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
37861.72Skamil}									\
37871.72Skamil									\
37881.72SkamilATF_TC_BODY(test, tc)							\
37891.72Skamil{									\
37901.72Skamil									\
37911.72Skamil        access_regs(regset, aux);					\
37921.1Skamil}
37931.1Skamil#endif
37941.1Skamil
37951.72Skamil#if defined(HAVE_GPREGS)
37961.72SkamilACCESS_REGS(access_regs1, "regs", "none")
37971.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
37981.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
37991.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
38001.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
38011.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
38021.1Skamil#endif
38031.1Skamil#if defined(HAVE_FPREGS)
38041.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
38051.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
38061.1Skamil#endif
38071.1Skamil
38081.72Skamil/// ----------------------------------------------------------------------------
38091.1Skamil
38101.1Skamil#if defined(PT_STEP)
38111.1Skamilstatic void
38121.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
38131.1Skamil{
38141.1Skamil	const int exitval = 5;
38151.1Skamil	const int sigval = SIGSTOP;
38161.1Skamil	pid_t child, wpid;
38171.1Skamil#if defined(TWAIT_HAVE_STATUS)
38181.1Skamil	int status;
38191.1Skamil#endif
38201.1Skamil	int happy;
38211.95Skamil	struct sigaction sa;
38221.81Skamil	struct ptrace_siginfo info;
38231.95Skamil	sigset_t intmask;
38241.95Skamil	struct kinfo_proc2 kp;
38251.95Skamil	size_t len = sizeof(kp);
38261.95Skamil
38271.95Skamil	int name[6];
38281.95Skamil	const size_t namelen = __arraycount(name);
38291.95Skamil	ki_sigset_t kp_sigmask;
38301.95Skamil	ki_sigset_t kp_sigignore;
38311.1Skamil
38321.1Skamil#if defined(__arm__)
38331.1Skamil	/* PT_STEP not supported on arm 32-bit */
38341.1Skamil	atf_tc_expect_fail("PR kern/52119");
38351.1Skamil#endif
38361.1Skamil
38371.95Skamil	if (masked || ignored)
38381.95Skamil		atf_tc_expect_fail("Unexpected sigmask reset on crash under "
38391.95Skamil		    "debugger");
38401.95Skamil
38411.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38421.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38431.1Skamil	if (child == 0) {
38441.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38451.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38461.1Skamil
38471.95Skamil		if (masked) {
38481.95Skamil			sigemptyset(&intmask);
38491.95Skamil			sigaddset(&intmask, SIGTRAP);
38501.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
38511.95Skamil		}
38521.95Skamil
38531.95Skamil		if (ignored) {
38541.95Skamil			memset(&sa, 0, sizeof(sa));
38551.95Skamil			sa.sa_handler = SIG_IGN;
38561.95Skamil			sigemptyset(&sa.sa_mask);
38571.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
38581.95Skamil		}
38591.95Skamil
38601.1Skamil		happy = check_happy(999);
38611.1Skamil
38621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38641.1Skamil
38651.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
38661.1Skamil
38671.13Schristos		DPRINTF("Before exiting of the child process\n");
38681.1Skamil		_exit(exitval);
38691.1Skamil	}
38701.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38711.1Skamil
38721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38741.1Skamil
38751.1Skamil	validate_status_stopped(status, sigval);
38761.1Skamil
38771.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38781.81Skamil	SYSCALL_REQUIRE(
38791.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38801.81Skamil
38811.81Skamil	DPRINTF("Before checking siginfo_t\n");
38821.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
38831.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
38841.81Skamil
38851.95Skamil	name[0] = CTL_KERN,
38861.95Skamil	name[1] = KERN_PROC2,
38871.95Skamil	name[2] = KERN_PROC_PID;
38881.95Skamil	name[3] = child;
38891.95Skamil	name[4] = sizeof(kp);
38901.95Skamil	name[5] = 1;
38911.95Skamil
38921.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
38931.95Skamil
38941.95Skamil	if (masked)
38951.95Skamil		kp_sigmask = kp.p_sigmask;
38961.95Skamil
38971.95Skamil	if (ignored)
38981.95Skamil		kp_sigignore = kp.p_sigignore;
38991.95Skamil
39001.1Skamil	while (N --> 0) {
39011.2Skamil		if (setstep) {
39021.13Schristos			DPRINTF("Before resuming the child process where it "
39031.2Skamil			    "left off and without signal to be sent (use "
39041.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
39051.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
39061.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
39071.2Skamil			    != -1);
39081.2Skamil		} else {
39091.13Schristos			DPRINTF("Before resuming the child process where it "
39101.2Skamil			    "left off and without signal to be sent (use "
39111.2Skamil			    "PT_STEP)\n");
39121.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
39131.2Skamil			    != -1);
39141.2Skamil		}
39151.1Skamil
39161.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39171.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
39181.1Skamil		    child);
39191.1Skamil
39201.1Skamil		validate_status_stopped(status, SIGTRAP);
39211.2Skamil
39221.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39231.81Skamil		SYSCALL_REQUIRE(
39241.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39251.81Skamil
39261.81Skamil		DPRINTF("Before checking siginfo_t\n");
39271.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
39281.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
39291.81Skamil
39301.2Skamil		if (setstep) {
39311.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
39321.2Skamil		}
39331.95Skamil
39341.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
39351.95Skamil
39361.95Skamil		if (masked) {
39371.95Skamil			DPRINTF("kp_sigmask="
39381.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
39391.95Skamil			    PRIx32 "\n",
39401.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
39411.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
39421.95Skamil
39431.95Skamil			DPRINTF("kp.p_sigmask="
39441.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
39451.95Skamil			    PRIx32 "\n",
39461.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
39471.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
39481.95Skamil
39491.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
39501.95Skamil			    sizeof(kp_sigmask)));
39511.95Skamil		}
39521.95Skamil
39531.95Skamil		if (ignored) {
39541.95Skamil			DPRINTF("kp_sigignore="
39551.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
39561.95Skamil			    PRIx32 "\n",
39571.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
39581.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
39591.95Skamil
39601.95Skamil			DPRINTF("kp.p_sigignore="
39611.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
39621.95Skamil			    PRIx32 "\n",
39631.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
39641.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
39651.95Skamil
39661.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
39671.95Skamil			    sizeof(kp_sigignore)));
39681.95Skamil		}
39691.1Skamil	}
39701.1Skamil
39711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39721.1Skamil	    "without signal to be sent\n");
39731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39741.1Skamil
39751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39771.1Skamil
39781.1Skamil	validate_status_exited(status, exitval);
39791.1Skamil
39801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39821.1Skamil}
39831.1Skamil
39841.73Skamil#define PTRACE_STEP(test, N, setstep)					\
39851.73SkamilATF_TC(test);								\
39861.73SkamilATF_TC_HEAD(test, tc)							\
39871.73Skamil{									\
39881.73Skamil        atf_tc_set_md_var(tc, "descr",					\
39891.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
39901.73Skamil}									\
39911.73Skamil									\
39921.73SkamilATF_TC_BODY(test, tc)							\
39931.73Skamil{									\
39941.73Skamil									\
39951.95Skamil        ptrace_step(N, setstep, false, false);				\
39961.1Skamil}
39971.1Skamil
39981.73SkamilPTRACE_STEP(step1, 1, 0)
39991.73SkamilPTRACE_STEP(step2, 2, 0)
40001.73SkamilPTRACE_STEP(step3, 3, 0)
40011.73SkamilPTRACE_STEP(step4, 4, 0)
40021.73SkamilPTRACE_STEP(setstep1, 1, 1)
40031.73SkamilPTRACE_STEP(setstep2, 2, 1)
40041.73SkamilPTRACE_STEP(setstep3, 3, 1)
40051.73SkamilPTRACE_STEP(setstep4, 4, 1)
40061.95Skamil
40071.95SkamilATF_TC(step_signalmasked);
40081.95SkamilATF_TC_HEAD(step_signalmasked, tc)
40091.95Skamil{
40101.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
40111.95Skamil}
40121.95Skamil
40131.95SkamilATF_TC_BODY(step_signalmasked, tc)
40141.95Skamil{
40151.95Skamil
40161.95Skamil	ptrace_step(1, 0, true, false);
40171.95Skamil}
40181.95Skamil
40191.95SkamilATF_TC(step_signalignored);
40201.95SkamilATF_TC_HEAD(step_signalignored, tc)
40211.95Skamil{
40221.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
40231.95Skamil}
40241.95Skamil
40251.95SkamilATF_TC_BODY(step_signalignored, tc)
40261.95Skamil{
40271.95Skamil
40281.95Skamil	ptrace_step(1, 0, false, true);
40291.95Skamil}
40301.1Skamil#endif
40311.1Skamil
40321.73Skamil/// ----------------------------------------------------------------------------
40331.1Skamil
40341.75Skamilstatic void
40351.75Skamilptrace_kill(const char *type)
40361.1Skamil{
40371.75Skamil	const int sigval = SIGSTOP;
40381.1Skamil	pid_t child, wpid;
40391.1Skamil#if defined(TWAIT_HAVE_STATUS)
40401.1Skamil	int status;
40411.1Skamil#endif
40421.1Skamil
40431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40451.1Skamil	if (child == 0) {
40461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40481.1Skamil
40491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40511.1Skamil
40521.1Skamil		/* NOTREACHED */
40531.1Skamil		FORKEE_ASSERTX(0 &&
40541.1Skamil		    "Child should be terminated by a signal from its parent");
40551.1Skamil	}
40561.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40571.1Skamil
40581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40601.1Skamil
40611.1Skamil	validate_status_stopped(status, sigval);
40621.1Skamil
40631.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
40641.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
40651.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
40661.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
40671.75Skamil		kill(child, SIGKILL);
40681.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
40691.75Skamil		setpgid(child, 0);
40701.75Skamil		killpg(getpgid(child), SIGKILL);
40711.75Skamil	}
40721.1Skamil
40731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40751.1Skamil
40761.75Skamil	validate_status_signaled(status, SIGKILL, 0);
40771.1Skamil
40781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40801.1Skamil}
40811.1Skamil
40821.75Skamil#define PTRACE_KILL(test, type)						\
40831.75SkamilATF_TC(test);								\
40841.75SkamilATF_TC_HEAD(test, tc)							\
40851.75Skamil{									\
40861.75Skamil        atf_tc_set_md_var(tc, "descr",					\
40871.75Skamil            "Verify killing the child with " type);			\
40881.75Skamil}									\
40891.75Skamil									\
40901.75SkamilATF_TC_BODY(test, tc)							\
40911.75Skamil{									\
40921.75Skamil									\
40931.75Skamil        ptrace_kill(type);						\
40941.1Skamil}
40951.1Skamil
40961.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
40971.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
40981.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
40991.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
41001.1Skamil
41011.75Skamil/// ----------------------------------------------------------------------------
41021.1Skamil
41031.77Skamilstatic void
41041.77Skamiltraceme_lwpinfo(const int threads)
41051.1Skamil{
41061.1Skamil	const int sigval = SIGSTOP;
41071.77Skamil	const int sigval2 = SIGINT;
41081.1Skamil	pid_t child, wpid;
41091.1Skamil#if defined(TWAIT_HAVE_STATUS)
41101.1Skamil	int status;
41111.1Skamil#endif
41121.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
41131.77Skamil	struct ptrace_siginfo info;
41141.77Skamil
41151.77Skamil	/* Maximum number of supported threads in this test */
41161.77Skamil	pthread_t t[3];
41171.77Skamil	int n, rv;
41181.77Skamil
41191.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
41201.1Skamil
41211.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41221.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41231.1Skamil	if (child == 0) {
41241.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41251.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41261.1Skamil
41271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41291.1Skamil
41301.77Skamil		for (n = 0; n < threads; n++) {
41311.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
41321.77Skamil			FORKEE_ASSERT(rv == 0);
41331.77Skamil		}
41341.77Skamil
41351.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
41361.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
41371.77Skamil
41381.77Skamil		/* NOTREACHED */
41391.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
41401.1Skamil	}
41411.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41421.1Skamil
41431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41451.1Skamil
41461.1Skamil	validate_status_stopped(status, sigval);
41471.1Skamil
41481.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
41491.77Skamil	SYSCALL_REQUIRE(
41501.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41511.77Skamil
41521.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
41531.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
41541.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41551.77Skamil	    info.psi_siginfo.si_errno);
41561.77Skamil
41571.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
41581.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
41591.77Skamil
41601.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
41611.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
41621.1Skamil
41631.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
41641.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
41651.1Skamil
41661.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
41671.77Skamil	    lwp.pl_lwpid);
41681.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
41691.1Skamil
41701.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
41711.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
41721.1Skamil
41731.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
41741.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
41751.1Skamil
41761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41771.1Skamil	    "without signal to be sent\n");
41781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41791.1Skamil
41801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41821.1Skamil
41831.77Skamil	validate_status_stopped(status, sigval2);
41841.77Skamil
41851.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
41861.77Skamil	SYSCALL_REQUIRE(
41871.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41881.77Skamil
41891.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
41901.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
41911.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41921.77Skamil	    info.psi_siginfo.si_errno);
41931.77Skamil
41941.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
41951.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
41961.77Skamil
41971.77Skamil	memset(&lwp, 0, sizeof(lwp));
41981.77Skamil
41991.77Skamil	for (n = 0; n <= threads; n++) {
42001.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
42011.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
42021.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
42031.77Skamil
42041.77Skamil		DPRINTF("Assert that the thread exists\n");
42051.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
42061.77Skamil
42071.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
42081.77Skamil		    lwp.pl_lwpid);
42091.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
42101.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
42111.77Skamil	}
42121.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
42131.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
42141.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
42151.77Skamil
42161.77Skamil	DPRINTF("Assert that there are no more threads\n");
42171.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
42181.77Skamil
42191.77Skamil	DPRINTF("Before resuming the child process where it left off and "
42201.77Skamil	    "without signal to be sent\n");
42211.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
42221.77Skamil
42231.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42241.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42251.77Skamil
42261.77Skamil	validate_status_signaled(status, SIGKILL, 0);
42271.1Skamil
42281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42301.1Skamil}
42311.1Skamil
42321.77Skamil#define TRACEME_LWPINFO(test, threads)					\
42331.77SkamilATF_TC(test);								\
42341.77SkamilATF_TC_HEAD(test, tc)							\
42351.77Skamil{									\
42361.77Skamil	atf_tc_set_md_var(tc, "descr",					\
42371.77Skamil	    "Verify LWPINFO with the child with " #threads		\
42381.77Skamil	    " spawned extra threads");					\
42391.77Skamil}									\
42401.77Skamil									\
42411.77SkamilATF_TC_BODY(test, tc)							\
42421.77Skamil{									\
42431.77Skamil									\
42441.77Skamil	traceme_lwpinfo(threads);					\
42451.1Skamil}
42461.1Skamil
42471.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
42481.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
42491.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
42501.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
42511.77Skamil
42521.77Skamil/// ----------------------------------------------------------------------------
42531.77Skamil
42541.77Skamil#if defined(TWAIT_HAVE_PID)
42551.77Skamilstatic void
42561.77Skamilattach_lwpinfo(const int threads)
42571.1Skamil{
42581.77Skamil	const int sigval = SIGINT;
42591.1Skamil	struct msg_fds parent_tracee, parent_tracer;
42601.1Skamil	const int exitval_tracer = 10;
42611.1Skamil	pid_t tracee, tracer, wpid;
42621.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
42631.1Skamil#if defined(TWAIT_HAVE_STATUS)
42641.1Skamil	int status;
42651.1Skamil#endif
42661.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
42671.77Skamil	struct ptrace_siginfo info;
42681.77Skamil
42691.77Skamil	/* Maximum number of supported threads in this test */
42701.77Skamil	pthread_t t[3];
42711.77Skamil	int n, rv;
42721.1Skamil
42731.13Schristos	DPRINTF("Spawn tracee\n");
42741.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
42751.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
42761.1Skamil	tracee = atf_utils_fork();
42771.1Skamil	if (tracee == 0) {
42781.1Skamil		/* Wait for message from the parent */
42791.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
42801.1Skamil
42811.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
42821.77Skamil
42831.77Skamil		for (n = 0; n < threads; n++) {
42841.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
42851.77Skamil			FORKEE_ASSERT(rv == 0);
42861.77Skamil		}
42871.77Skamil
42881.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
42891.77Skamil
42901.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42911.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42921.77Skamil
42931.77Skamil		/* NOTREACHED */
42941.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
42951.1Skamil	}
42961.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
42971.1Skamil
42981.13Schristos	DPRINTF("Spawn debugger\n");
42991.1Skamil	tracer = atf_utils_fork();
43001.1Skamil	if (tracer == 0) {
43011.1Skamil		/* No IPC to communicate with the child */
43021.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
43031.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
43041.1Skamil
43051.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
43061.1Skamil		FORKEE_REQUIRE_SUCCESS(
43071.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
43081.1Skamil
43091.1Skamil		forkee_status_stopped(status, SIGSTOP);
43101.1Skamil
43111.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
43121.77Skamil		    "tracee");
43131.77Skamil		FORKEE_ASSERT(
43141.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
43151.77Skamil
43161.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
43171.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
43181.77Skamil		    "si_errno=%#x\n",
43191.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
43201.77Skamil		    info.psi_siginfo.si_errno);
43211.77Skamil
43221.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
43231.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
43241.77Skamil
43251.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
43261.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
43271.1Skamil		    != -1);
43281.1Skamil
43291.13Schristos		DPRINTF("Assert that there exists a thread\n");
43301.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
43311.1Skamil
43321.13Schristos		DPRINTF("Assert that lwp thread %d received event "
43331.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
43341.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
43351.1Skamil
43361.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
43371.77Skamil		    "tracee\n");
43381.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
43391.1Skamil		    != -1);
43401.1Skamil
43411.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
43421.77Skamil		    "tracee\n");
43431.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
43441.1Skamil
43451.1Skamil		/* Resume tracee with PT_CONTINUE */
43461.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
43471.1Skamil
43481.1Skamil		/* Inform parent that tracer has attached to tracee */
43491.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
43501.77Skamil
43511.1Skamil		/* Wait for parent */
43521.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
43531.1Skamil
43541.77Skamil		/* Wait for tracee and assert that it raised a signal */
43551.77Skamil		FORKEE_REQUIRE_SUCCESS(
43561.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
43571.77Skamil
43581.77Skamil		forkee_status_stopped(status, SIGINT);
43591.77Skamil
43601.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
43611.77Skamil		    "child");
43621.77Skamil		FORKEE_ASSERT(
43631.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
43641.77Skamil
43651.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
43661.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
43671.77Skamil		    "si_errno=%#x\n",
43681.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
43691.77Skamil		    info.psi_siginfo.si_errno);
43701.77Skamil
43711.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
43721.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
43731.77Skamil
43741.77Skamil		memset(&lwp, 0, sizeof(lwp));
43751.77Skamil
43761.77Skamil		for (n = 0; n <= threads; n++) {
43771.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
43781.77Skamil			    "child\n");
43791.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
43801.77Skamil			    sizeof(lwp)) != -1);
43811.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
43821.77Skamil
43831.77Skamil			DPRINTF("Assert that the thread exists\n");
43841.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
43851.77Skamil
43861.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
43871.77Skamil			    "event\n", lwp.pl_lwpid);
43881.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
43891.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
43901.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
43911.77Skamil		}
43921.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
43931.77Skamil		    "tracee\n");
43941.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
43951.77Skamil		    != -1);
43961.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
43971.77Skamil
43981.77Skamil		DPRINTF("Assert that there are no more threads\n");
43991.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
44001.77Skamil
44011.77Skamil		DPRINTF("Before resuming the child process where it left off "
44021.77Skamil		    "and without signal to be sent\n");
44031.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
44041.77Skamil		    != -1);
44051.77Skamil
44061.1Skamil		/* Wait for tracee and assert that it exited */
44071.1Skamil		FORKEE_REQUIRE_SUCCESS(
44081.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
44091.1Skamil
44101.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
44111.1Skamil
44121.13Schristos		DPRINTF("Before exiting of the tracer process\n");
44131.1Skamil		_exit(exitval_tracer);
44141.1Skamil	}
44151.1Skamil
44161.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
44171.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
44181.1Skamil
44191.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
44201.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
44211.77Skamil
44221.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
44231.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
44241.1Skamil
44251.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
44261.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
44271.1Skamil
44281.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
44291.1Skamil	    TWAIT_FNAME);
44301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
44311.1Skamil	    tracer);
44321.1Skamil
44331.1Skamil	validate_status_exited(status, exitval_tracer);
44341.1Skamil
44351.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
44361.1Skamil	    TWAIT_FNAME);
44371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
44381.1Skamil	    tracee);
44391.1Skamil
44401.77Skamil	validate_status_signaled(status, SIGKILL, 0);
44411.1Skamil
44421.1Skamil	msg_close(&parent_tracer);
44431.1Skamil	msg_close(&parent_tracee);
44441.1Skamil}
44451.77Skamil
44461.77Skamil#define ATTACH_LWPINFO(test, threads)					\
44471.77SkamilATF_TC(test);								\
44481.77SkamilATF_TC_HEAD(test, tc)							\
44491.77Skamil{									\
44501.77Skamil	atf_tc_set_md_var(tc, "descr",					\
44511.77Skamil	    "Verify LWPINFO with the child with " #threads		\
44521.77Skamil	    " spawned extra threads (tracer is not the original "	\
44531.77Skamil	    "parent)");							\
44541.77Skamil}									\
44551.77Skamil									\
44561.77SkamilATF_TC_BODY(test, tc)							\
44571.77Skamil{									\
44581.77Skamil									\
44591.77Skamil	attach_lwpinfo(threads);					\
44601.77Skamil}
44611.77Skamil
44621.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
44631.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
44641.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
44651.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
44661.1Skamil#endif
44671.1Skamil
44681.77Skamil/// ----------------------------------------------------------------------------
44691.77Skamil
44701.1Skamilstatic void
44711.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
44721.1Skamil{
44731.1Skamil	const int exitval = 5;
44741.1Skamil	const int sigval = SIGINT;
44751.1Skamil	const int sigfaked = SIGTRAP;
44761.1Skamil	const int sicodefaked = TRAP_BRKPT;
44771.1Skamil	pid_t child, wpid;
44781.1Skamil	struct sigaction sa;
44791.1Skamil#if defined(TWAIT_HAVE_STATUS)
44801.1Skamil	int status;
44811.1Skamil#endif
44821.1Skamil	struct ptrace_siginfo info;
44831.1Skamil	memset(&info, 0, sizeof(info));
44841.1Skamil
44851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44871.1Skamil	if (child == 0) {
44881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44901.1Skamil
44911.79Skamil		sa.sa_sigaction = sah;
44921.1Skamil		sa.sa_flags = SA_SIGINFO;
44931.1Skamil		sigemptyset(&sa.sa_mask);
44941.1Skamil
44951.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
44961.79Skamil		    != -1);
44971.1Skamil
44981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45001.1Skamil
45011.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
45021.1Skamil
45031.13Schristos		DPRINTF("Before exiting of the child process\n");
45041.1Skamil		_exit(exitval);
45051.1Skamil	}
45061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45071.1Skamil
45081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45101.1Skamil
45111.1Skamil	validate_status_stopped(status, sigval);
45121.1Skamil
45131.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45141.61Skre	SYSCALL_REQUIRE(
45151.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45161.1Skamil
45171.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45181.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
45191.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45201.1Skamil	    info.psi_siginfo.si_errno);
45211.1Skamil
45221.79Skamil	if (faked) {
45231.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
45241.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
45251.79Skamil		info.psi_siginfo.si_signo = sigfaked;
45261.79Skamil		info.psi_siginfo.si_code = sicodefaked;
45271.79Skamil	}
45281.1Skamil
45291.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
45301.61Skre	SYSCALL_REQUIRE(
45311.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
45321.1Skamil
45331.79Skamil	if (faked) {
45341.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
45351.79Skamil		    "child\n");
45361.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
45371.79Skamil		    sizeof(info)) != -1);
45381.1Skamil
45391.79Skamil		DPRINTF("Before checking siginfo_t\n");
45401.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
45411.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
45421.79Skamil	}
45431.1Skamil
45441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45451.1Skamil	    "without signal to be sent\n");
45461.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
45471.79Skamil	    faked ? sigfaked : sigval) != -1);
45481.1Skamil
45491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45511.1Skamil
45521.1Skamil	validate_status_exited(status, exitval);
45531.1Skamil
45541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45561.1Skamil}
45571.1Skamil
45581.79Skamil#define PTRACE_SIGINFO(test, faked)					\
45591.79SkamilATF_TC(test);								\
45601.79SkamilATF_TC_HEAD(test, tc)							\
45611.79Skamil{									\
45621.79Skamil	atf_tc_set_md_var(tc, "descr",					\
45631.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
45641.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
45651.79Skamil}									\
45661.79Skamil									\
45671.79Skamilstatic int test##_caught = 0;						\
45681.79Skamil									\
45691.79Skamilstatic void								\
45701.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
45711.79Skamil{									\
45721.79Skamil	if (faked) {							\
45731.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
45741.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
45751.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
45761.79Skamil	} else {							\
45771.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
45781.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
45791.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
45801.79Skamil	}								\
45811.79Skamil									\
45821.79Skamil	++ test##_caught;						\
45831.79Skamil}									\
45841.79Skamil									\
45851.79SkamilATF_TC_BODY(test, tc)							\
45861.79Skamil{									\
45871.79Skamil									\
45881.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
45891.79Skamil}
45901.79Skamil
45911.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
45921.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
45931.79Skamil
45941.79Skamil/// ----------------------------------------------------------------------------
45951.79Skamil
45961.97Skamilstatic void
45971.97Skamiltraceme_exec(bool masked, bool ignored)
45981.1Skamil{
45991.1Skamil	const int sigval = SIGTRAP;
46001.1Skamil	pid_t child, wpid;
46011.1Skamil#if defined(TWAIT_HAVE_STATUS)
46021.1Skamil	int status;
46031.1Skamil#endif
46041.97Skamil	struct sigaction sa;
46051.97Skamil	struct ptrace_siginfo info;
46061.97Skamil	sigset_t intmask;
46071.97Skamil	struct kinfo_proc2 kp;
46081.97Skamil	size_t len = sizeof(kp);
46091.97Skamil
46101.97Skamil	int name[6];
46111.97Skamil	const size_t namelen = __arraycount(name);
46121.97Skamil	ki_sigset_t kp_sigmask;
46131.97Skamil	ki_sigset_t kp_sigignore;
46141.1Skamil
46151.1Skamil	memset(&info, 0, sizeof(info));
46161.1Skamil
46171.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46181.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46191.1Skamil	if (child == 0) {
46201.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46211.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46221.1Skamil
46231.97Skamil		if (masked) {
46241.97Skamil			sigemptyset(&intmask);
46251.97Skamil			sigaddset(&intmask, sigval);
46261.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
46271.97Skamil		}
46281.97Skamil
46291.97Skamil		if (ignored) {
46301.97Skamil			memset(&sa, 0, sizeof(sa));
46311.97Skamil			sa.sa_handler = SIG_IGN;
46321.97Skamil			sigemptyset(&sa.sa_mask);
46331.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
46341.97Skamil		}
46351.97Skamil
46361.13Schristos		DPRINTF("Before calling execve(2) from child\n");
46371.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
46381.1Skamil
46391.1Skamil		FORKEE_ASSERT(0 && "Not reached");
46401.1Skamil	}
46411.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46421.1Skamil
46431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46451.1Skamil
46461.1Skamil	validate_status_stopped(status, sigval);
46471.1Skamil
46481.97Skamil	name[0] = CTL_KERN,
46491.97Skamil	name[1] = KERN_PROC2,
46501.97Skamil	name[2] = KERN_PROC_PID;
46511.97Skamil	name[3] = getpid();
46521.97Skamil	name[4] = sizeof(kp);
46531.97Skamil	name[5] = 1;
46541.97Skamil
46551.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
46561.97Skamil
46571.97Skamil	if (masked)
46581.97Skamil		kp_sigmask = kp.p_sigmask;
46591.97Skamil
46601.97Skamil	if (ignored)
46611.97Skamil		kp_sigignore = kp.p_sigignore;
46621.97Skamil
46631.97Skamil	name[3] = getpid();
46641.97Skamil
46651.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
46661.97Skamil
46671.97Skamil	if (masked) {
46681.97Skamil		DPRINTF("kp_sigmask="
46691.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
46701.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
46711.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
46721.97Skamil
46731.97Skamil		DPRINTF("kp.p_sigmask="
46741.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
46751.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
46761.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
46771.97Skamil
46781.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
46791.97Skamil		    sizeof(kp_sigmask)));
46801.97Skamil	}
46811.97Skamil
46821.97Skamil	if (ignored) {
46831.97Skamil		DPRINTF("kp_sigignore="
46841.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
46851.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
46861.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
46871.97Skamil
46881.97Skamil		DPRINTF("kp.p_sigignore="
46891.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
46901.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
46911.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
46921.97Skamil
46931.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
46941.97Skamil		    sizeof(kp_sigignore)));
46951.97Skamil	}
46961.97Skamil
46971.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
46981.61Skre	SYSCALL_REQUIRE(
46991.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
47001.1Skamil
47011.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47021.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
47031.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47041.1Skamil	    info.psi_siginfo.si_errno);
47051.1Skamil
47061.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
47071.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
47081.1Skamil
47091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47101.1Skamil	    "without signal to be sent\n");
47111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47121.1Skamil
47131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47151.1Skamil
47161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47181.1Skamil}
47191.1Skamil
47201.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
47211.97SkamilATF_TC(test);								\
47221.97SkamilATF_TC_HEAD(test, tc)							\
47231.97Skamil{									\
47241.97Skamil       atf_tc_set_md_var(tc, "descr",					\
47251.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
47261.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
47271.97Skamil           masked ? " with ignored signal" : "");			\
47281.97Skamil}									\
47291.97Skamil									\
47301.97SkamilATF_TC_BODY(test, tc)							\
47311.97Skamil{									\
47321.97Skamil									\
47331.97Skamil       traceme_exec(masked, ignored);					\
47341.97Skamil}
47351.97Skamil
47361.97SkamilTRACEME_EXEC(traceme_exec, false, false)
47371.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
47381.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
47391.97Skamil
47401.82Skamil/// ----------------------------------------------------------------------------
47411.82Skamil
47421.83Skamilstatic volatile int done;
47431.1Skamil
47441.83Skamilstatic void *
47451.83Skamiltrace_threads_cb(void *arg __unused)
47461.1Skamil{
47471.1Skamil
47481.83Skamil	done++;
47491.83Skamil
47501.83Skamil	while (done < 3)
47511.83Skamil		continue;
47521.83Skamil
47531.83Skamil	return NULL;
47541.1Skamil}
47551.1Skamil
47561.83Skamilstatic void
47571.83Skamiltrace_threads(bool trace_create, bool trace_exit)
47581.1Skamil{
47591.1Skamil	const int sigval = SIGSTOP;
47601.1Skamil	pid_t child, wpid;
47611.1Skamil#if defined(TWAIT_HAVE_STATUS)
47621.1Skamil	int status;
47631.1Skamil#endif
47641.1Skamil	ptrace_state_t state;
47651.1Skamil	const int slen = sizeof(state);
47661.1Skamil	ptrace_event_t event;
47671.1Skamil	const int elen = sizeof(event);
47681.83Skamil	struct ptrace_siginfo info;
47691.83Skamil
47701.83Skamil	pthread_t t[3];
47711.83Skamil	int rv;
47721.83Skamil	size_t n;
47731.1Skamil	lwpid_t lid;
47741.83Skamil
47751.83Skamil	/* Track created and exited threads */
47761.83Skamil	bool traced_lwps[__arraycount(t)];
47771.83Skamil
47781.83Skamil	atf_tc_skip("PR kern/51995");
47791.1Skamil
47801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47821.1Skamil	if (child == 0) {
47831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47851.1Skamil
47861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47881.1Skamil
47891.83Skamil		for (n = 0; n < __arraycount(t); n++) {
47901.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
47911.83Skamil			    NULL);
47921.83Skamil			FORKEE_ASSERT(rv == 0);
47931.83Skamil		}
47941.1Skamil
47951.83Skamil		for (n = 0; n < __arraycount(t); n++) {
47961.83Skamil			rv = pthread_join(t[n], NULL);
47971.83Skamil			FORKEE_ASSERT(rv == 0);
47981.83Skamil		}
47991.1Skamil
48001.83Skamil		/*
48011.83Skamil		 * There is race between _exit() and pthread_join() detaching
48021.83Skamil		 * a thread. For simplicity kill the process after detecting
48031.83Skamil		 * LWP events.
48041.83Skamil		 */
48051.83Skamil		while (true)
48061.83Skamil			continue;
48071.1Skamil
48081.83Skamil		FORKEE_ASSERT(0 && "Not reached");
48091.1Skamil	}
48101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48111.1Skamil
48121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48141.1Skamil
48151.1Skamil	validate_status_stopped(status, sigval);
48161.1Skamil
48171.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48181.83Skamil	SYSCALL_REQUIRE(
48191.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48201.1Skamil
48211.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48221.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48231.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48241.83Skamil	    info.psi_siginfo.si_errno);
48251.1Skamil
48261.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
48271.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
48281.1Skamil
48291.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
48301.83Skamil	memset(&event, 0, sizeof(event));
48311.83Skamil	if (trace_create)
48321.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
48331.83Skamil	if (trace_exit)
48341.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
48351.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
48361.1Skamil
48371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48381.1Skamil	    "without signal to be sent\n");
48391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48401.1Skamil
48411.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
48421.1Skamil
48431.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
48441.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
48451.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
48461.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
48471.83Skamil		    child);
48481.1Skamil
48491.83Skamil		validate_status_stopped(status, SIGTRAP);
48501.1Skamil
48511.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
48521.83Skamil		    "child\n");
48531.83Skamil		SYSCALL_REQUIRE(
48541.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48551.1Skamil
48561.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48571.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
48581.83Skamil		    "si_errno=%#x\n",
48591.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48601.83Skamil		    info.psi_siginfo.si_errno);
48611.1Skamil
48621.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
48631.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
48641.1Skamil
48651.83Skamil		SYSCALL_REQUIRE(
48661.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
48671.1Skamil
48681.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
48691.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
48701.1Skamil
48711.83Skamil		lid = state.pe_lwp;
48721.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
48731.1Skamil
48741.83Skamil		traced_lwps[lid - 1] = true;
48751.1Skamil
48761.83Skamil		DPRINTF("Before resuming the child process where it left off "
48771.83Skamil		    "and without signal to be sent\n");
48781.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48791.83Skamil	}
48801.1Skamil
48811.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
48821.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
48831.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
48841.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
48851.83Skamil		    child);
48861.1Skamil
48871.83Skamil		validate_status_stopped(status, SIGTRAP);
48881.1Skamil
48891.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
48901.83Skamil		    "child\n");
48911.83Skamil		SYSCALL_REQUIRE(
48921.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48931.1Skamil
48941.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48951.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
48961.83Skamil		    "si_errno=%#x\n",
48971.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48981.83Skamil		    info.psi_siginfo.si_errno);
48991.1Skamil
49001.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
49011.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
49021.1Skamil
49031.83Skamil		SYSCALL_REQUIRE(
49041.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
49051.1Skamil
49061.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
49071.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
49081.1Skamil
49091.83Skamil		lid = state.pe_lwp;
49101.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
49111.1Skamil
49121.83Skamil		if (trace_create) {
49131.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
49141.83Skamil			traced_lwps[lid - 1] = false;
49151.83Skamil		}
49161.1Skamil
49171.83Skamil		DPRINTF("Before resuming the child process where it left off "
49181.83Skamil		    "and without signal to be sent\n");
49191.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49201.83Skamil	}
49211.1Skamil
49221.83Skamil	kill(child, SIGKILL);
49231.1Skamil
49241.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49251.1Skamil	    TWAIT_FNAME);
49261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49271.1Skamil
49281.83Skamil	validate_status_signaled(status, SIGKILL, 0);
49291.1Skamil
49301.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49311.1Skamil	    TWAIT_FNAME);
49321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49331.1Skamil}
49341.1Skamil
49351.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
49361.83SkamilATF_TC(test);								\
49371.83SkamilATF_TC_HEAD(test, tc)							\
49381.83Skamil{									\
49391.83Skamil        atf_tc_set_md_var(tc, "descr",					\
49401.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
49411.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
49421.83Skamil	    trace_exit ? "" : "out");					\
49431.83Skamil}									\
49441.83Skamil									\
49451.83SkamilATF_TC_BODY(test, tc)							\
49461.83Skamil{									\
49471.83Skamil									\
49481.83Skamil        trace_threads(trace_create, trace_exit);			\
49491.83Skamil}
49501.83Skamil
49511.83SkamilTRACE_THREADS(trace_thread1, false, false)
49521.83SkamilTRACE_THREADS(trace_thread2, false, true)
49531.83SkamilTRACE_THREADS(trace_thread3, true, false)
49541.83SkamilTRACE_THREADS(trace_thread4, true, true)
49551.83Skamil
49561.83Skamil/// ----------------------------------------------------------------------------
49571.83Skamil
49581.84SkamilATF_TC(signal_mask_unrelated);
49591.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
49601.1Skamil{
49611.1Skamil	atf_tc_set_md_var(tc, "descr",
49621.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
49631.1Skamil	    "from catching other signals");
49641.1Skamil}
49651.1Skamil
49661.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
49671.1Skamil{
49681.1Skamil	const int exitval = 5;
49691.1Skamil	const int sigval = SIGSTOP;
49701.1Skamil	const int sigmasked = SIGTRAP;
49711.1Skamil	const int signotmasked = SIGINT;
49721.1Skamil	pid_t child, wpid;
49731.1Skamil#if defined(TWAIT_HAVE_STATUS)
49741.1Skamil	int status;
49751.1Skamil#endif
49761.1Skamil	sigset_t intmask;
49771.1Skamil
49781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49801.1Skamil	if (child == 0) {
49811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49831.1Skamil
49841.1Skamil		sigemptyset(&intmask);
49851.1Skamil		sigaddset(&intmask, sigmasked);
49861.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
49871.1Skamil
49881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49901.1Skamil
49911.13Schristos		DPRINTF("Before raising %s from child\n",
49921.1Skamil		    strsignal(signotmasked));
49931.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
49941.1Skamil
49951.13Schristos		DPRINTF("Before exiting of the child process\n");
49961.1Skamil		_exit(exitval);
49971.1Skamil	}
49981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49991.1Skamil
50001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50021.1Skamil
50031.1Skamil	validate_status_stopped(status, sigval);
50041.1Skamil
50051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50061.1Skamil	    "without signal to be sent\n");
50071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50081.1Skamil
50091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50111.1Skamil
50121.1Skamil	validate_status_stopped(status, signotmasked);
50131.1Skamil
50141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50151.1Skamil	    "without signal to be sent\n");
50161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50171.1Skamil
50181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50201.1Skamil
50211.1Skamil	validate_status_exited(status, exitval);
50221.1Skamil
50231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50251.1Skamil}
50261.1Skamil
50271.84Skamil/// ----------------------------------------------------------------------------
50281.84Skamil
50291.1Skamil#if defined(TWAIT_HAVE_PID)
50301.99Skamilstatic void
50311.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked,
50321.99Skamil           bool ignored)
50331.1Skamil{
50341.1Skamil	const int exitval = 5;
50351.1Skamil	const int exitval2 = 15;
50361.1Skamil	const int sigval = SIGSTOP;
50371.99Skamil	pid_t child, child2 = 0, wpid;
50381.1Skamil#if defined(TWAIT_HAVE_STATUS)
50391.1Skamil	int status;
50401.1Skamil#endif
50411.1Skamil	ptrace_state_t state;
50421.1Skamil	const int slen = sizeof(state);
50431.1Skamil	ptrace_event_t event;
50441.1Skamil	const int elen = sizeof(event);
50451.99Skamil	pid_t (*fn)(void);
50461.99Skamil	struct sigaction sa;
50471.99Skamil	struct ptrace_siginfo info;
50481.99Skamil	sigset_t intmask;
50491.99Skamil	struct kinfo_proc2 kp;
50501.99Skamil	size_t len = sizeof(kp);
50511.99Skamil
50521.99Skamil	int name[6];
50531.99Skamil	const size_t namelen = __arraycount(name);
50541.99Skamil	ki_sigset_t kp_sigmask;
50551.99Skamil	ki_sigset_t kp_sigignore;
50561.1Skamil
50571.99Skamil	if (masked)
50581.99Skamil		atf_tc_expect_fail("Masked signal invisible to tracer");
50591.99Skamil
50601.99Skamil	if (trackfork)
50611.99Skamil		fn = fork;
50621.99Skamil	if (trackvfork || trackvforkdone)
50631.99Skamil		fn = vfork;
50641.14Schristos
50651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50671.1Skamil	if (child == 0) {
50681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50701.1Skamil
50711.99Skamil		if (masked) {
50721.99Skamil			sigemptyset(&intmask);
50731.99Skamil			sigaddset(&intmask, SIGTRAP);
50741.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
50751.99Skamil		}
50761.99Skamil
50771.99Skamil		if (ignored) {
50781.99Skamil			memset(&sa, 0, sizeof(sa));
50791.99Skamil			sa.sa_handler = SIG_IGN;
50801.99Skamil			sigemptyset(&sa.sa_mask);
50811.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
50821.99Skamil		}
50831.1Skamil
50841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50861.1Skamil
50871.99Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
50881.1Skamil
50891.1Skamil		if (child2 == 0)
50901.1Skamil			_exit(exitval2);
50911.1Skamil
50921.1Skamil		FORKEE_REQUIRE_SUCCESS
50931.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
50941.1Skamil
50951.1Skamil		forkee_status_exited(status, exitval2);
50961.1Skamil
50971.13Schristos		DPRINTF("Before exiting of the child process\n");
50981.1Skamil		_exit(exitval);
50991.1Skamil	}
51001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51011.1Skamil
51021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51041.1Skamil
51051.1Skamil	validate_status_stopped(status, sigval);
51061.1Skamil
51071.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51081.99Skamil	SYSCALL_REQUIRE(
51091.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51101.99Skamil
51111.99Skamil	DPRINTF("Before checking siginfo_t\n");
51121.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
51131.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
51141.1Skamil
51151.99Skamil	name[0] = CTL_KERN,
51161.99Skamil	name[1] = KERN_PROC2,
51171.99Skamil	name[2] = KERN_PROC_PID;
51181.99Skamil	name[3] = child;
51191.99Skamil	name[4] = sizeof(kp);
51201.99Skamil	name[5] = 1;
51211.1Skamil
51221.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
51231.1Skamil
51241.99Skamil	if (masked)
51251.99Skamil		kp_sigmask = kp.p_sigmask;
51261.1Skamil
51271.99Skamil	if (ignored)
51281.99Skamil		kp_sigignore = kp.p_sigignore;
51291.1Skamil
51301.99Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
51311.99Skamil	    trackfork ? "|PTRACE_FORK" : "",
51321.99Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
51331.99Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
51341.99Skamil	event.pe_set_event = 0;
51351.99Skamil	if (trackfork)
51361.99Skamil		event.pe_set_event |= PTRACE_FORK;
51371.99Skamil	if (trackvfork)
51381.99Skamil		event.pe_set_event |= PTRACE_VFORK;
51391.99Skamil	if (trackvforkdone)
51401.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
51411.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
51421.1Skamil
51431.99Skamil	DPRINTF("Before resuming the child process where it left off and "
51441.99Skamil	    "without signal to be sent\n");
51451.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51461.1Skamil
51471.99Skamil	if (trackfork || trackvfork) {
51481.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
51491.99Skamil		    child);
51501.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
51511.99Skamil		    child);
51521.1Skamil
51531.99Skamil		validate_status_stopped(status, SIGTRAP);
51541.1Skamil
51551.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
51561.1Skamil
51571.99Skamil		if (masked) {
51581.99Skamil			DPRINTF("kp_sigmask="
51591.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
51601.99Skamil			    PRIx32 "\n",
51611.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
51621.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
51631.1Skamil
51641.99Skamil			DPRINTF("kp.p_sigmask="
51651.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
51661.99Skamil			    PRIx32 "\n",
51671.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
51681.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
51691.1Skamil
51701.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
51711.99Skamil			    sizeof(kp_sigmask)));
51721.99Skamil		}
51731.1Skamil
51741.99Skamil		if (ignored) {
51751.99Skamil			DPRINTF("kp_sigignore="
51761.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
51771.99Skamil			    PRIx32 "\n",
51781.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
51791.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
51801.1Skamil
51811.99Skamil			DPRINTF("kp.p_sigignore="
51821.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
51831.99Skamil			    PRIx32 "\n",
51841.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
51851.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
51861.1Skamil
51871.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
51881.99Skamil			    sizeof(kp_sigignore)));
51891.99Skamil		}
51901.1Skamil
51911.99Skamil		SYSCALL_REQUIRE(
51921.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51931.99Skamil		if (trackfork) {
51941.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
51951.99Skamil			       PTRACE_FORK);
51961.99Skamil		}
51971.99Skamil		if (trackvfork) {
51981.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
51991.99Skamil			       PTRACE_VFORK);
52001.99Skamil		}
52011.1Skamil
52021.99Skamil		child2 = state.pe_other_pid;
52031.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
52041.1Skamil
52051.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
52061.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
52071.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
52081.99Skamil		    child2);
52091.1Skamil
52101.99Skamil		validate_status_stopped(status, SIGTRAP);
52111.1Skamil
52121.99Skamil		name[3] = child2;
52131.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
52141.1Skamil
52151.99Skamil		if (masked) {
52161.99Skamil			DPRINTF("kp_sigmask="
52171.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
52181.99Skamil			    PRIx32 "\n",
52191.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
52201.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
52211.1Skamil
52221.99Skamil			DPRINTF("kp.p_sigmask="
52231.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
52241.99Skamil			    PRIx32 "\n",
52251.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
52261.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
52271.14Schristos
52281.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
52291.99Skamil			    sizeof(kp_sigmask)));
52301.99Skamil		}
52311.1Skamil
52321.99Skamil		if (ignored) {
52331.99Skamil			DPRINTF("kp_sigignore="
52341.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
52351.99Skamil			    PRIx32 "\n",
52361.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
52371.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
52381.1Skamil
52391.99Skamil			DPRINTF("kp.p_sigignore="
52401.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
52411.99Skamil			    PRIx32 "\n",
52421.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
52431.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
52441.1Skamil
52451.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
52461.99Skamil			    sizeof(kp_sigignore)));
52471.99Skamil		}
52481.1Skamil
52491.99Skamil		SYSCALL_REQUIRE(
52501.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
52511.99Skamil		if (trackfork) {
52521.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
52531.99Skamil			       PTRACE_FORK);
52541.99Skamil		}
52551.99Skamil		if (trackvfork) {
52561.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
52571.99Skamil			       PTRACE_VFORK);
52581.99Skamil		}
52591.1Skamil
52601.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
52611.1Skamil
52621.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
52631.99Skamil		    "and without signal to be sent\n");
52641.99Skamil		SYSCALL_REQUIRE(
52651.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
52661.1Skamil
52671.99Skamil		DPRINTF("Before resuming the child process where it left off "
52681.99Skamil		    "and without signal to be sent\n");
52691.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52701.1Skamil	}
52711.1Skamil
52721.99Skamil	if (trackvforkdone) {
52731.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
52741.99Skamil		    child);
52751.99Skamil		TWAIT_REQUIRE_SUCCESS(
52761.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
52771.1Skamil
52781.99Skamil		validate_status_stopped(status, SIGTRAP);
52791.1Skamil
52801.99Skamil		name[3] = child;
52811.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
52821.1Skamil
52831.99Skamil		if (masked) {
52841.99Skamil			DPRINTF("kp_sigmask="
52851.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
52861.99Skamil			    PRIx32 "\n",
52871.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
52881.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
52891.1Skamil
52901.99Skamil			DPRINTF("kp.p_sigmask="
52911.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
52921.99Skamil			    PRIx32 "\n",
52931.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
52941.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
52951.1Skamil
52961.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
52971.99Skamil			    sizeof(kp_sigmask)));
52981.99Skamil		}
52991.1Skamil
53001.99Skamil		if (ignored) {
53011.99Skamil			DPRINTF("kp_sigignore="
53021.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53031.99Skamil			    PRIx32 "\n",
53041.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
53051.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
53061.1Skamil
53071.99Skamil			DPRINTF("kp.p_sigignore="
53081.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53091.99Skamil			    PRIx32 "\n",
53101.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
53111.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
53121.1Skamil
53131.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
53141.99Skamil			    sizeof(kp_sigignore)));
53151.99Skamil		}
53161.1Skamil
53171.99Skamil		SYSCALL_REQUIRE(
53181.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
53191.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
53201.1Skamil
53211.99Skamil		child2 = state.pe_other_pid;
53221.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
53231.99Skamil		    child2);
53241.1Skamil
53251.99Skamil		DPRINTF("Before resuming the child process where it left off "
53261.99Skamil		    "and without signal to be sent\n");
53271.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53281.99Skamil	}
53291.1Skamil
53301.99Skamil	if (trackfork || trackvfork) {
53311.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
53321.99Skamil		    "\n", TWAIT_FNAME);
53331.99Skamil		TWAIT_REQUIRE_SUCCESS(
53341.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
53351.1Skamil
53361.99Skamil		validate_status_exited(status, exitval2);
53371.1Skamil
53381.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
53391.99Skamil		    "process\n", TWAIT_FNAME);
53401.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
53411.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
53421.99Skamil	}
53431.1Skamil
53441.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
53451.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
53461.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53471.1Skamil
53481.1Skamil	validate_status_stopped(status, SIGCHLD);
53491.1Skamil
53501.57Skamil	DPRINTF("Before resuming the child process where it left off and "
53511.1Skamil	    "without signal to be sent\n");
53521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53531.1Skamil
53541.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53551.1Skamil	    TWAIT_FNAME);
53561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53571.1Skamil
53581.1Skamil	validate_status_exited(status, exitval);
53591.1Skamil
53601.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53611.57Skamil	    TWAIT_FNAME);
53621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53631.1Skamil}
53641.1Skamil
53651.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone,		\
53661.99Skamil                   masked,ignored)					\
53671.99SkamilATF_TC(name);								\
53681.99SkamilATF_TC_HEAD(name, tc)							\
53691.99Skamil{									\
53701.99Skamil	atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught "	\
53711.99Skamil	    "regardless of signal %s%s", 				\
53721.99Skamil	    trackfork ? "PTRACE_FORK" : "",				\
53731.99Skamil	    trackvfork ? "PTRACE_VFORK" : "",				\
53741.99Skamil	    trackvforkdone ? "PTRACE_VFORK_DONE" : "",			\
53751.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
53761.99Skamil}									\
53771.99Skamil									\
53781.99SkamilATF_TC_BODY(name, tc)							\
53791.99Skamil{									\
53801.99Skamil									\
53811.99Skamil	fork2_body(trackfork, trackvfork, trackvforkdone, masked,	\
53821.99Skamil	           ignored);						\
53831.1Skamil}
53841.1Skamil
53851.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false)
53861.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true)
53871.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false)
53881.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true)
53891.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false)
53901.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true)
53911.1Skamil#endif
53921.1Skamil
53931.99Skamil/// ----------------------------------------------------------------------------
53941.1Skamil
53951.83Skamilvolatile lwpid_t the_lwp_id = 0;
53961.83Skamil
53971.83Skamilstatic void
53981.83Skamillwp_main_func(void *arg)
53991.83Skamil{
54001.83Skamil	the_lwp_id = _lwp_self();
54011.83Skamil	_lwp_exit();
54021.83Skamil}
54031.83Skamil
54041.1SkamilATF_TC(signal9);
54051.1SkamilATF_TC_HEAD(signal9, tc)
54061.1Skamil{
54071.1Skamil	atf_tc_set_md_var(tc, "descr",
54081.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
54091.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
54101.1Skamil}
54111.1Skamil
54121.1SkamilATF_TC_BODY(signal9, tc)
54131.1Skamil{
54141.1Skamil	const int exitval = 5;
54151.1Skamil	const int sigval = SIGSTOP;
54161.1Skamil	const int sigmasked = SIGTRAP;
54171.1Skamil	pid_t child, wpid;
54181.1Skamil#if defined(TWAIT_HAVE_STATUS)
54191.1Skamil	int status;
54201.1Skamil#endif
54211.1Skamil	sigset_t intmask;
54221.1Skamil	ptrace_state_t state;
54231.1Skamil	const int slen = sizeof(state);
54241.1Skamil	ptrace_event_t event;
54251.1Skamil	const int elen = sizeof(event);
54261.1Skamil	ucontext_t uc;
54271.1Skamil	lwpid_t lid;
54281.1Skamil	static const size_t ssize = 16*1024;
54291.1Skamil	void *stack;
54301.1Skamil
54311.14Schristos	atf_tc_expect_fail("PR kern/51918");
54321.14Schristos
54331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54351.1Skamil	if (child == 0) {
54361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54381.1Skamil
54391.1Skamil		sigemptyset(&intmask);
54401.1Skamil		sigaddset(&intmask, sigmasked);
54411.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
54421.1Skamil
54431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54451.1Skamil
54461.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
54471.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
54481.1Skamil
54491.13Schristos		DPRINTF("Before making context for new lwp in child\n");
54501.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
54511.1Skamil
54521.13Schristos		DPRINTF("Before creating new in child\n");
54531.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54541.1Skamil
54551.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54561.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54571.1Skamil
54581.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54591.1Skamil		    "are the same\n", lid, the_lwp_id);
54601.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54611.1Skamil
54621.13Schristos		DPRINTF("Before exiting of the child process\n");
54631.1Skamil		_exit(exitval);
54641.1Skamil	}
54651.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54661.1Skamil
54671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54691.1Skamil
54701.1Skamil	validate_status_stopped(status, sigval);
54711.1Skamil
54721.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
54731.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
54741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
54751.1Skamil
54761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54771.1Skamil	    "without signal to be sent\n");
54781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54791.1Skamil
54801.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54811.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54831.1Skamil
54841.1Skamil	validate_status_stopped(status, sigmasked);
54851.1Skamil
54861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54871.1Skamil
54881.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
54891.1Skamil
54901.1Skamil	lid = state.pe_lwp;
54911.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
54921.1Skamil
54931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54941.1Skamil	    "without signal to be sent\n");
54951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54961.1Skamil
54971.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54981.1Skamil	    TWAIT_FNAME);
54991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55001.1Skamil
55011.1Skamil	validate_status_exited(status, exitval);
55021.1Skamil
55031.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55041.1Skamil	    TWAIT_FNAME);
55051.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55061.1Skamil}
55071.1Skamil
55081.1SkamilATF_TC(signal10);
55091.1SkamilATF_TC_HEAD(signal10, tc)
55101.1Skamil{
55111.1Skamil	atf_tc_set_md_var(tc, "descr",
55121.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
55131.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
55141.1Skamil}
55151.1Skamil
55161.1SkamilATF_TC_BODY(signal10, tc)
55171.1Skamil{
55181.1Skamil	const int exitval = 5;
55191.1Skamil	const int sigval = SIGSTOP;
55201.1Skamil	const int sigmasked = SIGTRAP;
55211.1Skamil	pid_t child, wpid;
55221.1Skamil#if defined(TWAIT_HAVE_STATUS)
55231.1Skamil	int status;
55241.1Skamil#endif
55251.1Skamil	sigset_t intmask;
55261.1Skamil	ptrace_state_t state;
55271.1Skamil	const int slen = sizeof(state);
55281.1Skamil	ptrace_event_t event;
55291.1Skamil	const int elen = sizeof(event);
55301.1Skamil	ucontext_t uc;
55311.1Skamil	lwpid_t lid;
55321.1Skamil	static const size_t ssize = 16*1024;
55331.1Skamil	void *stack;
55341.1Skamil
55351.14Schristos	atf_tc_expect_fail("PR kern/51918");
55361.14Schristos
55371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55391.1Skamil	if (child == 0) {
55401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55421.1Skamil
55431.1Skamil		sigemptyset(&intmask);
55441.1Skamil		sigaddset(&intmask, sigmasked);
55451.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
55461.1Skamil
55471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55491.1Skamil
55501.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
55511.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
55521.1Skamil
55531.13Schristos		DPRINTF("Before making context for new lwp in child\n");
55541.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
55551.1Skamil
55561.13Schristos		DPRINTF("Before creating new in child\n");
55571.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
55581.1Skamil
55591.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
55601.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
55611.1Skamil
55621.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
55631.1Skamil		    "are the same\n", lid, the_lwp_id);
55641.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
55651.1Skamil
55661.13Schristos		DPRINTF("Before exiting of the child process\n");
55671.1Skamil		_exit(exitval);
55681.1Skamil	}
55691.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55701.1Skamil
55711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55731.1Skamil
55741.1Skamil	validate_status_stopped(status, sigval);
55751.1Skamil
55761.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
55771.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
55781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
55791.1Skamil
55801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55811.1Skamil	    "without signal to be sent\n");
55821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55831.1Skamil
55841.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
55851.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
55861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55871.1Skamil
55881.1Skamil	validate_status_stopped(status, sigmasked);
55891.1Skamil
55901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55911.1Skamil
55921.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
55931.1Skamil
55941.1Skamil	lid = state.pe_lwp;
55951.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
55961.1Skamil
55971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55981.1Skamil	    "without signal to be sent\n");
55991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56001.1Skamil
56011.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
56021.1Skamil	    TWAIT_FNAME);
56031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56041.1Skamil
56051.1Skamil	validate_status_exited(status, exitval);
56061.1Skamil
56071.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
56081.1Skamil	    TWAIT_FNAME);
56091.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56101.1Skamil}
56111.1Skamil
56121.1Skamilstatic void
56131.1Skamillwp_main_stop(void *arg)
56141.1Skamil{
56151.1Skamil	the_lwp_id = _lwp_self();
56161.1Skamil
56171.1Skamil	raise(SIGTRAP);
56181.1Skamil
56191.1Skamil	_lwp_exit();
56201.1Skamil}
56211.1Skamil
56221.1SkamilATF_TC(suspend1);
56231.1SkamilATF_TC_HEAD(suspend1, tc)
56241.1Skamil{
56251.1Skamil	atf_tc_set_md_var(tc, "descr",
56261.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
56271.1Skamil	    "resumed by a tracee");
56281.1Skamil}
56291.1Skamil
56301.1SkamilATF_TC_BODY(suspend1, tc)
56311.1Skamil{
56321.1Skamil	const int exitval = 5;
56331.1Skamil	const int sigval = SIGSTOP;
56341.1Skamil	pid_t child, wpid;
56351.1Skamil#if defined(TWAIT_HAVE_STATUS)
56361.1Skamil	int status;
56371.1Skamil#endif
56381.1Skamil	ucontext_t uc;
56391.1Skamil	lwpid_t lid;
56401.1Skamil	static const size_t ssize = 16*1024;
56411.1Skamil	void *stack;
56421.1Skamil	struct ptrace_lwpinfo pl;
56431.1Skamil	struct ptrace_siginfo psi;
56441.1Skamil	volatile int go = 0;
56451.1Skamil
56461.17Skamil	// Feature pending for refactoring
56471.17Skamil	atf_tc_expect_fail("PR kern/51995");
56481.17Skamil
56491.16Skamil	// Hangs with qemu
56501.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
56511.16Skamil
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.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56591.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56601.1Skamil
56611.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
56621.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
56631.1Skamil
56641.13Schristos		DPRINTF("Before making context for new lwp in child\n");
56651.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
56661.1Skamil
56671.13Schristos		DPRINTF("Before creating new in child\n");
56681.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
56691.1Skamil
56701.1Skamil		while (go == 0)
56711.1Skamil			continue;
56721.1Skamil
56731.1Skamil		raise(SIGINT);
56741.1Skamil
56751.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
56761.1Skamil
56771.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
56781.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
56791.1Skamil
56801.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
56811.1Skamil		    "are the same\n", lid, the_lwp_id);
56821.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
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.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56951.1Skamil	    "without signal to be sent\n");
56961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56971.1Skamil
56981.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
56991.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
57001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57011.1Skamil
57021.1Skamil	validate_status_stopped(status, SIGTRAP);
57031.1Skamil
57041.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
57051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
57061.1Skamil
57071.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
57081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
57091.1Skamil
57101.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
57111.1Skamil	    child, getpid());
57121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
57131.1Skamil
57141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57151.1Skamil	    "without signal to be sent\n");
57161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57171.1Skamil
57181.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
57191.1Skamil	    "SIGINT\n", TWAIT_FNAME);
57201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57211.1Skamil
57221.1Skamil	validate_status_stopped(status, SIGINT);
57231.1Skamil
57241.1Skamil	pl.pl_lwpid = 0;
57251.1Skamil
57261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
57271.1Skamil	while (pl.pl_lwpid != 0) {
57281.1Skamil
57291.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
57301.1Skamil		switch (pl.pl_lwpid) {
57311.1Skamil		case 1:
57321.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
57331.1Skamil			break;
57341.1Skamil		case 2:
57351.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
57361.1Skamil			break;
57371.1Skamil		}
57381.1Skamil	}
57391.1Skamil
57401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57411.1Skamil	    "without signal to be sent\n");
57421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57431.1Skamil
57441.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
57451.1Skamil	    TWAIT_FNAME);
57461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57471.1Skamil
57481.1Skamil	validate_status_exited(status, exitval);
57491.1Skamil
57501.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
57511.1Skamil	    TWAIT_FNAME);
57521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57531.1Skamil}
57541.1Skamil
57551.1SkamilATF_TC(suspend2);
57561.1SkamilATF_TC_HEAD(suspend2, tc)
57571.1Skamil{
57581.1Skamil	atf_tc_set_md_var(tc, "descr",
57591.1Skamil	    "Verify that the while the only thread within a process is "
57601.1Skamil	    "suspended, the whole process cannot be unstopped");
57611.1Skamil}
57621.1Skamil
57631.1SkamilATF_TC_BODY(suspend2, tc)
57641.1Skamil{
57651.1Skamil	const int exitval = 5;
57661.1Skamil	const int sigval = SIGSTOP;
57671.1Skamil	pid_t child, wpid;
57681.1Skamil#if defined(TWAIT_HAVE_STATUS)
57691.1Skamil	int status;
57701.1Skamil#endif
57711.1Skamil	struct ptrace_siginfo psi;
57721.1Skamil
57731.17Skamil	// Feature pending for refactoring
57741.17Skamil	atf_tc_expect_fail("PR kern/51995");
57751.17Skamil
57761.16Skamil	// Hangs with qemu
57771.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
57781.16Skamil
57791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57811.1Skamil	if (child == 0) {
57821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57841.1Skamil
57851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57871.1Skamil
57881.13Schristos		DPRINTF("Before exiting of the child process\n");
57891.1Skamil		_exit(exitval);
57901.1Skamil	}
57911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57921.1Skamil
57931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57951.1Skamil
57961.1Skamil	validate_status_stopped(status, sigval);
57971.1Skamil
57981.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
57991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
58001.1Skamil
58011.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
58021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
58031.1Skamil
58041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58051.1Skamil	    "without signal to be sent\n");
58061.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
58071.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
58081.1Skamil
58091.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
58101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
58111.1Skamil
58121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58131.1Skamil	    "without signal to be sent\n");
58141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58151.1Skamil
58161.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
58171.1Skamil	    TWAIT_FNAME);
58181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58191.1Skamil
58201.1Skamil	validate_status_exited(status, exitval);
58211.1Skamil
58221.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
58231.1Skamil	    TWAIT_FNAME);
58241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58251.1Skamil}
58261.1Skamil
58271.1SkamilATF_TC(resume1);
58281.1SkamilATF_TC_HEAD(resume1, tc)
58291.1Skamil{
58301.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
58311.1Skamil	atf_tc_set_md_var(tc, "descr",
58321.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
58331.1Skamil	    "resumed by the debugger");
58341.1Skamil}
58351.1Skamil
58361.1SkamilATF_TC_BODY(resume1, tc)
58371.1Skamil{
58381.1Skamil	struct msg_fds fds;
58391.1Skamil	const int exitval = 5;
58401.1Skamil	const int sigval = SIGSTOP;
58411.1Skamil	pid_t child, wpid;
58421.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
58431.1Skamil#if defined(TWAIT_HAVE_STATUS)
58441.1Skamil	int status;
58451.1Skamil#endif
58461.1Skamil	ucontext_t uc;
58471.1Skamil	lwpid_t lid;
58481.1Skamil	static const size_t ssize = 16*1024;
58491.1Skamil	void *stack;
58501.1Skamil	struct ptrace_lwpinfo pl;
58511.1Skamil	struct ptrace_siginfo psi;
58521.1Skamil
58531.17Skamil	// Feature pending for refactoring
58541.17Skamil	atf_tc_expect_fail("PR kern/51995");
58551.17Skamil
58561.15Schristos	// Hangs with qemu
58571.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
58581.1Skamil
58591.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
58601.1Skamil
58611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58631.1Skamil	if (child == 0) {
58641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58661.1Skamil
58671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58691.1Skamil
58701.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
58711.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
58721.1Skamil
58731.13Schristos		DPRINTF("Before making context for new lwp in child\n");
58741.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
58751.1Skamil
58761.13Schristos		DPRINTF("Before creating new in child\n");
58771.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
58781.1Skamil
58791.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
58801.1Skamil
58811.1Skamil		raise(SIGINT);
58821.1Skamil
58831.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
58841.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
58851.1Skamil
58861.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
58871.1Skamil		    "are the same\n", lid, the_lwp_id);
58881.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
58891.1Skamil
58901.13Schristos		DPRINTF("Before exiting of the child process\n");
58911.1Skamil		_exit(exitval);
58921.1Skamil	}
58931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58941.1Skamil
58951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58971.1Skamil
58981.1Skamil	validate_status_stopped(status, sigval);
58991.1Skamil
59001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59011.1Skamil	    "without signal to be sent\n");
59021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59031.1Skamil
59041.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59051.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
59061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59071.1Skamil
59081.1Skamil	validate_status_stopped(status, SIGTRAP);
59091.1Skamil
59101.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
59111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
59121.1Skamil
59131.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
59141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
59151.1Skamil
59161.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
59171.1Skamil
59181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59191.1Skamil	    "without signal to be sent\n");
59201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59211.1Skamil
59221.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59231.1Skamil	    "SIGINT\n", TWAIT_FNAME);
59241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59251.1Skamil
59261.1Skamil	validate_status_stopped(status, SIGINT);
59271.1Skamil
59281.1Skamil	pl.pl_lwpid = 0;
59291.1Skamil
59301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
59311.1Skamil	while (pl.pl_lwpid != 0) {
59321.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
59331.1Skamil		switch (pl.pl_lwpid) {
59341.1Skamil		case 1:
59351.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
59361.1Skamil			break;
59371.1Skamil		case 2:
59381.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
59391.1Skamil			break;
59401.1Skamil		}
59411.1Skamil	}
59421.1Skamil
59431.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
59441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
59451.1Skamil
59461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59471.1Skamil	    "without signal to be sent\n");
59481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59491.1Skamil
59501.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59511.1Skamil	    TWAIT_FNAME);
59521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59531.1Skamil
59541.1Skamil	validate_status_exited(status, exitval);
59551.1Skamil
59561.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59571.1Skamil	    TWAIT_FNAME);
59581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59591.1Skamil
59601.1Skamil	msg_close(&fds);
59611.1Skamil
59621.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
59631.1Skamil	sleep(10);
59641.1Skamil}
59651.1Skamil
59661.1SkamilATF_TC(syscall1);
59671.1SkamilATF_TC_HEAD(syscall1, tc)
59681.1Skamil{
59691.1Skamil	atf_tc_set_md_var(tc, "descr",
59701.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
59711.1Skamil}
59721.1Skamil
59731.1SkamilATF_TC_BODY(syscall1, tc)
59741.1Skamil{
59751.1Skamil	const int exitval = 5;
59761.1Skamil	const int sigval = SIGSTOP;
59771.1Skamil	pid_t child, wpid;
59781.1Skamil#if defined(TWAIT_HAVE_STATUS)
59791.1Skamil	int status;
59801.1Skamil#endif
59811.1Skamil	struct ptrace_siginfo info;
59821.1Skamil	memset(&info, 0, sizeof(info));
59831.1Skamil
59841.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59851.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59861.1Skamil	if (child == 0) {
59871.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59881.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59891.1Skamil
59901.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59911.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59921.1Skamil
59931.1Skamil		syscall(SYS_getpid);
59941.1Skamil
59951.13Schristos		DPRINTF("Before exiting of the child process\n");
59961.1Skamil		_exit(exitval);
59971.1Skamil	}
59981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59991.1Skamil
60001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60021.1Skamil
60031.1Skamil	validate_status_stopped(status, sigval);
60041.1Skamil
60051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60061.1Skamil	    "without signal to be sent\n");
60071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
60081.1Skamil
60091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60111.1Skamil
60121.1Skamil	validate_status_stopped(status, SIGTRAP);
60131.1Skamil
60141.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
60151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
60161.1Skamil
60171.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
60181.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
60191.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
60201.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
60211.1Skamil
60221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60231.1Skamil	    "without signal to be sent\n");
60241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
60251.1Skamil
60261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60281.1Skamil
60291.1Skamil	validate_status_stopped(status, SIGTRAP);
60301.1Skamil
60311.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
60321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
60331.1Skamil
60341.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
60351.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
60361.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
60371.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
60381.1Skamil
60391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60401.1Skamil	    "without signal to be sent\n");
60411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60421.1Skamil
60431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60451.1Skamil
60461.1Skamil	validate_status_exited(status, exitval);
60471.1Skamil
60481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60491.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60501.1Skamil}
60511.1Skamil
60521.1SkamilATF_TC(syscallemu1);
60531.1SkamilATF_TC_HEAD(syscallemu1, tc)
60541.1Skamil{
60551.1Skamil	atf_tc_set_md_var(tc, "descr",
60561.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
60571.1Skamil}
60581.1Skamil
60591.1SkamilATF_TC_BODY(syscallemu1, tc)
60601.1Skamil{
60611.1Skamil	const int exitval = 5;
60621.1Skamil	const int sigval = SIGSTOP;
60631.1Skamil	pid_t child, wpid;
60641.1Skamil#if defined(TWAIT_HAVE_STATUS)
60651.1Skamil	int status;
60661.1Skamil#endif
60671.1Skamil
60681.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
60691.6Skamil	/* syscallemu does not work on sparc (32-bit) */
60701.6Skamil	atf_tc_expect_fail("PR kern/52166");
60711.6Skamil#endif
60721.6Skamil
60731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60751.1Skamil	if (child == 0) {
60761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60781.1Skamil
60791.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60801.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60811.1Skamil
60821.1Skamil		syscall(SYS_exit, 100);
60831.1Skamil
60841.13Schristos		DPRINTF("Before exiting of the child process\n");
60851.1Skamil		_exit(exitval);
60861.1Skamil	}
60871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60881.1Skamil
60891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60911.1Skamil
60921.1Skamil	validate_status_stopped(status, sigval);
60931.1Skamil
60941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60951.1Skamil	    "without signal to be sent\n");
60961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
60971.1Skamil
60981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61001.1Skamil
61011.1Skamil	validate_status_stopped(status, SIGTRAP);
61021.1Skamil
61031.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
61041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
61051.1Skamil
61061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61071.1Skamil	    "without signal to be sent\n");
61081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
61091.1Skamil
61101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61121.1Skamil
61131.1Skamil	validate_status_stopped(status, SIGTRAP);
61141.1Skamil
61151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61161.1Skamil	    "without signal to be sent\n");
61171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61181.1Skamil
61191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61211.1Skamil
61221.1Skamil	validate_status_exited(status, exitval);
61231.1Skamil
61241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61261.1Skamil}
61271.1Skamil
61281.1Skamil#include "t_ptrace_amd64_wait.h"
61291.1Skamil#include "t_ptrace_i386_wait.h"
61301.1Skamil#include "t_ptrace_x86_wait.h"
61311.1Skamil
61321.1SkamilATF_TP_ADD_TCS(tp)
61331.1Skamil{
61341.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
61351.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
61361.33Skamil
61371.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
61381.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
61391.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
61401.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
61411.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
61421.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
61431.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
61441.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
61451.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
61461.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
61471.33Skamil
61481.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
61491.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
61501.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
61511.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
61521.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
61531.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
61541.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
61551.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
61561.87Skamil
61571.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
61581.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
61591.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
61601.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
61611.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
61621.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
61631.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
61641.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
61651.86Skamil
61661.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
61671.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
61681.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
61691.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
61701.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
61711.59Skamil
61721.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
61731.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
61741.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
61751.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
61761.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
61771.88Skamil
61781.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
61791.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
61801.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
61811.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
61821.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
61831.88Skamil
61841.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
61851.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
61861.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
61871.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
61881.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
61891.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
61901.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
61911.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
61921.50Skamil
61931.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
61941.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
61951.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
61961.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
61971.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
61981.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
61991.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
62001.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
62011.50Skamil
62021.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
62031.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
62041.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
62051.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
62061.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
62071.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
62081.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
62091.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
62101.50Skamil
62111.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
62121.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
62131.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
62141.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
62151.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
62161.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
62171.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
62181.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
62191.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
62201.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
62211.1Skamil
62221.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
62231.37Skamil
62241.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
62251.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
62261.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
62271.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
62281.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
62291.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
62301.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
62311.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
62321.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
62331.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
62341.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
62351.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
62361.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
62371.40Skamil
62381.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
62391.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
62401.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
62411.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
62421.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
62431.41Skamil
62441.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
62451.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
62461.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
62471.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
62481.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
62491.92Skamil
62501.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
62511.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
62521.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
62531.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
62541.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
62551.92Skamil
62561.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
62571.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
62581.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
62591.43Skamil
62601.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
62611.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
62621.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
62631.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
62641.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
62651.59Skamil
62661.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62671.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
62681.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62691.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
62701.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62711.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
62721.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62731.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
62741.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62751.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
62761.94Skamil
62771.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62781.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
62791.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62801.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
62811.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62821.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
62831.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62841.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
62851.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
62861.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
62871.94Skamil
62881.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
62891.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
62901.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
62911.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
62921.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
62931.51Skamil
62941.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
62951.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
62961.51Skamil
62971.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
62981.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
62991.51Skamil
63001.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
63011.51Skamil		tracee_sees_its_original_parent_getppid);
63021.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
63031.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
63041.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
63051.51Skamil		tracee_sees_its_original_parent_procfs_status);
63061.1Skamil
63071.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
63081.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
63091.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
63101.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
63111.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
63121.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
63131.1Skamil
63141.31Skamil	ATF_TP_ADD_TC(tp, fork1);
63151.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
63161.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
63171.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
63181.31Skamil	ATF_TP_ADD_TC(tp, fork5);
63191.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
63201.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
63211.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
63221.31Skamil
63231.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
63241.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
63251.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
63261.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
63271.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
63281.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
63291.64Smartin// thes tests hang on SMP machines, disable them for now
63301.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
63311.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
63321.1Skamil
63331.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
63341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
63351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
63361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
63371.54Skamil
63381.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
63391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
63401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
63411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
63421.54Skamil
63431.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
63441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
63451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
63461.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
63471.54Skamil
63481.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
63491.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
63501.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
63511.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
63521.54Skamil
63531.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
63541.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
63551.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
63561.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
63571.54Skamil
63581.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
63591.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
63601.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
63611.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
63621.54Skamil
63631.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
63641.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
63651.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
63661.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
63671.54Skamil
63681.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
63691.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
63701.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
63711.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
63721.54Skamil
63731.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
63741.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
63751.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
63761.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
63771.54Skamil
63781.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
63791.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
63801.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
63811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
63821.1Skamil
63831.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
63841.1Skamil
63851.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
63861.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
63871.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
63881.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
63891.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
63901.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
63911.1Skamil
63921.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
63931.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
63941.1Skamil
63951.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
63961.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
63971.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
63981.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
63991.1Skamil
64001.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
64011.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
64021.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
64031.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
64041.2Skamil
64051.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
64061.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
64071.95Skamil
64081.1Skamil	ATF_TP_ADD_TC(tp, kill1);
64091.1Skamil	ATF_TP_ADD_TC(tp, kill2);
64101.75Skamil	ATF_TP_ADD_TC(tp, kill3);
64111.1Skamil
64121.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
64131.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
64141.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
64151.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
64161.77Skamil
64171.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
64181.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
64191.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
64201.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
64211.1Skamil
64221.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
64231.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
64241.79Skamil
64251.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
64261.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
64271.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
64281.1Skamil
64291.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
64301.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
64311.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
64321.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
64331.1Skamil
64341.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
64351.84Skamil
64361.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
64371.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
64381.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
64391.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
64401.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
64411.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
64421.99Skamil
64431.1Skamil	ATF_TP_ADD_TC(tp, signal9);
64441.1Skamil	ATF_TP_ADD_TC(tp, signal10);
64451.1Skamil
64461.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
64471.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
64481.1Skamil
64491.1Skamil	ATF_TP_ADD_TC(tp, resume1);
64501.1Skamil
64511.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
64521.1Skamil
64531.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
64541.1Skamil
64551.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
64561.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
64571.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
64581.1Skamil
64591.1Skamil	return atf_no_error();
64601.1Skamil}
6461