t_ptrace_wait.c revision 1.88
11.88Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.88 2019/02/15 05:06:38 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.88Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.88 2019/02/15 05:06:38 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.88Skamil	pid_t child, wpid;
5171.88Skamil#if defined(TWAIT_HAVE_STATUS)
5181.88Skamil	int status;
5191.88Skamil#endif
5201.88Skamil	struct ptrace_siginfo info;
5211.88Skamil	sigset_t intmask;
5221.88Skamil
5231.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5241.88Skamil	if (sig == SIGILL)
5251.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5261.88Skamil#endif
5271.88Skamil
5281.88Skamil	memset(&info, 0, sizeof(info));
5291.88Skamil
5301.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5311.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5321.88Skamil	if (child == 0) {
5331.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5341.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5351.88Skamil
5361.88Skamil		sigemptyset(&intmask);
5371.88Skamil		sigaddset(&intmask, sig);
5381.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5391.88Skamil
5401.88Skamil		DPRINTF("Before executing a trap\n");
5411.88Skamil		switch (sig) {
5421.88Skamil		case SIGTRAP:
5431.88Skamil			trigger_trap();
5441.88Skamil			break;
5451.88Skamil		case SIGSEGV:
5461.88Skamil			trigger_segv();
5471.88Skamil			break;
5481.88Skamil		case SIGILL:
5491.88Skamil			trigger_ill();
5501.88Skamil			break;
5511.88Skamil		case SIGFPE:
5521.88Skamil			trigger_fpe();
5531.88Skamil			break;
5541.88Skamil		case SIGBUS:
5551.88Skamil			trigger_bus();
5561.88Skamil			break;
5571.88Skamil		default:
5581.88Skamil			/* NOTREACHED */
5591.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5601.88Skamil		}
5611.88Skamil
5621.88Skamil		/* NOTREACHED */
5631.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5641.88Skamil	}
5651.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5661.88Skamil
5671.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5681.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5691.88Skamil
5701.88Skamil	validate_status_stopped(status, sig);
5711.88Skamil
5721.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
5731.88Skamil	SYSCALL_REQUIRE(
5741.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5751.88Skamil
5761.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5771.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5781.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5791.88Skamil	    info.psi_siginfo.si_errno);
5801.88Skamil
5811.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
5821.88Skamil	switch (sig) {
5831.88Skamil	case SIGTRAP:
5841.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
5851.88Skamil		break;
5861.88Skamil	case SIGSEGV:
5871.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
5881.88Skamil		break;
5891.88Skamil	case SIGILL:
5901.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
5911.88Skamil		break;
5921.88Skamil	case SIGFPE:
5931.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
5941.88Skamil		break;
5951.88Skamil	case SIGBUS:
5961.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
5971.88Skamil		break;
5981.88Skamil	}
5991.88Skamil
6001.88Skamil
6011.88Skamil
6021.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6031.88Skamil
6041.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6051.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6061.88Skamil
6071.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6081.88Skamil
6091.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6101.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6111.88Skamil}
6121.88Skamil
6131.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6141.88SkamilATF_TC(test);								\
6151.88SkamilATF_TC_HEAD(test, tc)							\
6161.88Skamil{									\
6171.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6181.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6191.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6201.88Skamil}									\
6211.88Skamil									\
6221.88SkamilATF_TC_BODY(test, tc)							\
6231.88Skamil{									\
6241.88Skamil									\
6251.88Skamil	traceme_signalmasked_crash(sig);				\
6261.88Skamil}
6271.88Skamil
6281.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
6291.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
6301.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
6311.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
6321.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
6331.88Skamil
6341.88Skamil/// ----------------------------------------------------------------------------
6351.88Skamil
6361.88Skamilstatic void
6371.88Skamiltraceme_signalignored_crash(int sig)
6381.88Skamil{
6391.88Skamil	pid_t child, wpid;
6401.88Skamil#if defined(TWAIT_HAVE_STATUS)
6411.88Skamil	int status;
6421.88Skamil#endif
6431.88Skamil	struct sigaction sa;
6441.88Skamil	struct ptrace_siginfo info;
6451.88Skamil
6461.88Skamil#ifndef PTRACE_ILLEGAL_ASM
6471.88Skamil	if (sig == SIGILL)
6481.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
6491.88Skamil#endif
6501.88Skamil
6511.88Skamil	memset(&info, 0, sizeof(info));
6521.88Skamil
6531.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
6541.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
6551.88Skamil	if (child == 0) {
6561.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
6571.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
6581.88Skamil
6591.88Skamil		memset(&sa, 0, sizeof(sa));
6601.88Skamil		sa.sa_handler = SIG_IGN;
6611.88Skamil		sigemptyset(&sa.sa_mask);
6621.88Skamil
6631.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
6641.88Skamil
6651.88Skamil		DPRINTF("Before executing a trap\n");
6661.88Skamil		switch (sig) {
6671.88Skamil		case SIGTRAP:
6681.88Skamil			trigger_trap();
6691.88Skamil			break;
6701.88Skamil		case SIGSEGV:
6711.88Skamil			trigger_segv();
6721.88Skamil			break;
6731.88Skamil		case SIGILL:
6741.88Skamil			trigger_ill();
6751.88Skamil			break;
6761.88Skamil		case SIGFPE:
6771.88Skamil			trigger_fpe();
6781.88Skamil			break;
6791.88Skamil		case SIGBUS:
6801.88Skamil			trigger_bus();
6811.88Skamil			break;
6821.88Skamil		default:
6831.88Skamil			/* NOTREACHED */
6841.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
6851.88Skamil		}
6861.88Skamil
6871.88Skamil		/* NOTREACHED */
6881.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
6891.88Skamil	}
6901.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
6911.88Skamil
6921.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6931.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6941.88Skamil
6951.88Skamil	validate_status_stopped(status, sig);
6961.88Skamil
6971.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6981.88Skamil	SYSCALL_REQUIRE(
6991.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7001.88Skamil
7011.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7021.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7031.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7041.88Skamil	    info.psi_siginfo.si_errno);
7051.88Skamil
7061.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
7071.88Skamil	switch (sig) {
7081.88Skamil	case SIGTRAP:
7091.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
7101.88Skamil		break;
7111.88Skamil	case SIGSEGV:
7121.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
7131.88Skamil		break;
7141.88Skamil	case SIGILL:
7151.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
7161.88Skamil		break;
7171.88Skamil	case SIGFPE:
7181.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
7191.88Skamil		break;
7201.88Skamil	case SIGBUS:
7211.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
7221.88Skamil		break;
7231.88Skamil	}
7241.88Skamil
7251.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
7261.88Skamil
7271.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7281.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7291.88Skamil
7301.88Skamil	validate_status_signaled(status, SIGKILL, 0);
7311.88Skamil
7321.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7331.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
7341.88Skamil}
7351.88Skamil
7361.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
7371.88SkamilATF_TC(test);								\
7381.88SkamilATF_TC_HEAD(test, tc)							\
7391.88Skamil{									\
7401.88Skamil	atf_tc_set_md_var(tc, "descr",					\
7411.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
7421.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
7431.88Skamil}									\
7441.88Skamil									\
7451.88SkamilATF_TC_BODY(test, tc)							\
7461.88Skamil{									\
7471.88Skamil									\
7481.88Skamil	traceme_signalignored_crash(sig);				\
7491.88Skamil}
7501.88Skamil
7511.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
7521.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
7531.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
7541.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
7551.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
7561.88Skamil
7571.88Skamil/// ----------------------------------------------------------------------------
7581.88Skamil
7591.88Skamilstatic void
7601.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
7611.1Skamil{
7621.1Skamil	const int exitval = 5;
7631.34Skamil	const int sigval = SIGSTOP;
7641.1Skamil	pid_t child, wpid;
7651.1Skamil	struct sigaction sa;
7661.1Skamil#if defined(TWAIT_HAVE_STATUS)
7671.1Skamil	int status;
7681.1Skamil#endif
7691.61Skre	struct ptrace_siginfo info;
7701.1Skamil
7711.45Skamil	memset(&info, 0, sizeof(info));
7721.45Skamil
7731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
7741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
7751.1Skamil	if (child == 0) {
7761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7781.1Skamil
7791.34Skamil		sa.sa_handler = sah;
7801.1Skamil		sa.sa_flags = SA_SIGINFO;
7811.1Skamil		sigemptyset(&sa.sa_mask);
7821.1Skamil
7831.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
7841.1Skamil
7851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7871.1Skamil
7881.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
7891.1Skamil
7901.13Schristos		DPRINTF("Before exiting of the child process\n");
7911.1Skamil		_exit(exitval);
7921.1Skamil	}
7931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7941.1Skamil
7951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7971.1Skamil
7981.1Skamil	validate_status_stopped(status, sigval);
7991.1Skamil
8001.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
8011.61Skre	SYSCALL_REQUIRE(
8021.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8031.45Skamil
8041.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8051.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8061.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8071.45Skamil	    info.psi_siginfo.si_errno);
8081.45Skamil
8091.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8101.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
8111.45Skamil
8121.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
8131.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
8141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
8151.1Skamil
8161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8181.1Skamil
8191.1Skamil	validate_status_exited(status, exitval);
8201.1Skamil
8211.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
8221.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8231.1Skamil}
8241.1Skamil
8251.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
8261.61SkreATF_TC(test);								\
8271.61SkreATF_TC_HEAD(test, tc)							\
8281.61Skre{									\
8291.61Skre	atf_tc_set_md_var(tc, "descr",					\
8301.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
8311.61Skre	    "handled correctly and caught by a signal handler");	\
8321.61Skre}									\
8331.61Skre									\
8341.61Skrestatic int test##_caught = 0;						\
8351.61Skre									\
8361.61Skrestatic void								\
8371.61Skretest##_sighandler(int arg)						\
8381.61Skre{									\
8391.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
8401.61Skre									\
8411.61Skre	++ test##_caught;						\
8421.61Skre}									\
8431.61Skre									\
8441.61SkreATF_TC_BODY(test, tc)							\
8451.61Skre{									\
8461.61Skre									\
8471.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
8481.34Skamil}
8491.34Skamil
8501.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
8511.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
8521.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
8531.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
8541.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
8551.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
8561.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
8571.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
8581.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
8591.34Skamil
8601.34Skamil/// ----------------------------------------------------------------------------
8611.34Skamil
8621.35Skamilstatic void
8631.50Skamiltraceme_sendsignal_masked(int sigsent)
8641.50Skamil{
8651.50Skamil	const int exitval = 5;
8661.50Skamil	const int sigval = SIGSTOP;
8671.50Skamil	pid_t child, wpid;
8681.50Skamil	sigset_t set;
8691.50Skamil#if defined(TWAIT_HAVE_STATUS)
8701.50Skamil	int status;
8711.50Skamil#endif
8721.61Skre	struct ptrace_siginfo info;
8731.50Skamil
8741.50Skamil	memset(&info, 0, sizeof(info));
8751.50Skamil
8761.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8771.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
8781.50Skamil	if (child == 0) {
8791.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8801.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8811.50Skamil
8821.50Skamil		sigemptyset(&set);
8831.50Skamil		sigaddset(&set, sigsent);
8841.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
8851.50Skamil
8861.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
8871.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
8881.50Skamil
8891.50Skamil		_exit(exitval);
8901.50Skamil	}
8911.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8921.50Skamil
8931.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8941.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8951.50Skamil
8961.50Skamil	validate_status_stopped(status, sigval);
8971.50Skamil
8981.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
8991.61Skre	SYSCALL_REQUIRE(
9001.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9011.50Skamil
9021.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9031.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9041.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9051.50Skamil	    info.psi_siginfo.si_errno);
9061.50Skamil
9071.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9081.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9091.50Skamil
9101.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
9111.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9121.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9131.50Skamil
9141.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9151.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9161.50Skamil
9171.50Skamil	validate_status_exited(status, exitval);
9181.50Skamil
9191.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9201.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9211.50Skamil}
9221.50Skamil
9231.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
9241.61SkreATF_TC(test);								\
9251.61SkreATF_TC_HEAD(test, tc)							\
9261.61Skre{									\
9271.61Skre	atf_tc_set_md_var(tc, "descr",					\
9281.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9291.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
9301.61Skre}									\
9311.61Skre									\
9321.61SkreATF_TC_BODY(test, tc)							\
9331.61Skre{									\
9341.61Skre									\
9351.61Skre	traceme_sendsignal_masked(sig);					\
9361.50Skamil}
9371.50Skamil
9381.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
9391.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
9401.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
9411.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
9421.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
9431.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
9441.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
9451.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
9461.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
9471.50Skamil
9481.50Skamil/// ----------------------------------------------------------------------------
9491.50Skamil
9501.50Skamilstatic void
9511.50Skamiltraceme_sendsignal_ignored(int sigsent)
9521.50Skamil{
9531.50Skamil	const int exitval = 5;
9541.50Skamil	const int sigval = SIGSTOP;
9551.50Skamil	pid_t child, wpid;
9561.50Skamil	struct sigaction sa;
9571.50Skamil#if defined(TWAIT_HAVE_STATUS)
9581.50Skamil	int status;
9591.50Skamil#endif
9601.61Skre	struct ptrace_siginfo info;
9611.50Skamil
9621.50Skamil	memset(&info, 0, sizeof(info));
9631.50Skamil
9641.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9651.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
9661.50Skamil	if (child == 0) {
9671.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9681.61Skre
9691.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9701.50Skamil
9711.50Skamil		memset(&sa, 0, sizeof(sa));
9721.50Skamil		sa.sa_handler = SIG_IGN;
9731.50Skamil		sigemptyset(&sa.sa_mask);
9741.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
9751.50Skamil
9761.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9771.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9781.50Skamil
9791.50Skamil		_exit(exitval);
9801.50Skamil	}
9811.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9821.50Skamil
9831.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9841.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9851.50Skamil
9861.50Skamil	validate_status_stopped(status, sigval);
9871.50Skamil
9881.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9891.61Skre	SYSCALL_REQUIRE(
9901.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9911.50Skamil
9921.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9931.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9941.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9951.50Skamil	    info.psi_siginfo.si_errno);
9961.50Skamil
9971.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9981.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9991.50Skamil
10001.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10011.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10021.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10031.50Skamil
10041.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10051.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10061.50Skamil
10071.50Skamil	validate_status_exited(status, exitval);
10081.50Skamil
10091.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10101.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10111.50Skamil}
10121.50Skamil
10131.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
10141.61SkreATF_TC(test);								\
10151.61SkreATF_TC_HEAD(test, tc)							\
10161.61Skre{									\
10171.61Skre	atf_tc_set_md_var(tc, "descr",					\
10181.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10191.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
10201.61Skre}									\
10211.61Skre									\
10221.61SkreATF_TC_BODY(test, tc)							\
10231.61Skre{									\
10241.61Skre									\
10251.61Skre	traceme_sendsignal_ignored(sig);				\
10261.50Skamil}
10271.50Skamil
10281.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
10291.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
10301.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
10311.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
10321.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
10331.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
10341.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
10351.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
10361.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
10371.50Skamil
10381.50Skamil/// ----------------------------------------------------------------------------
10391.50Skamil
10401.50Skamilstatic void
10411.50Skamiltraceme_sendsignal_simple(int sigsent)
10421.1Skamil{
10431.35Skamil	const int sigval = SIGSTOP;
10441.35Skamil	int exitval = 0;
10451.1Skamil	pid_t child, wpid;
10461.1Skamil#if defined(TWAIT_HAVE_STATUS)
10471.1Skamil	int status;
10481.85Skamil	int expect_core;
10491.85Skamil
10501.85Skamil	switch (sigsent) {
10511.85Skamil	case SIGABRT:
10521.85Skamil	case SIGTRAP:
10531.85Skamil	case SIGBUS:
10541.85Skamil	case SIGILL:
10551.85Skamil	case SIGFPE:
10561.85Skamil	case SIGSEGV:
10571.85Skamil		expect_core = 1;
10581.85Skamil		break;
10591.85Skamil	default:
10601.85Skamil		expect_core = 0;
10611.85Skamil		break;
10621.85Skamil	}
10631.1Skamil#endif
10641.61Skre	struct ptrace_siginfo info;
10651.1Skamil
10661.45Skamil	memset(&info, 0, sizeof(info));
10671.45Skamil
10681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
10691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
10701.1Skamil	if (child == 0) {
10711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10731.1Skamil
10741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10761.1Skamil
10771.35Skamil		switch (sigsent) {
10781.35Skamil		case SIGCONT:
10791.48Skamil		case SIGSTOP:
10801.35Skamil			_exit(exitval);
10811.35Skamil		default:
10821.35Skamil			/* NOTREACHED */
10831.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
10841.35Skamil		}
10851.1Skamil	}
10861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10871.1Skamil
10881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10901.1Skamil
10911.1Skamil	validate_status_stopped(status, sigval);
10921.1Skamil
10931.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10941.61Skre	SYSCALL_REQUIRE(
10951.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10961.45Skamil
10971.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10981.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10991.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11001.45Skamil	    info.psi_siginfo.si_errno);
11011.45Skamil
11021.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11031.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11041.45Skamil
11051.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
11061.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11081.1Skamil
11091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11111.1Skamil
11121.35Skamil	switch (sigsent) {
11131.48Skamil	case SIGSTOP:
11141.48Skamil		validate_status_stopped(status, sigsent);
11151.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
11161.61Skre		    "child\n");
11171.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
11181.61Skre		    sizeof(info)) != -1);
11191.48Skamil
11201.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11211.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
11221.61Skre		    "si_errno=%#x\n",
11231.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11241.61Skre		    info.psi_siginfo.si_errno);
11251.48Skamil
11261.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11271.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11281.48Skamil
11291.48Skamil		DPRINTF("Before resuming the child process where it left off "
11301.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
11311.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
11321.48Skamil
11331.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11341.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
11351.61Skre		    child);
11361.48Skamil		/* FALLTHROUGH */
11371.35Skamil	case SIGCONT:
11381.35Skamil		validate_status_exited(status, exitval);
11391.35Skamil		break;
11401.35Skamil	default:
11411.35Skamil		validate_status_signaled(status, sigsent, expect_core);
11421.35Skamil		break;
11431.35Skamil	}
11441.1Skamil
11451.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11471.1Skamil}
11481.1Skamil
11491.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
11501.61SkreATF_TC(test);								\
11511.61SkreATF_TC_HEAD(test, tc)							\
11521.61Skre{									\
11531.61Skre	atf_tc_set_md_var(tc, "descr",					\
11541.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11551.61Skre	    "handled correctly in a child without a signal handler");	\
11561.61Skre}									\
11571.61Skre									\
11581.61SkreATF_TC_BODY(test, tc)							\
11591.61Skre{									\
11601.61Skre									\
11611.61Skre	traceme_sendsignal_simple(sig);					\
11621.35Skamil}
11631.35Skamil
11641.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
11651.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
11661.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
11671.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
11681.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
11691.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
11701.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
11711.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
11721.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
11731.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
11741.35Skamil
11751.35Skamil/// ----------------------------------------------------------------------------
11761.35Skamil
11771.37SkamilATF_TC(traceme_pid1_parent);
11781.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
11791.37Skamil{
11801.37Skamil	atf_tc_set_md_var(tc, "descr",
11811.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
11821.37Skamil}
11831.37Skamil
11841.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
11851.37Skamil{
11861.37Skamil	struct msg_fds parent_child;
11871.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
11881.37Skamil	pid_t child1, child2, wpid;
11891.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11901.37Skamil#if defined(TWAIT_HAVE_STATUS)
11911.37Skamil	int status;
11921.37Skamil#endif
11931.37Skamil
11941.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
11951.37Skamil
11961.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
11971.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
11981.37Skamil	if (child1 == 0) {
11991.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
12001.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
12011.37Skamil		if (child2 != 0) {
12021.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
12031.61Skre			    getpid(), child2);
12041.37Skamil			_exit(exitval_child1);
12051.37Skamil		}
12061.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
12071.37Skamil
12081.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
12091.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
12101.37Skamil
12111.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12121.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
12131.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
12141.37Skamil
12151.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
12161.37Skamil
12171.37Skamil		_exit(exitval_child2);
12181.37Skamil	}
12191.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
12201.37Skamil
12211.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12221.61Skre	TWAIT_REQUIRE_SUCCESS(
12231.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
12241.37Skamil
12251.37Skamil	validate_status_exited(status, exitval_child1);
12261.37Skamil
12271.37Skamil	DPRINTF("Notify that child1 is dead\n");
12281.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
12291.37Skamil
12301.37Skamil	DPRINTF("Wait for exiting of child2\n");
12311.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
12321.37Skamil}
12331.37Skamil
12341.37Skamil/// ----------------------------------------------------------------------------
12351.37Skamil
12361.40Skamilstatic void
12371.40Skamiltraceme_vfork_raise(int sigval)
12381.40Skamil{
12391.46Skamil	const int exitval = 5, exitval_watcher = 10;
12401.46Skamil	pid_t child, parent, watcher, wpid;
12411.46Skamil	int rv;
12421.40Skamil#if defined(TWAIT_HAVE_STATUS)
12431.40Skamil	int status;
12441.85Skamil
12451.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
12461.85Skamil	volatile int expect_core;
12471.85Skamil
12481.85Skamil	switch (sigval) {
12491.85Skamil	case SIGABRT:
12501.85Skamil	case SIGTRAP:
12511.85Skamil	case SIGBUS:
12521.85Skamil	case SIGILL:
12531.85Skamil	case SIGFPE:
12541.85Skamil	case SIGSEGV:
12551.85Skamil		expect_core = 1;
12561.85Skamil		break;
12571.85Skamil	default:
12581.85Skamil		expect_core = 0;
12591.85Skamil		break;
12601.85Skamil	}
12611.40Skamil#endif
12621.40Skamil
12631.46Skamil	/*
12641.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
12651.46Skamil	 * the SIGKILL signal to it.
12661.46Skamil	 *
12671.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
12681.46Skamil	 * simpler to reparent this process to initproc and forget about it.
12691.46Skamil	 */
12701.46Skamil	if (sigval == SIGSTOP) {
12711.46Skamil		parent = getpid();
12721.46Skamil
12731.46Skamil		watcher = fork();
12741.46Skamil		ATF_REQUIRE(watcher != 1);
12751.46Skamil		if (watcher == 0) {
12761.46Skamil			/* Double fork(2) trick to reparent to initproc */
12771.46Skamil			watcher = fork();
12781.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
12791.46Skamil			if (watcher != 0)
12801.46Skamil				_exit(exitval_watcher);
12811.46Skamil
12821.46Skamil			child = await_stopped_child(parent);
12831.46Skamil
12841.46Skamil			errno = 0;
12851.46Skamil			rv = kill(child, SIGKILL);
12861.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
12871.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
12881.46Skamil
12891.46Skamil			/* This exit value will be collected by initproc */
12901.46Skamil			_exit(0);
12911.46Skamil		}
12921.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12931.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
12941.61Skre		    watcher);
12951.46Skamil
12961.46Skamil		validate_status_exited(status, exitval_watcher);
12971.46Skamil
12981.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12991.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
13001.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
13011.46Skamil	}
13021.46Skamil
13031.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13041.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
13051.40Skamil	if (child == 0) {
13061.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13071.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13081.40Skamil
13091.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13101.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13111.40Skamil
13121.40Skamil		switch (sigval) {
13131.46Skamil		case SIGSTOP:
13141.40Skamil		case SIGKILL:
13151.40Skamil		case SIGABRT:
13161.40Skamil		case SIGHUP:
13171.85Skamil		case SIGTRAP:
13181.85Skamil		case SIGBUS:
13191.85Skamil		case SIGILL:
13201.85Skamil		case SIGFPE:
13211.85Skamil		case SIGSEGV:
13221.40Skamil			/* NOTREACHED */
13231.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
13241.70Smrg			__unreachable();
13251.40Skamil		default:
13261.40Skamil			DPRINTF("Before exiting of the child process\n");
13271.40Skamil			_exit(exitval);
13281.40Skamil		}
13291.40Skamil	}
13301.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13311.40Skamil
13321.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13331.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13341.40Skamil
13351.40Skamil	switch (sigval) {
13361.40Skamil	case SIGKILL:
13371.40Skamil	case SIGABRT:
13381.40Skamil	case SIGHUP:
13391.85Skamil	case SIGTRAP:
13401.85Skamil	case SIGBUS:
13411.85Skamil	case SIGILL:
13421.85Skamil	case SIGFPE:
13431.85Skamil	case SIGSEGV:
13441.40Skamil		validate_status_signaled(status, sigval, expect_core);
13451.40Skamil		break;
13461.40Skamil	case SIGSTOP:
13471.46Skamil		validate_status_signaled(status, SIGKILL, 0);
13481.46Skamil		break;
13491.40Skamil	case SIGCONT:
13501.47Skamil	case SIGTSTP:
13511.47Skamil	case SIGTTIN:
13521.47Skamil	case SIGTTOU:
13531.40Skamil		validate_status_exited(status, exitval);
13541.40Skamil		break;
13551.40Skamil	default:
13561.40Skamil		/* NOTREACHED */
13571.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
13581.40Skamil		break;
13591.40Skamil	}
13601.40Skamil
13611.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13621.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13631.40Skamil}
13641.40Skamil
13651.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
13661.61SkreATF_TC(test);								\
13671.61SkreATF_TC_HEAD(test, tc)							\
13681.61Skre{									\
13691.61Skre	atf_tc_set_md_var(tc, "descr",					\
13701.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
13711.61Skre	    "vfork(2)ed child");					\
13721.61Skre}									\
13731.61Skre									\
13741.61SkreATF_TC_BODY(test, tc)							\
13751.61Skre{									\
13761.61Skre									\
13771.61Skre	traceme_vfork_raise(sig);					\
13781.40Skamil}
13791.40Skamil
13801.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
13811.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
13821.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
13831.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
13841.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
13851.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
13861.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
13871.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
13881.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
13891.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
13901.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
13911.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
13921.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
13931.40Skamil
13941.40Skamil/// ----------------------------------------------------------------------------
13951.40Skamil
13961.52Skamilstatic void
13971.52Skamiltraceme_vfork_crash(int sig)
13981.41Skamil{
13991.41Skamil	pid_t child, wpid;
14001.41Skamil#if defined(TWAIT_HAVE_STATUS)
14011.41Skamil	int status;
14021.41Skamil#endif
14031.41Skamil
14041.71Skamil#ifndef PTRACE_ILLEGAL_ASM
14051.71Skamil	if (sig == SIGILL)
14061.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
14071.71Skamil#endif
14081.71Skamil
14091.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14101.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14111.41Skamil	if (child == 0) {
14121.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14131.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14141.41Skamil
14151.52Skamil		DPRINTF("Before executing a trap\n");
14161.52Skamil		switch (sig) {
14171.52Skamil		case SIGTRAP:
14181.52Skamil			trigger_trap();
14191.52Skamil			break;
14201.52Skamil		case SIGSEGV:
14211.52Skamil			trigger_segv();
14221.52Skamil			break;
14231.52Skamil		case SIGILL:
14241.52Skamil			trigger_ill();
14251.52Skamil			break;
14261.52Skamil		case SIGFPE:
14271.52Skamil			trigger_fpe();
14281.52Skamil			break;
14291.52Skamil		case SIGBUS:
14301.52Skamil			trigger_bus();
14311.52Skamil			break;
14321.52Skamil		default:
14331.52Skamil			/* NOTREACHED */
14341.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14351.52Skamil		}
14361.41Skamil
14371.41Skamil		/* NOTREACHED */
14381.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
14391.41Skamil	}
14401.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14411.41Skamil
14421.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14431.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14441.41Skamil
14451.52Skamil	validate_status_signaled(status, sig, 1);
14461.41Skamil
14471.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14481.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14491.41Skamil}
14501.41Skamil
14511.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
14521.61SkreATF_TC(test);								\
14531.61SkreATF_TC_HEAD(test, tc)							\
14541.61Skre{									\
14551.61Skre	atf_tc_set_md_var(tc, "descr",					\
14561.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
14571.61Skre	    "vfork(2)ed child");					\
14581.61Skre}									\
14591.61Skre									\
14601.61SkreATF_TC_BODY(test, tc)							\
14611.61Skre{									\
14621.61Skre									\
14631.61Skre	traceme_vfork_crash(sig);					\
14641.52Skamil}
14651.52Skamil
14661.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
14671.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
14681.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
14691.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
14701.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
14711.52Skamil
14721.41Skamil/// ----------------------------------------------------------------------------
14731.41Skamil
14741.43SkamilATF_TC(traceme_vfork_exec);
14751.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
14761.43Skamil{
14771.43Skamil	atf_tc_set_md_var(tc, "descr",
14781.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
14791.43Skamil}
14801.43Skamil
14811.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
14821.43Skamil{
14831.43Skamil	const int sigval = SIGTRAP;
14841.43Skamil	pid_t child, wpid;
14851.43Skamil#if defined(TWAIT_HAVE_STATUS)
14861.43Skamil	int status;
14871.43Skamil#endif
14881.61Skre	struct ptrace_siginfo info;
14891.43Skamil
14901.43Skamil	memset(&info, 0, sizeof(info));
14911.43Skamil
14921.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14931.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14941.43Skamil	if (child == 0) {
14951.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14961.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14971.43Skamil
14981.43Skamil		DPRINTF("Before calling execve(2) from child\n");
14991.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
15001.43Skamil
15011.43Skamil		/* NOTREACHED */
15021.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
15031.43Skamil	}
15041.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15051.43Skamil
15061.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15071.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15081.43Skamil
15091.43Skamil	validate_status_stopped(status, sigval);
15101.43Skamil
15111.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
15121.61Skre	SYSCALL_REQUIRE(
15131.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
15141.43Skamil
15151.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
15161.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
15171.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
15181.43Skamil	    info.psi_siginfo.si_errno);
15191.43Skamil
15201.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
15211.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
15221.43Skamil
15231.43Skamil	DPRINTF("Before resuming the child process where it left off and "
15241.43Skamil	    "without signal to be sent\n");
15251.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15261.43Skamil
15271.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15281.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15291.43Skamil
15301.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15311.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15321.43Skamil}
15331.43Skamil
15341.43Skamil/// ----------------------------------------------------------------------------
15351.43Skamil
15361.1Skamil#if defined(TWAIT_HAVE_PID)
15371.51Skamilstatic void
15381.59Skamilunrelated_tracer_sees_crash(int sig)
15391.59Skamil{
15401.59Skamil	struct msg_fds parent_tracee, parent_tracer;
15411.59Skamil	const int exitval = 10;
15421.59Skamil	pid_t tracee, tracer, wpid;
15431.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15441.59Skamil#if defined(TWAIT_HAVE_STATUS)
15451.59Skamil	int status;
15461.59Skamil#endif
15471.59Skamil	struct ptrace_siginfo info;
15481.61Skre
15491.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15501.71Skamil	if (sig == SIGILL)
15511.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15521.71Skamil#endif
15531.71Skamil
15541.59Skamil	memset(&info, 0, sizeof(info));
15551.59Skamil
15561.59Skamil	DPRINTF("Spawn tracee\n");
15571.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15581.59Skamil	tracee = atf_utils_fork();
15591.59Skamil	if (tracee == 0) {
15601.59Skamil		// Wait for parent to let us crash
15611.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
15621.61Skre
15631.59Skamil		DPRINTF("Before executing a trap\n");
15641.59Skamil		switch (sig) {
15651.59Skamil		case SIGTRAP:
15661.59Skamil			trigger_trap();
15671.59Skamil			break;
15681.59Skamil		case SIGSEGV:
15691.59Skamil			trigger_segv();
15701.59Skamil			break;
15711.59Skamil		case SIGILL:
15721.59Skamil			trigger_ill();
15731.59Skamil			break;
15741.59Skamil		case SIGFPE:
15751.59Skamil			trigger_fpe();
15761.59Skamil			break;
15771.59Skamil		case SIGBUS:
15781.59Skamil			trigger_bus();
15791.59Skamil			break;
15801.59Skamil		default:
15811.59Skamil			/* NOTREACHED */
15821.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15831.59Skamil		}
15841.59Skamil
15851.59Skamil		/* NOTREACHED */
15861.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15871.59Skamil	}
15881.59Skamil
15891.59Skamil	DPRINTF("Spawn debugger\n");
15901.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
15911.59Skamil	tracer = atf_utils_fork();
15921.59Skamil	if (tracer == 0) {
15931.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
15941.59Skamil		tracer = atf_utils_fork();
15951.59Skamil		if (tracer != 0)
15961.61Skre			_exit(exitval);
15971.59Skamil
15981.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
15991.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
16001.59Skamil
16011.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
16021.59Skamil		FORKEE_REQUIRE_SUCCESS(
16031.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
16041.59Skamil
16051.59Skamil		forkee_status_stopped(status, SIGSTOP);
16061.59Skamil
16071.59Skamil		/* Resume tracee with PT_CONTINUE */
16081.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
16091.59Skamil
16101.59Skamil		/* Inform parent that tracer has attached to tracee */
16111.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
16121.59Skamil
16131.59Skamil		/* Wait for parent to tell use that tracee should have exited */
16141.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
16151.59Skamil
16161.59Skamil		/* Wait for tracee and assert that it exited */
16171.59Skamil		FORKEE_REQUIRE_SUCCESS(
16181.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
16191.59Skamil
16201.59Skamil		validate_status_stopped(status, sig);
16211.59Skamil
16221.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
16231.61Skre		    "traced process\n");
16241.61Skre		SYSCALL_REQUIRE(
16251.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
16261.59Skamil
16271.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
16281.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
16291.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
16301.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
16311.59Skamil
16321.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
16331.59Skamil		switch (sig) {
16341.59Skamil		case SIGTRAP:
16351.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
16361.59Skamil			break;
16371.59Skamil		case SIGSEGV:
16381.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
16391.59Skamil			break;
16401.71Skamil		case SIGILL:
16411.71Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
16421.71Skamil			break;
16431.59Skamil		case SIGFPE:
16441.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
16451.59Skamil			break;
16461.59Skamil		case SIGBUS:
16471.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
16481.59Skamil			break;
16491.59Skamil		}
16501.59Skamil
16511.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
16521.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
16531.61Skre		TWAIT_REQUIRE_SUCCESS(
16541.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
16551.59Skamil
16561.59Skamil		validate_status_signaled(status, SIGKILL, 0);
16571.59Skamil
16581.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
16591.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
16601.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
16611.59Skamil
16621.71Skamil		/* Inform parent that tracer is exiting normally */
16631.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
16641.71Skamil
16651.59Skamil		DPRINTF("Before exiting of the tracer process\n");
16661.59Skamil		_exit(0 /* collect by initproc */);
16671.59Skamil	}
16681.59Skamil
16691.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
16701.59Skamil	    "calling %s()\n", TWAIT_FNAME);
16711.59Skamil	TWAIT_REQUIRE_SUCCESS(
16721.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
16731.59Skamil
16741.59Skamil	validate_status_exited(status, exitval);
16751.59Skamil
16761.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
16771.59Skamil	    TWAIT_FNAME);
16781.59Skamil	TWAIT_REQUIRE_SUCCESS(
16791.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
16801.59Skamil
16811.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
16821.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
16831.59Skamil
16841.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
16851.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
16861.59Skamil
16871.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
16881.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
16891.59Skamil
16901.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
16911.59Skamil	    TWAIT_FNAME);
16921.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
16931.59Skamil
16941.59Skamil	validate_status_signaled(status, SIGKILL, 0);
16951.59Skamil
16961.71Skamil	DPRINTF("Await normal exit of tracer\n");
16971.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
16981.71Skamil
16991.59Skamil	msg_close(&parent_tracer);
17001.59Skamil	msg_close(&parent_tracee);
17011.59Skamil}
17021.59Skamil
17031.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
17041.61SkreATF_TC(test);								\
17051.61SkreATF_TC_HEAD(test, tc)							\
17061.61Skre{									\
17071.61Skre	atf_tc_set_md_var(tc, "descr",					\
17081.61Skre	    "Assert that an unrelated tracer sees crash signal from the " \
17091.61Skre	    "debuggee");						\
17101.61Skre}									\
17111.61Skre									\
17121.61SkreATF_TC_BODY(test, tc)							\
17131.61Skre{									\
17141.61Skre									\
17151.61Skre	unrelated_tracer_sees_crash(sig);				\
17161.59Skamil}
17171.59Skamil
17181.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
17191.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
17201.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
17211.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
17221.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
17231.59Skamil#endif
17241.59Skamil
17251.59Skamil/// ----------------------------------------------------------------------------
17261.59Skamil
17271.59Skamil#if defined(TWAIT_HAVE_PID)
17281.59Skamilstatic void
17291.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
17301.67Skamil                                             bool stopped)
17311.1Skamil{
17321.51Skamil	/*
17331.51Skamil	 * notimeout - disable timeout in await zombie function
17341.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
17351.67Skamil	 * stopped - attach to a stopped process
17361.51Skamil	 */
17371.1Skamil
17381.1Skamil	struct msg_fds parent_tracee, parent_tracer;
17391.1Skamil	const int exitval_tracee = 5;
17401.1Skamil	const int exitval_tracer = 10;
17411.1Skamil	pid_t tracee, tracer, wpid;
17421.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
17431.1Skamil#if defined(TWAIT_HAVE_STATUS)
17441.1Skamil	int status;
17451.1Skamil#endif
17461.1Skamil
17471.67Skamil	/*
17481.67Skamil	 * Only a subset of options are supported.
17491.67Skamil	 */
17501.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
17511.67Skamil	            (!notimeout && unrelated && !stopped) ||
17521.67Skamil	            (notimeout && !unrelated && !stopped) ||
17531.67Skamil	            (!notimeout && unrelated && stopped));
17541.67Skamil
17551.13Schristos	DPRINTF("Spawn tracee\n");
17561.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
17571.1Skamil	tracee = atf_utils_fork();
17581.1Skamil	if (tracee == 0) {
17591.67Skamil		if (stopped) {
17601.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
17611.67Skamil			raise(SIGSTOP);
17621.67Skamil		}
17631.67Skamil
17641.1Skamil		// Wait for parent to let us exit
17651.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
17661.1Skamil		_exit(exitval_tracee);
17671.1Skamil	}
17681.1Skamil
17691.13Schristos	DPRINTF("Spawn debugger\n");
17701.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
17711.1Skamil	tracer = atf_utils_fork();
17721.1Skamil	if (tracer == 0) {
17731.51Skamil		if(unrelated) {
17741.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
17751.51Skamil			tracer = atf_utils_fork();
17761.51Skamil			if (tracer != 0)
17771.51Skamil				_exit(exitval_tracer);
17781.51Skamil		}
17791.51Skamil
17801.67Skamil		if (stopped) {
17811.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
17821.67Skamil			await_stopped(tracee);
17831.67Skamil		}
17841.67Skamil
17851.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
17861.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
17871.1Skamil
17881.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
17891.1Skamil		FORKEE_REQUIRE_SUCCESS(
17901.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17911.1Skamil
17921.1Skamil		forkee_status_stopped(status, SIGSTOP);
17931.1Skamil
17941.1Skamil		/* Resume tracee with PT_CONTINUE */
17951.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
17961.1Skamil
17971.1Skamil		/* Inform parent that tracer has attached to tracee */
17981.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
17991.1Skamil
18001.1Skamil		/* Wait for parent to tell use that tracee should have exited */
18011.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
18021.1Skamil
18031.1Skamil		/* Wait for tracee and assert that it exited */
18041.1Skamil		FORKEE_REQUIRE_SUCCESS(
18051.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
18061.1Skamil
18071.1Skamil		forkee_status_exited(status, exitval_tracee);
18081.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
18091.1Skamil
18101.13Schristos		DPRINTF("Before exiting of the tracer process\n");
18111.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
18121.51Skamil	}
18131.51Skamil
18141.51Skamil	if (unrelated) {
18151.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
18161.51Skamil		    "calling %s()\n", TWAIT_FNAME);
18171.51Skamil		TWAIT_REQUIRE_SUCCESS(
18181.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
18191.51Skamil
18201.51Skamil		validate_status_exited(status, exitval_tracer);
18211.51Skamil
18221.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
18231.51Skamil		    TWAIT_FNAME);
18241.51Skamil		TWAIT_REQUIRE_SUCCESS(
18251.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
18261.1Skamil	}
18271.1Skamil
18281.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
18291.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
18301.1Skamil
18311.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
18321.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
18331.1Skamil
18341.13Schristos	DPRINTF("Detect that tracee is zombie\n");
18351.51Skamil	if (notimeout)
18361.26Skamil		await_zombie_raw(tracee, 0);
18371.26Skamil	else
18381.26Skamil		await_zombie(tracee);
18391.1Skamil
18401.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
18411.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
18421.1Skamil	    TWAIT_FNAME);
18431.1Skamil	TWAIT_REQUIRE_SUCCESS(
18441.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
18451.1Skamil
18461.51Skamil	if (unrelated) {
18471.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
18481.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
18491.51Skamil	} else {
18501.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
18511.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
18521.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
18531.59Skamil			"%s()\n", TWAIT_FNAME);
18541.51Skamil
18551.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
18561.59Skamil			"tracee\n");
18571.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
18581.51Skamil		    tracer);
18591.1Skamil
18601.51Skamil		validate_status_exited(status, exitval_tracer);
18611.51Skamil	}
18621.1Skamil
18631.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
18641.1Skamil	    TWAIT_FNAME);
18651.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
18661.1Skamil
18671.1Skamil	validate_status_exited(status, exitval_tracee);
18681.1Skamil
18691.1Skamil	msg_close(&parent_tracer);
18701.1Skamil	msg_close(&parent_tracee);
18711.1Skamil}
18721.26Skamil
18731.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
18741.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
18751.51Skamil{
18761.51Skamil	atf_tc_set_md_var(tc, "descr",
18771.51Skamil	    "Assert that tracer sees process termination before the parent");
18781.51Skamil}
18791.51Skamil
18801.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
18811.26Skamil{
18821.26Skamil
18831.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
18841.26Skamil}
18851.26Skamil
18861.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
18871.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
18881.1Skamil{
18891.1Skamil	atf_tc_set_md_var(tc, "descr",
18901.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
18911.51Skamil	    "process and no other error is reported");
18921.1Skamil}
18931.1Skamil
18941.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
18951.1Skamil{
18961.51Skamil	time_t start, end;
18971.51Skamil	double diff;
18981.51Skamil	unsigned long N = 0;
18991.1Skamil
19001.51Skamil	/*
19011.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
19021.51Skamil	 * This test body isn't specific to this race, however it's just good
19031.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
19041.51Skamil	 */
19051.1Skamil
19061.51Skamil	start = time(NULL);
19071.51Skamil	while (true) {
19081.51Skamil		DPRINTF("Step: %lu\n", N);
19091.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
19101.67Skamil		                                             false);
19111.51Skamil		end = time(NULL);
19121.51Skamil		diff = difftime(end, start);
19131.51Skamil		if (diff >= 5.0)
19141.51Skamil			break;
19151.51Skamil		++N;
19161.1Skamil	}
19171.51Skamil	DPRINTF("Iterations: %lu\n", N);
19181.51Skamil}
19191.1Skamil
19201.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
19211.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
19221.51Skamil{
19231.51Skamil	atf_tc_set_md_var(tc, "descr",
19241.51Skamil	    "Assert that tracer sees process termination before the parent");
19251.51Skamil}
19261.1Skamil
19271.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
19281.51Skamil{
19291.1Skamil
19301.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
19311.67Skamil}
19321.67Skamil
19331.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
19341.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
19351.67Skamil{
19361.67Skamil	atf_tc_set_md_var(tc, "descr",
19371.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
19381.67Skamil}
19391.67Skamil
19401.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
19411.67Skamil{
19421.67Skamil
19431.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
19441.1Skamil}
19451.1Skamil#endif
19461.1Skamil
19471.51Skamil/// ----------------------------------------------------------------------------
19481.51Skamil
19491.66Skamilstatic void
19501.66Skamilparent_attach_to_its_child(bool stopped)
19511.1Skamil{
19521.1Skamil	struct msg_fds parent_tracee;
19531.1Skamil	const int exitval_tracee = 5;
19541.1Skamil	pid_t tracee, wpid;
19551.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19561.1Skamil#if defined(TWAIT_HAVE_STATUS)
19571.1Skamil	int status;
19581.1Skamil#endif
19591.1Skamil
19601.13Schristos	DPRINTF("Spawn tracee\n");
19611.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19621.1Skamil	tracee = atf_utils_fork();
19631.1Skamil	if (tracee == 0) {
19641.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
19651.13Schristos		DPRINTF("Parent should now attach to tracee\n");
19661.1Skamil
19671.66Skamil		if (stopped) {
19681.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
19691.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
19701.66Skamil		}
19711.66Skamil
19721.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
19731.1Skamil		/* Wait for message from the parent */
19741.1Skamil		_exit(exitval_tracee);
19751.1Skamil	}
19761.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
19771.57Skamil
19781.66Skamil	if (stopped) {
19791.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
19801.66Skamil		await_stopped(tracee);
19811.66Skamil	}
19821.66Skamil
19831.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
19841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
19851.1Skamil
19861.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
19871.1Skamil	    TWAIT_FNAME);
19881.1Skamil	TWAIT_REQUIRE_SUCCESS(
19891.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
19901.1Skamil
19911.1Skamil	validate_status_stopped(status, SIGSTOP);
19921.1Skamil
19931.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
19941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
19951.1Skamil
19961.13Schristos	DPRINTF("Let the tracee exit now\n");
19971.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
19981.1Skamil
19991.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
20001.1Skamil	TWAIT_REQUIRE_SUCCESS(
20011.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20021.1Skamil
20031.1Skamil	validate_status_exited(status, exitval_tracee);
20041.1Skamil
20051.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
20061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
20071.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
20081.1Skamil
20091.1Skamil	msg_close(&parent_tracee);
20101.1Skamil}
20111.1Skamil
20121.66SkamilATF_TC(parent_attach_to_its_child);
20131.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
20141.66Skamil{
20151.66Skamil	atf_tc_set_md_var(tc, "descr",
20161.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
20171.66Skamil}
20181.66Skamil
20191.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
20201.66Skamil{
20211.66Skamil
20221.66Skamil	parent_attach_to_its_child(false);
20231.66Skamil}
20241.66Skamil
20251.66SkamilATF_TC(parent_attach_to_its_stopped_child);
20261.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
20271.66Skamil{
20281.66Skamil	atf_tc_set_md_var(tc, "descr",
20291.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
20301.66Skamil}
20311.66Skamil
20321.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
20331.66Skamil{
20341.66Skamil
20351.66Skamil	parent_attach_to_its_child(true);
20361.66Skamil}
20371.66Skamil
20381.51Skamil/// ----------------------------------------------------------------------------
20391.51Skamil
20401.65Skamilstatic void
20411.65Skamilchild_attach_to_its_parent(bool stopped)
20421.1Skamil{
20431.1Skamil	struct msg_fds parent_tracee;
20441.1Skamil	const int exitval_tracer = 5;
20451.1Skamil	pid_t tracer, wpid;
20461.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
20471.1Skamil#if defined(TWAIT_HAVE_STATUS)
20481.1Skamil	int status;
20491.1Skamil#endif
20501.1Skamil
20511.13Schristos	DPRINTF("Spawn tracer\n");
20521.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
20531.1Skamil	tracer = atf_utils_fork();
20541.1Skamil	if (tracer == 0) {
20551.1Skamil		/* Wait for message from the parent */
20561.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
20571.1Skamil
20581.65Skamil		if (stopped) {
20591.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
20601.65Skamil			        getppid());
20611.65Skamil			await_stopped(getppid());
20621.65Skamil		}
20631.65Skamil
20641.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
20651.1Skamil		    getppid());
20661.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
20671.1Skamil
20681.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
20691.1Skamil		    TWAIT_FNAME);
20701.1Skamil		FORKEE_REQUIRE_SUCCESS(
20711.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
20721.1Skamil
20731.1Skamil		forkee_status_stopped(status, SIGSTOP);
20741.1Skamil
20751.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
20761.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
20771.1Skamil		    != -1);
20781.1Skamil
20791.1Skamil		/* Tell parent we are ready */
20801.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
20811.1Skamil
20821.1Skamil		_exit(exitval_tracer);
20831.1Skamil	}
20841.1Skamil
20851.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
20861.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
20871.65Skamil
20881.65Skamil	if (stopped) {
20891.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
20901.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
20911.65Skamil	}
20921.65Skamil
20931.13Schristos	DPRINTF("Allow the tracer to exit now\n");
20941.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
20951.1Skamil
20961.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
20971.1Skamil	TWAIT_REQUIRE_SUCCESS(
20981.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
20991.1Skamil
21001.1Skamil	validate_status_exited(status, exitval_tracer);
21011.1Skamil
21021.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
21031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
21041.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
21051.1Skamil
21061.1Skamil	msg_close(&parent_tracee);
21071.1Skamil}
21081.1Skamil
21091.65SkamilATF_TC(child_attach_to_its_parent);
21101.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
21111.65Skamil{
21121.65Skamil	atf_tc_set_md_var(tc, "descr",
21131.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
21141.65Skamil}
21151.65Skamil
21161.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
21171.65Skamil{
21181.65Skamil
21191.65Skamil	child_attach_to_its_parent(false);
21201.65Skamil}
21211.65Skamil
21221.65SkamilATF_TC(child_attach_to_its_stopped_parent);
21231.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
21241.65Skamil{
21251.65Skamil	atf_tc_set_md_var(tc, "descr",
21261.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
21271.65Skamil}
21281.65Skamil
21291.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
21301.65Skamil{
21311.65Skamil	/*
21321.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
21331.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
21341.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
21351.65Skamil	 *
21361.65Skamil	 * As a workaround spawn this test as a subprocess.
21371.65Skamil	 */
21381.65Skamil
21391.65Skamil	const int exitval = 15;
21401.65Skamil	pid_t child, wpid;
21411.65Skamil#if defined(TWAIT_HAVE_STATUS)
21421.65Skamil	int status;
21431.65Skamil#endif
21441.65Skamil
21451.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
21461.65Skamil	if (child == 0) {
21471.65Skamil		child_attach_to_its_parent(true);
21481.65Skamil		_exit(exitval);
21491.65Skamil	} else {
21501.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21511.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21521.65Skamil
21531.65Skamil		validate_status_exited(status, exitval);
21541.65Skamil
21551.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
21561.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21571.65Skamil	}
21581.65Skamil}
21591.65Skamil
21601.51Skamil/// ----------------------------------------------------------------------------
21611.51Skamil
21621.1Skamil#if defined(TWAIT_HAVE_PID)
21631.1Skamil
21641.51Skamilenum tracee_sees_its_original_parent_type {
21651.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
21661.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
21671.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
21681.51Skamil};
21691.51Skamil
21701.51Skamilstatic void
21711.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
21721.1Skamil{
21731.1Skamil	struct msg_fds parent_tracer, parent_tracee;
21741.1Skamil	const int exitval_tracee = 5;
21751.1Skamil	const int exitval_tracer = 10;
21761.1Skamil	pid_t parent, tracee, tracer, wpid;
21771.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
21781.1Skamil#if defined(TWAIT_HAVE_STATUS)
21791.1Skamil	int status;
21801.1Skamil#endif
21811.51Skamil	/* sysctl(3) - kinfo_proc2 */
21821.51Skamil	int name[CTL_MAXNAME];
21831.51Skamil	struct kinfo_proc2 kp;
21841.51Skamil	size_t len = sizeof(kp);
21851.51Skamil	unsigned int namelen;
21861.51Skamil
21871.51Skamil	/* procfs - status  */
21881.51Skamil	FILE *fp;
21891.51Skamil	struct stat st;
21901.51Skamil	const char *fname = "/proc/curproc/status";
21911.51Skamil	char s_executable[MAXPATHLEN];
21921.51Skamil	int s_pid, s_ppid;
21931.51Skamil	int rv;
21941.51Skamil
21951.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
21961.61Skre		SYSCALL_REQUIRE(
21971.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
21981.61Skre		if (rv != 0)
21991.51Skamil			atf_tc_skip("/proc/curproc/status not found");
22001.51Skamil	}
22011.1Skamil
22021.13Schristos	DPRINTF("Spawn tracee\n");
22031.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
22041.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
22051.1Skamil	tracee = atf_utils_fork();
22061.1Skamil	if (tracee == 0) {
22071.1Skamil		parent = getppid();
22081.1Skamil
22091.1Skamil		/* Emit message to the parent */
22101.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
22111.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
22121.1Skamil
22131.51Skamil		switch (type) {
22141.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
22151.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
22161.51Skamil			break;
22171.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
22181.51Skamil			namelen = 0;
22191.51Skamil			name[namelen++] = CTL_KERN;
22201.51Skamil			name[namelen++] = KERN_PROC2;
22211.51Skamil			name[namelen++] = KERN_PROC_PID;
22221.51Skamil			name[namelen++] = getpid();
22231.51Skamil			name[namelen++] = len;
22241.51Skamil			name[namelen++] = 1;
22251.51Skamil
22261.61Skre			FORKEE_ASSERT_EQ(
22271.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
22281.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
22291.51Skamil			break;
22301.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
22311.51Skamil			/*
22321.51Skamil			 * Format:
22331.51Skamil			 *  EXECUTABLE PID PPID ...
22341.51Skamil			 */
22351.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
22361.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
22371.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
22381.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
22391.51Skamil			break;
22401.51Skamil		}
22411.1Skamil
22421.1Skamil		_exit(exitval_tracee);
22431.1Skamil	}
22441.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
22451.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
22461.1Skamil
22471.13Schristos	DPRINTF("Spawn debugger\n");
22481.1Skamil	tracer = atf_utils_fork();
22491.1Skamil	if (tracer == 0) {
22501.1Skamil		/* No IPC to communicate with the child */
22511.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
22521.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
22531.1Skamil
22541.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
22551.1Skamil		FORKEE_REQUIRE_SUCCESS(
22561.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22571.1Skamil
22581.1Skamil		forkee_status_stopped(status, SIGSTOP);
22591.1Skamil
22601.1Skamil		/* Resume tracee with PT_CONTINUE */
22611.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
22621.1Skamil
22631.1Skamil		/* Inform parent that tracer has attached to tracee */
22641.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
22651.1Skamil
22661.1Skamil		/* Wait for parent to tell use that tracee should have exited */
22671.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
22681.1Skamil
22691.1Skamil		/* Wait for tracee and assert that it exited */
22701.1Skamil		FORKEE_REQUIRE_SUCCESS(
22711.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22721.1Skamil
22731.1Skamil		forkee_status_exited(status, exitval_tracee);
22741.1Skamil
22751.13Schristos		DPRINTF("Before exiting of the tracer process\n");
22761.1Skamil		_exit(exitval_tracer);
22771.1Skamil	}
22781.1Skamil
22791.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
22801.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
22811.1Skamil
22821.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
22831.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
22841.1Skamil
22851.13Schristos	DPRINTF("Detect that tracee is zombie\n");
22861.1Skamil	await_zombie(tracee);
22871.1Skamil
22881.13Schristos	DPRINTF("Assert that there is no status about tracee - "
22891.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
22901.1Skamil	TWAIT_REQUIRE_SUCCESS(
22911.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
22921.1Skamil
22931.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
22941.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
22951.1Skamil
22961.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
22971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
22981.1Skamil	    tracer);
22991.1Skamil
23001.1Skamil	validate_status_exited(status, exitval_tracer);
23011.1Skamil
23021.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
23031.1Skamil	    TWAIT_FNAME);
23041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
23051.1Skamil	    tracee);
23061.1Skamil
23071.1Skamil	validate_status_exited(status, exitval_tracee);
23081.1Skamil
23091.1Skamil	msg_close(&parent_tracer);
23101.1Skamil	msg_close(&parent_tracee);
23111.1Skamil}
23121.1Skamil
23131.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
23141.61SkreATF_TC(test);								\
23151.61SkreATF_TC_HEAD(test, tc)							\
23161.61Skre{									\
23171.61Skre	atf_tc_set_md_var(tc, "descr",					\
23181.61Skre	    "Assert that tracee sees its original parent when being traced " \
23191.61Skre	    "(check " descr ")");					\
23201.61Skre}									\
23211.61Skre									\
23221.61SkreATF_TC_BODY(test, tc)							\
23231.61Skre{									\
23241.61Skre									\
23251.61Skre	tracee_sees_its_original_parent(type);				\
23261.1Skamil}
23271.1Skamil
23281.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
23291.51Skamil	tracee_sees_its_original_parent_getppid,
23301.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
23311.51Skamil	"getppid(2)");
23321.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
23331.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
23341.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
23351.51Skamil	"sysctl(3) and kinfo_proc2");
23361.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
23371.51Skamil	tracee_sees_its_original_parent_procfs_status,
23381.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
23391.51Skamil	"the status file in procfs");
23401.1Skamil#endif
23411.1Skamil
23421.51Skamil/// ----------------------------------------------------------------------------
23431.1Skamil
23441.53Skamilstatic void
23451.53Skamileventmask_preserved(int event)
23461.1Skamil{
23471.1Skamil	const int exitval = 5;
23481.1Skamil	const int sigval = SIGSTOP;
23491.1Skamil	pid_t child, wpid;
23501.1Skamil#if defined(TWAIT_HAVE_STATUS)
23511.1Skamil	int status;
23521.1Skamil#endif
23531.1Skamil	ptrace_event_t set_event, get_event;
23541.1Skamil	const int len = sizeof(ptrace_event_t);
23551.1Skamil
23561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23581.1Skamil	if (child == 0) {
23591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23611.1Skamil
23621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23641.1Skamil
23651.13Schristos		DPRINTF("Before exiting of the child process\n");
23661.1Skamil		_exit(exitval);
23671.1Skamil	}
23681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23691.1Skamil
23701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23721.1Skamil
23731.1Skamil	validate_status_stopped(status, sigval);
23741.1Skamil
23751.53Skamil	set_event.pe_set_event = event;
23761.61Skre	SYSCALL_REQUIRE(
23771.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
23781.61Skre	SYSCALL_REQUIRE(
23791.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
23801.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
23811.1Skamil
23821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23831.1Skamil	    "without signal to be sent\n");
23841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23851.1Skamil
23861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23881.1Skamil
23891.1Skamil	validate_status_exited(status, exitval);
23901.1Skamil
23911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23931.1Skamil}
23941.1Skamil
23951.61Skre#define EVENTMASK_PRESERVED(test, event)				\
23961.61SkreATF_TC(test);								\
23971.61SkreATF_TC_HEAD(test, tc)							\
23981.61Skre{									\
23991.61Skre	atf_tc_set_md_var(tc, "descr",					\
24001.61Skre	    "Verify that eventmask " #event " is preserved");		\
24011.61Skre}									\
24021.61Skre									\
24031.61SkreATF_TC_BODY(test, tc)							\
24041.61Skre{									\
24051.61Skre									\
24061.61Skre	eventmask_preserved(event);					\
24071.1Skamil}
24081.1Skamil
24091.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
24101.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
24111.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
24121.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
24131.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
24141.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
24151.1Skamil
24161.53Skamil/// ----------------------------------------------------------------------------
24171.1Skamil
24181.28Skamilstatic void
24191.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
24201.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
24211.1Skamil{
24221.1Skamil	const int exitval = 5;
24231.1Skamil	const int exitval2 = 15;
24241.1Skamil	const int sigval = SIGSTOP;
24251.31Skamil	pid_t child, child2 = 0, wpid;
24261.1Skamil#if defined(TWAIT_HAVE_STATUS)
24271.1Skamil	int status;
24281.1Skamil#endif
24291.1Skamil	ptrace_state_t state;
24301.1Skamil	const int slen = sizeof(state);
24311.1Skamil	ptrace_event_t event;
24321.1Skamil	const int elen = sizeof(event);
24331.1Skamil
24341.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24351.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24361.1Skamil	if (child == 0) {
24371.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24381.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24391.1Skamil
24401.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24411.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24421.1Skamil
24431.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
24441.1Skamil
24451.1Skamil		if (child2 == 0)
24461.1Skamil			_exit(exitval2);
24471.1Skamil
24481.1Skamil		FORKEE_REQUIRE_SUCCESS
24491.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
24501.1Skamil
24511.1Skamil		forkee_status_exited(status, exitval2);
24521.1Skamil
24531.13Schristos		DPRINTF("Before exiting of the child process\n");
24541.1Skamil		_exit(exitval);
24551.1Skamil	}
24561.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24571.1Skamil
24581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24601.1Skamil
24611.1Skamil	validate_status_stopped(status, sigval);
24621.1Skamil
24631.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
24641.61Skre	    trackfork ? "|PTRACE_FORK" : "",
24651.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
24661.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
24671.30Skamil	event.pe_set_event = 0;
24681.30Skamil	if (trackfork)
24691.30Skamil		event.pe_set_event |= PTRACE_FORK;
24701.30Skamil	if (trackvfork)
24711.30Skamil		event.pe_set_event |= PTRACE_VFORK;
24721.30Skamil	if (trackvforkdone)
24731.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
24741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
24751.1Skamil
24761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24771.1Skamil	    "without signal to be sent\n");
24781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24791.1Skamil
24801.29Skamil#if defined(TWAIT_HAVE_PID)
24811.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
24821.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
24831.61Skre		    child);
24841.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
24851.61Skre		    child);
24861.1Skamil
24871.29Skamil		validate_status_stopped(status, SIGTRAP);
24881.1Skamil
24891.61Skre		SYSCALL_REQUIRE(
24901.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
24911.31Skamil		if (trackfork && fn == fork) {
24921.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
24931.30Skamil			       PTRACE_FORK);
24941.30Skamil		}
24951.31Skamil		if (trackvfork && fn == vfork) {
24961.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
24971.30Skamil			       PTRACE_VFORK);
24981.30Skamil		}
24991.29Skamil
25001.29Skamil		child2 = state.pe_other_pid;
25011.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
25021.29Skamil
25031.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
25041.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
25051.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
25061.29Skamil		    child2);
25071.1Skamil
25081.29Skamil		validate_status_stopped(status, SIGTRAP);
25091.1Skamil
25101.61Skre		SYSCALL_REQUIRE(
25111.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
25121.31Skamil		if (trackfork && fn == fork) {
25131.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
25141.30Skamil			       PTRACE_FORK);
25151.30Skamil		}
25161.31Skamil		if (trackvfork && fn == vfork) {
25171.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
25181.30Skamil			       PTRACE_VFORK);
25191.30Skamil		}
25201.30Skamil
25211.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
25221.29Skamil
25231.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
25241.29Skamil		    "and without signal to be sent\n");
25251.61Skre		SYSCALL_REQUIRE(
25261.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
25271.29Skamil
25281.29Skamil		DPRINTF("Before resuming the child process where it left off "
25291.61Skre		    "and without signal to be sent\n");
25301.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25311.30Skamil	}
25321.30Skamil#endif
25331.30Skamil
25341.31Skamil	if (trackvforkdone && fn == vfork) {
25351.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
25361.61Skre		    child);
25371.61Skre		TWAIT_REQUIRE_SUCCESS(
25381.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
25391.30Skamil
25401.30Skamil		validate_status_stopped(status, SIGTRAP);
25411.30Skamil
25421.61Skre		SYSCALL_REQUIRE(
25431.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
25441.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
25451.30Skamil
25461.30Skamil		child2 = state.pe_other_pid;
25471.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
25481.61Skre		    child2);
25491.30Skamil
25501.30Skamil		DPRINTF("Before resuming the child process where it left off "
25511.61Skre		    "and without signal to be sent\n");
25521.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25531.30Skamil	}
25541.29Skamil
25551.30Skamil#if defined(TWAIT_HAVE_PID)
25561.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
25571.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
25581.61Skre		    "\n", TWAIT_FNAME);
25591.61Skre		TWAIT_REQUIRE_SUCCESS(
25601.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
25611.29Skamil
25621.29Skamil		validate_status_exited(status, exitval2);
25631.29Skamil
25641.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
25651.61Skre		    "process\n", TWAIT_FNAME);
25661.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
25671.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
25681.29Skamil	}
25691.29Skamil#endif
25701.1Skamil
25711.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
25721.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
25731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25741.1Skamil
25751.1Skamil	validate_status_stopped(status, SIGCHLD);
25761.1Skamil
25771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25781.1Skamil	    "without signal to be sent\n");
25791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25801.1Skamil
25811.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
25821.1Skamil	    TWAIT_FNAME);
25831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25841.1Skamil
25851.1Skamil	validate_status_exited(status, exitval);
25861.1Skamil
25871.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
25881.1Skamil	    TWAIT_FNAME);
25891.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25901.1Skamil}
25911.28Skamil
25921.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
25931.61SkreATF_TC(name);								\
25941.61SkreATF_TC_HEAD(name, tc)							\
25951.61Skre{									\
25961.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
25971.61Skre}									\
25981.61Skre									\
25991.61SkreATF_TC_BODY(name, tc)							\
26001.61Skre{									\
26011.61Skre									\
26021.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
26031.32Skamil}
26041.32Skamil
26051.32Skamil#define F false
26061.32Skamil#define T true
26071.32Skamil
26081.32Skamil#define F_IF__0(x)
26091.32Skamil#define F_IF__1(x) x
26101.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
26111.32Skamil#define F_IF_(x,y) F_IF__(x,y)
26121.32Skamil#define F_IF(x,y) F_IF_(x,y)
26131.32Skamil
26141.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
26151.61Skre	"Verify " #function "(2) called with 0"				\
26161.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
26171.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
26181.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
26191.61Skre	" in EVENT_MASK."						\
26201.61Skre	F_IF(dchildbit," Detach child in this test.")			\
26211.61Skre	F_IF(dparentbit," Detach parent in this test.")
26221.1Skamil
26231.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
26241.31Skamil#if defined(TWAIT_HAVE_PID)
26251.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
26261.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
26271.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
26281.31Skamil#endif
26291.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
26301.31Skamil#if defined(TWAIT_HAVE_PID)
26311.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
26321.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
26331.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
26341.31Skamil#endif
26351.1Skamil
26361.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
26371.31Skamil#if defined(TWAIT_HAVE_PID)
26381.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
26391.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
26401.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
26411.31Skamil#endif
26421.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
26431.31Skamil#if defined(TWAIT_HAVE_PID)
26441.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
26451.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
26461.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
26471.31Skamil#endif
26481.31Skamil
26491.54Skamil/// ----------------------------------------------------------------------------
26501.31Skamil
26511.54Skamilenum bytes_transfer_type {
26521.54Skamil	BYTES_TRANSFER_DATA,
26531.54Skamil	BYTES_TRANSFER_DATAIO,
26541.54Skamil	BYTES_TRANSFER_TEXT,
26551.54Skamil	BYTES_TRANSFER_TEXTIO,
26561.54Skamil	BYTES_TRANSFER_AUXV
26571.54Skamil};
26581.31Skamil
26591.54Skamilstatic int __used
26601.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
26611.54Skamil{
26621.54Skamil	int e, f, g, h;
26631.1Skamil
26641.54Skamil	a *= 4;
26651.54Skamil	b += 3;
26661.54Skamil	c -= 2;
26671.54Skamil	d /= 1;
26681.1Skamil
26691.54Skamil	e = strtol("10", NULL, 10);
26701.54Skamil	f = strtol("20", NULL, 10);
26711.54Skamil	g = strtol("30", NULL, 10);
26721.54Skamil	h = strtol("40", NULL, 10);
26731.1Skamil
26741.54Skamil	return (a + b * c - d) + (e * f - g / h);
26751.1Skamil}
26761.1Skamil
26771.54Skamilstatic void
26781.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
26791.1Skamil{
26801.1Skamil	const int exitval = 5;
26811.1Skamil	const int sigval = SIGSTOP;
26821.1Skamil	pid_t child, wpid;
26831.54Skamil	bool skip = false;
26841.1Skamil
26851.54Skamil	int lookup_me = 0;
26861.54Skamil	uint8_t lookup_me8 = 0;
26871.54Skamil	uint16_t lookup_me16 = 0;
26881.54Skamil	uint32_t lookup_me32 = 0;
26891.54Skamil	uint64_t lookup_me64 = 0;
26901.1Skamil
26911.54Skamil	int magic = 0x13579246;
26921.54Skamil	uint8_t magic8 = 0xab;
26931.54Skamil	uint16_t magic16 = 0x1234;
26941.54Skamil	uint32_t magic32 = 0x98765432;
26951.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
26961.1Skamil
26971.54Skamil	struct ptrace_io_desc io;
26981.1Skamil#if defined(TWAIT_HAVE_STATUS)
26991.1Skamil	int status;
27001.1Skamil#endif
27011.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
27021.60Skre	AuxInfo ai[513], *aip;
27031.55Schristos
27041.55Schristos	ATF_REQUIRE(size < sizeof(ai));
27051.1Skamil
27061.54Skamil	/* Prepare variables for .TEXT transfers */
27071.54Skamil	switch (type) {
27081.54Skamil	case BYTES_TRANSFER_TEXT:
27091.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
27101.54Skamil		break;
27111.54Skamil	case BYTES_TRANSFER_TEXTIO:
27121.54Skamil		switch (size) {
27131.54Skamil		case 8:
27141.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
27151.54Skamil			break;
27161.54Skamil		case 16:
27171.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
27181.54Skamil			break;
27191.54Skamil		case 32:
27201.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
27211.54Skamil			break;
27221.54Skamil		case 64:
27231.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
27241.54Skamil			break;
27251.54Skamil		}
27261.54Skamil		break;
27271.54Skamil	default:
27281.54Skamil		break;
27291.54Skamil	}
27301.1Skamil
27311.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
27321.54Skamil	switch (type) {
27331.54Skamil	case BYTES_TRANSFER_TEXTIO:
27341.54Skamil	case BYTES_TRANSFER_DATAIO:
27351.54Skamil		io.piod_op = operation;
27361.54Skamil		switch (size) {
27371.54Skamil		case 8:
27381.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
27391.54Skamil			               (void *)bytes_transfer_dummy :
27401.54Skamil			               &lookup_me8;
27411.54Skamil			io.piod_addr = &lookup_me8;
27421.54Skamil			io.piod_len = sizeof(lookup_me8);
27431.54Skamil			break;
27441.54Skamil		case 16:
27451.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
27461.54Skamil			               (void *)bytes_transfer_dummy :
27471.54Skamil			               &lookup_me16;
27481.54Skamil			io.piod_addr = &lookup_me16;
27491.54Skamil			io.piod_len = sizeof(lookup_me16);
27501.54Skamil			break;
27511.54Skamil		case 32:
27521.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
27531.54Skamil			               (void *)bytes_transfer_dummy :
27541.54Skamil			               &lookup_me32;
27551.54Skamil			io.piod_addr = &lookup_me32;
27561.54Skamil			io.piod_len = sizeof(lookup_me32);
27571.54Skamil			break;
27581.54Skamil		case 64:
27591.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
27601.54Skamil			               (void *)bytes_transfer_dummy :
27611.54Skamil			               &lookup_me64;
27621.54Skamil			io.piod_addr = &lookup_me64;
27631.54Skamil			io.piod_len = sizeof(lookup_me64);
27641.54Skamil			break;
27651.54Skamil		default:
27661.54Skamil			break;
27671.54Skamil		}
27681.54Skamil		break;
27691.54Skamil	case BYTES_TRANSFER_AUXV:
27701.54Skamil		io.piod_op = operation;
27711.54Skamil		io.piod_offs = 0;
27721.54Skamil		io.piod_addr = ai;
27731.54Skamil		io.piod_len = size;
27741.54Skamil		break;
27751.54Skamil	default:
27761.54Skamil		break;
27771.1Skamil	}
27781.1Skamil
27791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27811.1Skamil	if (child == 0) {
27821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27841.1Skamil
27851.54Skamil		switch (type) {
27861.54Skamil		case BYTES_TRANSFER_DATA:
27871.54Skamil			switch (operation) {
27881.54Skamil			case PT_READ_D:
27891.54Skamil			case PT_READ_I:
27901.54Skamil				lookup_me = magic;
27911.54Skamil				break;
27921.54Skamil			default:
27931.54Skamil				break;
27941.54Skamil			}
27951.54Skamil			break;
27961.54Skamil		case BYTES_TRANSFER_DATAIO:
27971.54Skamil			switch (operation) {
27981.54Skamil			case PIOD_READ_D:
27991.54Skamil			case PIOD_READ_I:
28001.54Skamil				switch (size) {
28011.54Skamil				case 8:
28021.54Skamil					lookup_me8 = magic8;
28031.54Skamil					break;
28041.54Skamil				case 16:
28051.54Skamil					lookup_me16 = magic16;
28061.54Skamil					break;
28071.54Skamil				case 32:
28081.54Skamil					lookup_me32 = magic32;
28091.54Skamil					break;
28101.54Skamil				case 64:
28111.54Skamil					lookup_me64 = magic64;
28121.54Skamil					break;
28131.54Skamil				default:
28141.54Skamil					break;
28151.54Skamil				}
28161.54Skamil				break;
28171.54Skamil			default:
28181.54Skamil				break;
28191.54Skamil			}
28201.54Skamil		default:
28211.54Skamil			break;
28221.54Skamil		}
28231.54Skamil
28241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28261.1Skamil
28271.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
28281.54Skamil		switch (type) {
28291.54Skamil		case BYTES_TRANSFER_DATA:
28301.54Skamil			switch (operation) {
28311.54Skamil			case PT_WRITE_D:
28321.54Skamil			case PT_WRITE_I:
28331.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
28341.54Skamil				break;
28351.54Skamil			default:
28361.54Skamil				break;
28371.54Skamil			}
28381.54Skamil			break;
28391.54Skamil		case BYTES_TRANSFER_DATAIO:
28401.54Skamil			switch (operation) {
28411.54Skamil			case PIOD_WRITE_D:
28421.54Skamil			case PIOD_WRITE_I:
28431.54Skamil				switch (size) {
28441.54Skamil				case 8:
28451.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
28461.54Skamil					break;
28471.54Skamil				case 16:
28481.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
28491.54Skamil					break;
28501.54Skamil				case 32:
28511.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
28521.54Skamil					break;
28531.54Skamil				case 64:
28541.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
28551.54Skamil					break;
28561.54Skamil				default:
28571.54Skamil					break;
28581.54Skamil				}
28591.54Skamil				break;
28601.54Skamil			default:
28611.54Skamil				break;
28621.54Skamil			}
28631.54Skamil			break;
28641.54Skamil		case BYTES_TRANSFER_TEXT:
28651.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
28661.54Skamil			                     sizeof(magic)) == 0);
28671.54Skamil			break;
28681.54Skamil		case BYTES_TRANSFER_TEXTIO:
28691.54Skamil			switch (size) {
28701.54Skamil			case 8:
28711.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
28721.54Skamil				                     bytes_transfer_dummy,
28731.54Skamil				                     sizeof(magic8)) == 0);
28741.54Skamil				break;
28751.54Skamil			case 16:
28761.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
28771.54Skamil				                     bytes_transfer_dummy,
28781.54Skamil				                     sizeof(magic16)) == 0);
28791.54Skamil				break;
28801.54Skamil			case 32:
28811.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
28821.54Skamil				                     bytes_transfer_dummy,
28831.54Skamil				                     sizeof(magic32)) == 0);
28841.54Skamil				break;
28851.54Skamil			case 64:
28861.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
28871.54Skamil				                     bytes_transfer_dummy,
28881.54Skamil				                     sizeof(magic64)) == 0);
28891.54Skamil				break;
28901.54Skamil			}
28911.54Skamil			break;
28921.54Skamil		default:
28931.54Skamil			break;
28941.54Skamil		}
28951.54Skamil
28961.13Schristos		DPRINTF("Before exiting of the child process\n");
28971.1Skamil		_exit(exitval);
28981.1Skamil	}
28991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29001.1Skamil
29011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29031.1Skamil
29041.1Skamil	validate_status_stopped(status, sigval);
29051.1Skamil
29061.54Skamil	/* Check PaX MPROTECT */
29071.54Skamil	if (!can_we_write_to_text(child)) {
29081.54Skamil		switch (type) {
29091.54Skamil		case BYTES_TRANSFER_TEXTIO:
29101.54Skamil			switch (operation) {
29111.54Skamil			case PIOD_WRITE_D:
29121.54Skamil			case PIOD_WRITE_I:
29131.54Skamil				skip = true;
29141.54Skamil				break;
29151.54Skamil			default:
29161.54Skamil				break;
29171.54Skamil			}
29181.54Skamil			break;
29191.54Skamil		case BYTES_TRANSFER_TEXT:
29201.54Skamil			switch (operation) {
29211.54Skamil			case PT_WRITE_D:
29221.54Skamil			case PT_WRITE_I:
29231.54Skamil				skip = true;
29241.54Skamil				break;
29251.54Skamil			default:
29261.54Skamil				break;
29271.54Skamil			}
29281.54Skamil			break;
29291.54Skamil		default:
29301.54Skamil			break;
29311.54Skamil		}
29321.54Skamil	}
29331.1Skamil
29341.54Skamil	/* Bailout cleanly killing the child process */
29351.54Skamil	if (skip) {
29361.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
29371.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29381.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
29391.54Skamil		                      child);
29401.1Skamil
29411.54Skamil		validate_status_signaled(status, SIGKILL, 0);
29421.1Skamil
29431.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
29441.54Skamil	}
29451.1Skamil
29461.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
29471.54Skamil	       "parent=%d\n", child, getpid());
29481.1Skamil
29491.54Skamil	switch (type) {
29501.54Skamil	case BYTES_TRANSFER_TEXTIO:
29511.54Skamil	case BYTES_TRANSFER_DATAIO:
29521.54Skamil	case BYTES_TRANSFER_AUXV:
29531.54Skamil		switch (operation) {
29541.54Skamil		case PIOD_WRITE_D:
29551.54Skamil		case PIOD_WRITE_I:
29561.54Skamil			switch (size) {
29571.54Skamil			case 8:
29581.54Skamil				lookup_me8 = magic8;
29591.54Skamil				break;
29601.54Skamil			case 16:
29611.54Skamil				lookup_me16 = magic16;
29621.54Skamil				break;
29631.54Skamil			case 32:
29641.54Skamil				lookup_me32 = magic32;
29651.54Skamil				break;
29661.54Skamil			case 64:
29671.54Skamil				lookup_me64 = magic64;
29681.54Skamil				break;
29691.54Skamil			default:
29701.54Skamil				break;
29711.54Skamil			}
29721.54Skamil			break;
29731.54Skamil		default:
29741.54Skamil			break;
29751.54Skamil		}
29761.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
29771.54Skamil		switch (operation) {
29781.54Skamil		case PIOD_READ_D:
29791.54Skamil		case PIOD_READ_I:
29801.54Skamil			switch (size) {
29811.54Skamil			case 8:
29821.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
29831.54Skamil				break;
29841.54Skamil			case 16:
29851.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
29861.54Skamil				break;
29871.54Skamil			case 32:
29881.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
29891.54Skamil				break;
29901.54Skamil			case 64:
29911.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
29921.54Skamil				break;
29931.54Skamil			default:
29941.54Skamil				break;
29951.54Skamil			}
29961.54Skamil			break;
29971.54Skamil		case PIOD_READ_AUXV:
29981.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
29991.54Skamil			        io.piod_len);
30001.54Skamil			ATF_REQUIRE(io.piod_len > 0);
30011.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
30021.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
30031.54Skamil				    (long long int)aip->a_type,
30041.54Skamil				    (long long int)aip->a_v);
30051.54Skamil			break;
30061.54Skamil		default:
30071.54Skamil			break;
30081.54Skamil		}
30091.54Skamil		break;
30101.54Skamil	case BYTES_TRANSFER_TEXT:
30111.54Skamil		switch (operation) {
30121.54Skamil		case PT_READ_D:
30131.54Skamil		case PT_READ_I:
30141.54Skamil			errno = 0;
30151.54Skamil			lookup_me = ptrace(operation, child,
30161.54Skamil			                   bytes_transfer_dummy, 0);
30171.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
30181.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
30191.54Skamil			break;
30201.54Skamil		case PT_WRITE_D:
30211.54Skamil		case PT_WRITE_I:
30221.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
30231.54Skamil			                       bytes_transfer_dummy, magic)
30241.54Skamil			                != -1);
30251.54Skamil			break;
30261.54Skamil		default:
30271.54Skamil			break;
30281.54Skamil		}
30291.54Skamil		break;
30301.54Skamil	case BYTES_TRANSFER_DATA:
30311.54Skamil		switch (operation) {
30321.54Skamil		case PT_READ_D:
30331.54Skamil		case PT_READ_I:
30341.54Skamil			errno = 0;
30351.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
30361.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
30371.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
30381.54Skamil			break;
30391.54Skamil		case PT_WRITE_D:
30401.54Skamil		case PT_WRITE_I:
30411.54Skamil			lookup_me = magic;
30421.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
30431.54Skamil			                       magic) != -1);
30441.54Skamil			break;
30451.54Skamil		default:
30461.54Skamil			break;
30471.54Skamil		}
30481.54Skamil		break;
30491.54Skamil	default:
30501.54Skamil		break;
30511.54Skamil	}
30521.1Skamil
30531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30541.1Skamil	    "without signal to be sent\n");
30551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30561.1Skamil
30571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30591.1Skamil
30601.1Skamil	validate_status_exited(status, exitval);
30611.1Skamil
30621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30641.1Skamil}
30651.1Skamil
30661.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
30671.61SkreATF_TC(test);								\
30681.61SkreATF_TC_HEAD(test, tc)							\
30691.61Skre{									\
30701.61Skre	atf_tc_set_md_var(tc, "descr",					\
30711.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
30721.61Skre	    " of type " #type);						\
30731.61Skre}									\
30741.61Skre									\
30751.61SkreATF_TC_BODY(test, tc)							\
30761.61Skre{									\
30771.61Skre									\
30781.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
30791.1Skamil}
30801.1Skamil
30811.54Skamil// DATA
30821.1Skamil
30831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
30841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
30851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
30861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
30871.54Skamil
30881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
30891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
30901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
30911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
30921.54Skamil
30931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
30941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
30951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
30961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
30971.54Skamil
30981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
30991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
31001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
31011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
31021.54Skamil
31031.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
31041.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
31051.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
31061.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
31071.54Skamil
31081.54Skamil// TEXT
31091.54Skamil
31101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
31111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
31121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
31131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
31141.54Skamil
31151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
31161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
31171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
31181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
31191.54Skamil
31201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
31211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
31221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
31231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
31241.54Skamil
31251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
31261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
31271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
31281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
31291.54Skamil
31301.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
31311.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
31321.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
31331.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
31341.1Skamil
31351.54Skamil// AUXV
31361.1Skamil
31371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
31381.1Skamil
31391.54Skamil/// ----------------------------------------------------------------------------
31401.1Skamil
31411.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
31421.72Skamilstatic void
31431.72Skamilaccess_regs(const char *regset, const char *aux)
31441.1Skamil{
31451.1Skamil	const int exitval = 5;
31461.1Skamil	const int sigval = SIGSTOP;
31471.1Skamil	pid_t child, wpid;
31481.1Skamil#if defined(TWAIT_HAVE_STATUS)
31491.1Skamil	int status;
31501.1Skamil#endif
31511.72Skamil#if defined(HAVE_GPREGS)
31521.72Skamil	struct reg gpr;
31531.76Sscole	register_t rgstr;
31541.1Skamil#endif
31551.72Skamil#if defined(HAVE_FPREGS)
31561.72Skamil	struct fpreg fpr;
31571.1Skamil#endif
31581.76Sscole
31591.72Skamil#if !defined(HAVE_GPREGS)
31601.72Skamil	if (strcmp(regset, "regs") == 0)
31611.72Skamil		atf_tc_fail("Impossible test scenario!");
31621.1Skamil#endif
31631.1Skamil
31641.72Skamil#if !defined(HAVE_FPREGS)
31651.72Skamil	if (strcmp(regset, "fpregs") == 0)
31661.72Skamil		atf_tc_fail("Impossible test scenario!");
31671.1Skamil#endif
31681.1Skamil
31691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31711.1Skamil	if (child == 0) {
31721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31741.1Skamil
31751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31771.1Skamil
31781.13Schristos		DPRINTF("Before exiting of the child process\n");
31791.1Skamil		_exit(exitval);
31801.1Skamil	}
31811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31821.1Skamil
31831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31851.1Skamil
31861.1Skamil	validate_status_stopped(status, sigval);
31871.1Skamil
31881.1Skamil#if defined(HAVE_GPREGS)
31891.72Skamil	if (strcmp(regset, "regs") == 0) {
31901.72Skamil		DPRINTF("Call GETREGS for the child process\n");
31911.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
31921.72Skamil
31931.72Skamil		if (strcmp(aux, "none") == 0) {
31941.72Skamil			DPRINTF("Retrieved registers\n");
31951.72Skamil		} else if (strcmp(aux, "pc") == 0) {
31961.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
31971.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
31981.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
31991.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
32001.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
32011.72Skamil		} else if (strcmp(aux, "sp") == 0) {
32021.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
32031.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
32041.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
32051.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
32061.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
32071.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
32081.72Skamil			DPRINTF("Call SETREGS for the child process\n");
32091.72Skamil			SYSCALL_REQUIRE(
32101.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
32111.72Skamil		}
32121.72Skamil	}
32131.1Skamil#endif
32141.1Skamil
32151.72Skamil#if defined(HAVE_FPREGS)
32161.72Skamil	if (strcmp(regset, "fpregs") == 0) {
32171.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
32181.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
32191.72Skamil
32201.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
32211.72Skamil			DPRINTF("Retrieved FP registers\n");
32221.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
32231.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
32241.72Skamil			SYSCALL_REQUIRE(
32251.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
32261.72Skamil		}
32271.1Skamil	}
32281.1Skamil#endif
32291.1Skamil
32301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32311.1Skamil	    "without signal to be sent\n");
32321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32331.1Skamil
32341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32361.1Skamil
32371.1Skamil	validate_status_exited(status, exitval);
32381.1Skamil
32391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32411.1Skamil}
32421.1Skamil
32431.72Skamil#define ACCESS_REGS(test, regset, aux)					\
32441.72SkamilATF_TC(test);								\
32451.72SkamilATF_TC_HEAD(test, tc)							\
32461.72Skamil{									\
32471.72Skamil        atf_tc_set_md_var(tc, "descr",					\
32481.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
32491.72Skamil}									\
32501.72Skamil									\
32511.72SkamilATF_TC_BODY(test, tc)							\
32521.72Skamil{									\
32531.72Skamil									\
32541.72Skamil        access_regs(regset, aux);					\
32551.1Skamil}
32561.1Skamil#endif
32571.1Skamil
32581.72Skamil#if defined(HAVE_GPREGS)
32591.72SkamilACCESS_REGS(access_regs1, "regs", "none")
32601.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
32611.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
32621.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
32631.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
32641.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
32651.1Skamil#endif
32661.1Skamil#if defined(HAVE_FPREGS)
32671.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
32681.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
32691.1Skamil#endif
32701.1Skamil
32711.72Skamil/// ----------------------------------------------------------------------------
32721.1Skamil
32731.1Skamil#if defined(PT_STEP)
32741.1Skamilstatic void
32751.2Skamilptrace_step(int N, int setstep)
32761.1Skamil{
32771.1Skamil	const int exitval = 5;
32781.1Skamil	const int sigval = SIGSTOP;
32791.1Skamil	pid_t child, wpid;
32801.1Skamil#if defined(TWAIT_HAVE_STATUS)
32811.1Skamil	int status;
32821.1Skamil#endif
32831.1Skamil	int happy;
32841.81Skamil	struct ptrace_siginfo info;
32851.1Skamil
32861.1Skamil#if defined(__arm__)
32871.1Skamil	/* PT_STEP not supported on arm 32-bit */
32881.1Skamil	atf_tc_expect_fail("PR kern/52119");
32891.1Skamil#endif
32901.1Skamil
32911.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32921.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32931.1Skamil	if (child == 0) {
32941.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32951.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32961.1Skamil
32971.1Skamil		happy = check_happy(999);
32981.1Skamil
32991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33011.1Skamil
33021.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
33031.1Skamil
33041.13Schristos		DPRINTF("Before exiting of the child process\n");
33051.1Skamil		_exit(exitval);
33061.1Skamil	}
33071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33081.1Skamil
33091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33111.1Skamil
33121.1Skamil	validate_status_stopped(status, sigval);
33131.1Skamil
33141.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
33151.81Skamil	SYSCALL_REQUIRE(
33161.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
33171.81Skamil
33181.81Skamil	DPRINTF("Before checking siginfo_t\n");
33191.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
33201.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
33211.81Skamil
33221.1Skamil	while (N --> 0) {
33231.2Skamil		if (setstep) {
33241.13Schristos			DPRINTF("Before resuming the child process where it "
33251.2Skamil			    "left off and without signal to be sent (use "
33261.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
33271.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
33281.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
33291.2Skamil			    != -1);
33301.2Skamil		} else {
33311.13Schristos			DPRINTF("Before resuming the child process where it "
33321.2Skamil			    "left off and without signal to be sent (use "
33331.2Skamil			    "PT_STEP)\n");
33341.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
33351.2Skamil			    != -1);
33361.2Skamil		}
33371.1Skamil
33381.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33391.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
33401.1Skamil		    child);
33411.1Skamil
33421.1Skamil		validate_status_stopped(status, SIGTRAP);
33431.2Skamil
33441.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
33451.81Skamil		SYSCALL_REQUIRE(
33461.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
33471.81Skamil
33481.81Skamil		DPRINTF("Before checking siginfo_t\n");
33491.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
33501.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
33511.81Skamil
33521.2Skamil		if (setstep) {
33531.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
33541.2Skamil		}
33551.1Skamil	}
33561.1Skamil
33571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33581.1Skamil	    "without signal to be sent\n");
33591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33601.1Skamil
33611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33631.1Skamil
33641.1Skamil	validate_status_exited(status, exitval);
33651.1Skamil
33661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33681.1Skamil}
33691.1Skamil
33701.73Skamil#define PTRACE_STEP(test, N, setstep)					\
33711.73SkamilATF_TC(test);								\
33721.73SkamilATF_TC_HEAD(test, tc)							\
33731.73Skamil{									\
33741.73Skamil        atf_tc_set_md_var(tc, "descr",					\
33751.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
33761.73Skamil}									\
33771.73Skamil									\
33781.73SkamilATF_TC_BODY(test, tc)							\
33791.73Skamil{									\
33801.73Skamil									\
33811.73Skamil        ptrace_step(N, setstep);					\
33821.1Skamil}
33831.1Skamil
33841.73SkamilPTRACE_STEP(step1, 1, 0)
33851.73SkamilPTRACE_STEP(step2, 2, 0)
33861.73SkamilPTRACE_STEP(step3, 3, 0)
33871.73SkamilPTRACE_STEP(step4, 4, 0)
33881.73SkamilPTRACE_STEP(setstep1, 1, 1)
33891.73SkamilPTRACE_STEP(setstep2, 2, 1)
33901.73SkamilPTRACE_STEP(setstep3, 3, 1)
33911.73SkamilPTRACE_STEP(setstep4, 4, 1)
33921.1Skamil#endif
33931.1Skamil
33941.73Skamil/// ----------------------------------------------------------------------------
33951.1Skamil
33961.75Skamilstatic void
33971.75Skamilptrace_kill(const char *type)
33981.1Skamil{
33991.75Skamil	const int sigval = SIGSTOP;
34001.1Skamil	pid_t child, wpid;
34011.1Skamil#if defined(TWAIT_HAVE_STATUS)
34021.1Skamil	int status;
34031.1Skamil#endif
34041.1Skamil
34051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34071.1Skamil	if (child == 0) {
34081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34101.1Skamil
34111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34131.1Skamil
34141.1Skamil		/* NOTREACHED */
34151.1Skamil		FORKEE_ASSERTX(0 &&
34161.1Skamil		    "Child should be terminated by a signal from its parent");
34171.1Skamil	}
34181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34191.1Skamil
34201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34221.1Skamil
34231.1Skamil	validate_status_stopped(status, sigval);
34241.1Skamil
34251.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
34261.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
34271.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
34281.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
34291.75Skamil		kill(child, SIGKILL);
34301.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
34311.75Skamil		setpgid(child, 0);
34321.75Skamil		killpg(getpgid(child), SIGKILL);
34331.75Skamil	}
34341.1Skamil
34351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34371.1Skamil
34381.75Skamil	validate_status_signaled(status, SIGKILL, 0);
34391.1Skamil
34401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34421.1Skamil}
34431.1Skamil
34441.75Skamil#define PTRACE_KILL(test, type)						\
34451.75SkamilATF_TC(test);								\
34461.75SkamilATF_TC_HEAD(test, tc)							\
34471.75Skamil{									\
34481.75Skamil        atf_tc_set_md_var(tc, "descr",					\
34491.75Skamil            "Verify killing the child with " type);			\
34501.75Skamil}									\
34511.75Skamil									\
34521.75SkamilATF_TC_BODY(test, tc)							\
34531.75Skamil{									\
34541.75Skamil									\
34551.75Skamil        ptrace_kill(type);						\
34561.1Skamil}
34571.1Skamil
34581.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
34591.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
34601.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
34611.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
34621.1Skamil
34631.75Skamil/// ----------------------------------------------------------------------------
34641.1Skamil
34651.77Skamilstatic void
34661.77Skamiltraceme_lwpinfo(const int threads)
34671.1Skamil{
34681.1Skamil	const int sigval = SIGSTOP;
34691.77Skamil	const int sigval2 = SIGINT;
34701.1Skamil	pid_t child, wpid;
34711.1Skamil#if defined(TWAIT_HAVE_STATUS)
34721.1Skamil	int status;
34731.1Skamil#endif
34741.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
34751.77Skamil	struct ptrace_siginfo info;
34761.77Skamil
34771.77Skamil	/* Maximum number of supported threads in this test */
34781.77Skamil	pthread_t t[3];
34791.77Skamil	int n, rv;
34801.77Skamil
34811.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
34821.1Skamil
34831.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34841.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34851.1Skamil	if (child == 0) {
34861.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34871.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34881.1Skamil
34891.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34901.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34911.1Skamil
34921.77Skamil		for (n = 0; n < threads; n++) {
34931.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
34941.77Skamil			FORKEE_ASSERT(rv == 0);
34951.77Skamil		}
34961.77Skamil
34971.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
34981.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
34991.77Skamil
35001.77Skamil		/* NOTREACHED */
35011.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
35021.1Skamil	}
35031.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35041.1Skamil
35051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35071.1Skamil
35081.1Skamil	validate_status_stopped(status, sigval);
35091.1Skamil
35101.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
35111.77Skamil	SYSCALL_REQUIRE(
35121.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35131.77Skamil
35141.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35151.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35161.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35171.77Skamil	    info.psi_siginfo.si_errno);
35181.77Skamil
35191.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
35201.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
35211.77Skamil
35221.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
35231.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
35241.1Skamil
35251.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
35261.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
35271.1Skamil
35281.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
35291.77Skamil	    lwp.pl_lwpid);
35301.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
35311.1Skamil
35321.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
35331.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
35341.1Skamil
35351.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
35361.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
35371.1Skamil
35381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35391.1Skamil	    "without signal to be sent\n");
35401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35411.1Skamil
35421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35441.1Skamil
35451.77Skamil	validate_status_stopped(status, sigval2);
35461.77Skamil
35471.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
35481.77Skamil	SYSCALL_REQUIRE(
35491.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35501.77Skamil
35511.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35521.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35531.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35541.77Skamil	    info.psi_siginfo.si_errno);
35551.77Skamil
35561.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
35571.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
35581.77Skamil
35591.77Skamil	memset(&lwp, 0, sizeof(lwp));
35601.77Skamil
35611.77Skamil	for (n = 0; n <= threads; n++) {
35621.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
35631.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
35641.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
35651.77Skamil
35661.77Skamil		DPRINTF("Assert that the thread exists\n");
35671.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
35681.77Skamil
35691.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
35701.77Skamil		    lwp.pl_lwpid);
35711.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
35721.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
35731.77Skamil	}
35741.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
35751.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
35761.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
35771.77Skamil
35781.77Skamil	DPRINTF("Assert that there are no more threads\n");
35791.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
35801.77Skamil
35811.77Skamil	DPRINTF("Before resuming the child process where it left off and "
35821.77Skamil	    "without signal to be sent\n");
35831.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
35841.77Skamil
35851.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35861.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35871.77Skamil
35881.77Skamil	validate_status_signaled(status, SIGKILL, 0);
35891.1Skamil
35901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35921.1Skamil}
35931.1Skamil
35941.77Skamil#define TRACEME_LWPINFO(test, threads)					\
35951.77SkamilATF_TC(test);								\
35961.77SkamilATF_TC_HEAD(test, tc)							\
35971.77Skamil{									\
35981.77Skamil	atf_tc_set_md_var(tc, "descr",					\
35991.77Skamil	    "Verify LWPINFO with the child with " #threads		\
36001.77Skamil	    " spawned extra threads");					\
36011.77Skamil}									\
36021.77Skamil									\
36031.77SkamilATF_TC_BODY(test, tc)							\
36041.77Skamil{									\
36051.77Skamil									\
36061.77Skamil	traceme_lwpinfo(threads);					\
36071.1Skamil}
36081.1Skamil
36091.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
36101.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
36111.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
36121.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
36131.77Skamil
36141.77Skamil/// ----------------------------------------------------------------------------
36151.77Skamil
36161.77Skamil#if defined(TWAIT_HAVE_PID)
36171.77Skamilstatic void
36181.77Skamilattach_lwpinfo(const int threads)
36191.1Skamil{
36201.77Skamil	const int sigval = SIGINT;
36211.1Skamil	struct msg_fds parent_tracee, parent_tracer;
36221.1Skamil	const int exitval_tracer = 10;
36231.1Skamil	pid_t tracee, tracer, wpid;
36241.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
36251.1Skamil#if defined(TWAIT_HAVE_STATUS)
36261.1Skamil	int status;
36271.1Skamil#endif
36281.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
36291.77Skamil	struct ptrace_siginfo info;
36301.77Skamil
36311.77Skamil	/* Maximum number of supported threads in this test */
36321.77Skamil	pthread_t t[3];
36331.77Skamil	int n, rv;
36341.1Skamil
36351.13Schristos	DPRINTF("Spawn tracee\n");
36361.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
36371.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
36381.1Skamil	tracee = atf_utils_fork();
36391.1Skamil	if (tracee == 0) {
36401.1Skamil		/* Wait for message from the parent */
36411.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
36421.1Skamil
36431.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
36441.77Skamil
36451.77Skamil		for (n = 0; n < threads; n++) {
36461.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
36471.77Skamil			FORKEE_ASSERT(rv == 0);
36481.77Skamil		}
36491.77Skamil
36501.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
36511.77Skamil
36521.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36531.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36541.77Skamil
36551.77Skamil		/* NOTREACHED */
36561.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
36571.1Skamil	}
36581.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
36591.1Skamil
36601.13Schristos	DPRINTF("Spawn debugger\n");
36611.1Skamil	tracer = atf_utils_fork();
36621.1Skamil	if (tracer == 0) {
36631.1Skamil		/* No IPC to communicate with the child */
36641.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
36651.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
36661.1Skamil
36671.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
36681.1Skamil		FORKEE_REQUIRE_SUCCESS(
36691.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
36701.1Skamil
36711.1Skamil		forkee_status_stopped(status, SIGSTOP);
36721.1Skamil
36731.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
36741.77Skamil		    "tracee");
36751.77Skamil		FORKEE_ASSERT(
36761.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
36771.77Skamil
36781.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36791.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
36801.77Skamil		    "si_errno=%#x\n",
36811.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36821.77Skamil		    info.psi_siginfo.si_errno);
36831.77Skamil
36841.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
36851.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
36861.77Skamil
36871.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
36881.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
36891.1Skamil		    != -1);
36901.1Skamil
36911.13Schristos		DPRINTF("Assert that there exists a thread\n");
36921.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
36931.1Skamil
36941.13Schristos		DPRINTF("Assert that lwp thread %d received event "
36951.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
36961.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
36971.1Skamil
36981.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
36991.77Skamil		    "tracee\n");
37001.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
37011.1Skamil		    != -1);
37021.1Skamil
37031.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
37041.77Skamil		    "tracee\n");
37051.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
37061.1Skamil
37071.1Skamil		/* Resume tracee with PT_CONTINUE */
37081.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
37091.1Skamil
37101.1Skamil		/* Inform parent that tracer has attached to tracee */
37111.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
37121.77Skamil
37131.1Skamil		/* Wait for parent */
37141.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
37151.1Skamil
37161.77Skamil		/* Wait for tracee and assert that it raised a signal */
37171.77Skamil		FORKEE_REQUIRE_SUCCESS(
37181.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
37191.77Skamil
37201.77Skamil		forkee_status_stopped(status, SIGINT);
37211.77Skamil
37221.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
37231.77Skamil		    "child");
37241.77Skamil		FORKEE_ASSERT(
37251.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
37261.77Skamil
37271.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37281.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
37291.77Skamil		    "si_errno=%#x\n",
37301.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37311.77Skamil		    info.psi_siginfo.si_errno);
37321.77Skamil
37331.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
37341.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
37351.77Skamil
37361.77Skamil		memset(&lwp, 0, sizeof(lwp));
37371.77Skamil
37381.77Skamil		for (n = 0; n <= threads; n++) {
37391.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
37401.77Skamil			    "child\n");
37411.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
37421.77Skamil			    sizeof(lwp)) != -1);
37431.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
37441.77Skamil
37451.77Skamil			DPRINTF("Assert that the thread exists\n");
37461.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
37471.77Skamil
37481.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
37491.77Skamil			    "event\n", lwp.pl_lwpid);
37501.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
37511.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
37521.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
37531.77Skamil		}
37541.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
37551.77Skamil		    "tracee\n");
37561.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
37571.77Skamil		    != -1);
37581.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
37591.77Skamil
37601.77Skamil		DPRINTF("Assert that there are no more threads\n");
37611.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
37621.77Skamil
37631.77Skamil		DPRINTF("Before resuming the child process where it left off "
37641.77Skamil		    "and without signal to be sent\n");
37651.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
37661.77Skamil		    != -1);
37671.77Skamil
37681.1Skamil		/* Wait for tracee and assert that it exited */
37691.1Skamil		FORKEE_REQUIRE_SUCCESS(
37701.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
37711.1Skamil
37721.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
37731.1Skamil
37741.13Schristos		DPRINTF("Before exiting of the tracer process\n");
37751.1Skamil		_exit(exitval_tracer);
37761.1Skamil	}
37771.1Skamil
37781.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
37791.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
37801.1Skamil
37811.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
37821.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
37831.77Skamil
37841.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
37851.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
37861.1Skamil
37871.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
37881.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
37891.1Skamil
37901.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
37911.1Skamil	    TWAIT_FNAME);
37921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
37931.1Skamil	    tracer);
37941.1Skamil
37951.1Skamil	validate_status_exited(status, exitval_tracer);
37961.1Skamil
37971.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
37981.1Skamil	    TWAIT_FNAME);
37991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
38001.1Skamil	    tracee);
38011.1Skamil
38021.77Skamil	validate_status_signaled(status, SIGKILL, 0);
38031.1Skamil
38041.1Skamil	msg_close(&parent_tracer);
38051.1Skamil	msg_close(&parent_tracee);
38061.1Skamil}
38071.77Skamil
38081.77Skamil#define ATTACH_LWPINFO(test, threads)					\
38091.77SkamilATF_TC(test);								\
38101.77SkamilATF_TC_HEAD(test, tc)							\
38111.77Skamil{									\
38121.77Skamil	atf_tc_set_md_var(tc, "descr",					\
38131.77Skamil	    "Verify LWPINFO with the child with " #threads		\
38141.77Skamil	    " spawned extra threads (tracer is not the original "	\
38151.77Skamil	    "parent)");							\
38161.77Skamil}									\
38171.77Skamil									\
38181.77SkamilATF_TC_BODY(test, tc)							\
38191.77Skamil{									\
38201.77Skamil									\
38211.77Skamil	attach_lwpinfo(threads);					\
38221.77Skamil}
38231.77Skamil
38241.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
38251.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
38261.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
38271.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
38281.1Skamil#endif
38291.1Skamil
38301.77Skamil/// ----------------------------------------------------------------------------
38311.77Skamil
38321.1Skamilstatic void
38331.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
38341.1Skamil{
38351.1Skamil	const int exitval = 5;
38361.1Skamil	const int sigval = SIGINT;
38371.1Skamil	const int sigfaked = SIGTRAP;
38381.1Skamil	const int sicodefaked = TRAP_BRKPT;
38391.1Skamil	pid_t child, wpid;
38401.1Skamil	struct sigaction sa;
38411.1Skamil#if defined(TWAIT_HAVE_STATUS)
38421.1Skamil	int status;
38431.1Skamil#endif
38441.1Skamil	struct ptrace_siginfo info;
38451.1Skamil	memset(&info, 0, sizeof(info));
38461.1Skamil
38471.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38481.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38491.1Skamil	if (child == 0) {
38501.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38511.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38521.1Skamil
38531.79Skamil		sa.sa_sigaction = sah;
38541.1Skamil		sa.sa_flags = SA_SIGINFO;
38551.1Skamil		sigemptyset(&sa.sa_mask);
38561.1Skamil
38571.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
38581.79Skamil		    != -1);
38591.1Skamil
38601.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38611.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38621.1Skamil
38631.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
38641.1Skamil
38651.13Schristos		DPRINTF("Before exiting of the child process\n");
38661.1Skamil		_exit(exitval);
38671.1Skamil	}
38681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38691.1Skamil
38701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38721.1Skamil
38731.1Skamil	validate_status_stopped(status, sigval);
38741.1Skamil
38751.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38761.61Skre	SYSCALL_REQUIRE(
38771.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38781.1Skamil
38791.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
38801.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
38811.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
38821.1Skamil	    info.psi_siginfo.si_errno);
38831.1Skamil
38841.79Skamil	if (faked) {
38851.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
38861.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
38871.79Skamil		info.psi_siginfo.si_signo = sigfaked;
38881.79Skamil		info.psi_siginfo.si_code = sicodefaked;
38891.79Skamil	}
38901.1Skamil
38911.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
38921.61Skre	SYSCALL_REQUIRE(
38931.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
38941.1Skamil
38951.79Skamil	if (faked) {
38961.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
38971.79Skamil		    "child\n");
38981.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
38991.79Skamil		    sizeof(info)) != -1);
39001.1Skamil
39011.79Skamil		DPRINTF("Before checking siginfo_t\n");
39021.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
39031.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
39041.79Skamil	}
39051.1Skamil
39061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39071.1Skamil	    "without signal to be sent\n");
39081.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
39091.79Skamil	    faked ? sigfaked : sigval) != -1);
39101.1Skamil
39111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39131.1Skamil
39141.1Skamil	validate_status_exited(status, exitval);
39151.1Skamil
39161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39181.1Skamil}
39191.1Skamil
39201.79Skamil#define PTRACE_SIGINFO(test, faked)					\
39211.79SkamilATF_TC(test);								\
39221.79SkamilATF_TC_HEAD(test, tc)							\
39231.79Skamil{									\
39241.79Skamil	atf_tc_set_md_var(tc, "descr",					\
39251.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
39261.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
39271.79Skamil}									\
39281.79Skamil									\
39291.79Skamilstatic int test##_caught = 0;						\
39301.79Skamil									\
39311.79Skamilstatic void								\
39321.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
39331.79Skamil{									\
39341.79Skamil	if (faked) {							\
39351.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
39361.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
39371.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
39381.79Skamil	} else {							\
39391.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
39401.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
39411.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
39421.79Skamil	}								\
39431.79Skamil									\
39441.79Skamil	++ test##_caught;						\
39451.79Skamil}									\
39461.79Skamil									\
39471.79SkamilATF_TC_BODY(test, tc)							\
39481.79Skamil{									\
39491.79Skamil									\
39501.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
39511.79Skamil}
39521.79Skamil
39531.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
39541.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
39551.79Skamil
39561.79Skamil/// ----------------------------------------------------------------------------
39571.79Skamil
39581.82SkamilATF_TC(traceme_exec);
39591.82SkamilATF_TC_HEAD(traceme_exec, tc)
39601.1Skamil{
39611.1Skamil	atf_tc_set_md_var(tc, "descr",
39621.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
39631.1Skamil}
39641.1Skamil
39651.82SkamilATF_TC_BODY(traceme_exec, tc)
39661.1Skamil{
39671.1Skamil	const int sigval = SIGTRAP;
39681.1Skamil	pid_t child, wpid;
39691.1Skamil#if defined(TWAIT_HAVE_STATUS)
39701.1Skamil	int status;
39711.1Skamil#endif
39721.1Skamil
39731.1Skamil	struct ptrace_siginfo info;
39741.1Skamil	memset(&info, 0, sizeof(info));
39751.1Skamil
39761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39781.1Skamil	if (child == 0) {
39791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39811.1Skamil
39821.13Schristos		DPRINTF("Before calling execve(2) from child\n");
39831.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
39841.1Skamil
39851.1Skamil		FORKEE_ASSERT(0 && "Not reached");
39861.1Skamil	}
39871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39881.1Skamil
39891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39911.1Skamil
39921.1Skamil	validate_status_stopped(status, sigval);
39931.1Skamil
39941.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39951.61Skre	SYSCALL_REQUIRE(
39961.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39971.1Skamil
39981.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
39991.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
40001.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
40011.1Skamil	    info.psi_siginfo.si_errno);
40021.1Skamil
40031.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
40041.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
40051.1Skamil
40061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40071.1Skamil	    "without signal to be sent\n");
40081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40091.1Skamil
40101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40121.1Skamil
40131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40151.1Skamil}
40161.1Skamil
40171.82Skamil/// ----------------------------------------------------------------------------
40181.82Skamil
40191.83Skamilstatic volatile int done;
40201.1Skamil
40211.83Skamilstatic void *
40221.83Skamiltrace_threads_cb(void *arg __unused)
40231.1Skamil{
40241.1Skamil
40251.83Skamil	done++;
40261.83Skamil
40271.83Skamil	while (done < 3)
40281.83Skamil		continue;
40291.83Skamil
40301.83Skamil	return NULL;
40311.1Skamil}
40321.1Skamil
40331.83Skamilstatic void
40341.83Skamiltrace_threads(bool trace_create, bool trace_exit)
40351.1Skamil{
40361.1Skamil	const int sigval = SIGSTOP;
40371.1Skamil	pid_t child, wpid;
40381.1Skamil#if defined(TWAIT_HAVE_STATUS)
40391.1Skamil	int status;
40401.1Skamil#endif
40411.1Skamil	ptrace_state_t state;
40421.1Skamil	const int slen = sizeof(state);
40431.1Skamil	ptrace_event_t event;
40441.1Skamil	const int elen = sizeof(event);
40451.83Skamil	struct ptrace_siginfo info;
40461.83Skamil
40471.83Skamil	pthread_t t[3];
40481.83Skamil	int rv;
40491.83Skamil	size_t n;
40501.1Skamil	lwpid_t lid;
40511.83Skamil
40521.83Skamil	/* Track created and exited threads */
40531.83Skamil	bool traced_lwps[__arraycount(t)];
40541.83Skamil
40551.83Skamil	atf_tc_skip("PR kern/51995");
40561.1Skamil
40571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40591.1Skamil	if (child == 0) {
40601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40621.1Skamil
40631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40651.1Skamil
40661.83Skamil		for (n = 0; n < __arraycount(t); n++) {
40671.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
40681.83Skamil			    NULL);
40691.83Skamil			FORKEE_ASSERT(rv == 0);
40701.83Skamil		}
40711.1Skamil
40721.83Skamil		for (n = 0; n < __arraycount(t); n++) {
40731.83Skamil			rv = pthread_join(t[n], NULL);
40741.83Skamil			FORKEE_ASSERT(rv == 0);
40751.83Skamil		}
40761.1Skamil
40771.83Skamil		/*
40781.83Skamil		 * There is race between _exit() and pthread_join() detaching
40791.83Skamil		 * a thread. For simplicity kill the process after detecting
40801.83Skamil		 * LWP events.
40811.83Skamil		 */
40821.83Skamil		while (true)
40831.83Skamil			continue;
40841.1Skamil
40851.83Skamil		FORKEE_ASSERT(0 && "Not reached");
40861.1Skamil	}
40871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40881.1Skamil
40891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40911.1Skamil
40921.1Skamil	validate_status_stopped(status, sigval);
40931.1Skamil
40941.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40951.83Skamil	SYSCALL_REQUIRE(
40961.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
40971.1Skamil
40981.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
40991.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
41001.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41011.83Skamil	    info.psi_siginfo.si_errno);
41021.1Skamil
41031.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
41041.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
41051.1Skamil
41061.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
41071.83Skamil	memset(&event, 0, sizeof(event));
41081.83Skamil	if (trace_create)
41091.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
41101.83Skamil	if (trace_exit)
41111.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
41121.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
41131.1Skamil
41141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41151.1Skamil	    "without signal to be sent\n");
41161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41171.1Skamil
41181.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
41191.1Skamil
41201.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
41211.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
41221.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
41231.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
41241.83Skamil		    child);
41251.1Skamil
41261.83Skamil		validate_status_stopped(status, SIGTRAP);
41271.1Skamil
41281.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
41291.83Skamil		    "child\n");
41301.83Skamil		SYSCALL_REQUIRE(
41311.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41321.1Skamil
41331.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
41341.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
41351.83Skamil		    "si_errno=%#x\n",
41361.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41371.83Skamil		    info.psi_siginfo.si_errno);
41381.1Skamil
41391.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
41401.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
41411.1Skamil
41421.83Skamil		SYSCALL_REQUIRE(
41431.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
41441.1Skamil
41451.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
41461.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
41471.1Skamil
41481.83Skamil		lid = state.pe_lwp;
41491.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
41501.1Skamil
41511.83Skamil		traced_lwps[lid - 1] = true;
41521.1Skamil
41531.83Skamil		DPRINTF("Before resuming the child process where it left off "
41541.83Skamil		    "and without signal to be sent\n");
41551.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41561.83Skamil	}
41571.1Skamil
41581.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
41591.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
41601.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
41611.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
41621.83Skamil		    child);
41631.1Skamil
41641.83Skamil		validate_status_stopped(status, SIGTRAP);
41651.1Skamil
41661.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
41671.83Skamil		    "child\n");
41681.83Skamil		SYSCALL_REQUIRE(
41691.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41701.1Skamil
41711.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
41721.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
41731.83Skamil		    "si_errno=%#x\n",
41741.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41751.83Skamil		    info.psi_siginfo.si_errno);
41761.1Skamil
41771.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
41781.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
41791.1Skamil
41801.83Skamil		SYSCALL_REQUIRE(
41811.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
41821.1Skamil
41831.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
41841.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
41851.1Skamil
41861.83Skamil		lid = state.pe_lwp;
41871.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
41881.1Skamil
41891.83Skamil		if (trace_create) {
41901.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
41911.83Skamil			traced_lwps[lid - 1] = false;
41921.83Skamil		}
41931.1Skamil
41941.83Skamil		DPRINTF("Before resuming the child process where it left off "
41951.83Skamil		    "and without signal to be sent\n");
41961.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41971.83Skamil	}
41981.1Skamil
41991.83Skamil	kill(child, SIGKILL);
42001.1Skamil
42011.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
42021.1Skamil	    TWAIT_FNAME);
42031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42041.1Skamil
42051.83Skamil	validate_status_signaled(status, SIGKILL, 0);
42061.1Skamil
42071.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
42081.1Skamil	    TWAIT_FNAME);
42091.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42101.1Skamil}
42111.1Skamil
42121.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
42131.83SkamilATF_TC(test);								\
42141.83SkamilATF_TC_HEAD(test, tc)							\
42151.83Skamil{									\
42161.83Skamil        atf_tc_set_md_var(tc, "descr",					\
42171.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
42181.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
42191.83Skamil	    trace_exit ? "" : "out");					\
42201.83Skamil}									\
42211.83Skamil									\
42221.83SkamilATF_TC_BODY(test, tc)							\
42231.83Skamil{									\
42241.83Skamil									\
42251.83Skamil        trace_threads(trace_create, trace_exit);			\
42261.83Skamil}
42271.83Skamil
42281.83SkamilTRACE_THREADS(trace_thread1, false, false)
42291.83SkamilTRACE_THREADS(trace_thread2, false, true)
42301.83SkamilTRACE_THREADS(trace_thread3, true, false)
42311.83SkamilTRACE_THREADS(trace_thread4, true, true)
42321.83Skamil
42331.83Skamil/// ----------------------------------------------------------------------------
42341.83Skamil
42351.84SkamilATF_TC(signal_mask_unrelated);
42361.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
42371.1Skamil{
42381.1Skamil	atf_tc_set_md_var(tc, "descr",
42391.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
42401.1Skamil	    "from catching other signals");
42411.1Skamil}
42421.1Skamil
42431.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
42441.1Skamil{
42451.1Skamil	const int exitval = 5;
42461.1Skamil	const int sigval = SIGSTOP;
42471.1Skamil	const int sigmasked = SIGTRAP;
42481.1Skamil	const int signotmasked = SIGINT;
42491.1Skamil	pid_t child, wpid;
42501.1Skamil#if defined(TWAIT_HAVE_STATUS)
42511.1Skamil	int status;
42521.1Skamil#endif
42531.1Skamil	sigset_t intmask;
42541.1Skamil
42551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42571.1Skamil	if (child == 0) {
42581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42601.1Skamil
42611.1Skamil		sigemptyset(&intmask);
42621.1Skamil		sigaddset(&intmask, sigmasked);
42631.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
42641.1Skamil
42651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42671.1Skamil
42681.13Schristos		DPRINTF("Before raising %s from child\n",
42691.1Skamil		    strsignal(signotmasked));
42701.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
42711.1Skamil
42721.13Schristos		DPRINTF("Before exiting of the child process\n");
42731.1Skamil		_exit(exitval);
42741.1Skamil	}
42751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42761.1Skamil
42771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42791.1Skamil
42801.1Skamil	validate_status_stopped(status, sigval);
42811.1Skamil
42821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42831.1Skamil	    "without signal to be sent\n");
42841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42851.1Skamil
42861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42881.1Skamil
42891.1Skamil	validate_status_stopped(status, signotmasked);
42901.1Skamil
42911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42921.1Skamil	    "without signal to be sent\n");
42931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42941.1Skamil
42951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42971.1Skamil
42981.1Skamil	validate_status_exited(status, exitval);
42991.1Skamil
43001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43011.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43021.1Skamil}
43031.1Skamil
43041.84Skamil/// ----------------------------------------------------------------------------
43051.84Skamil
43061.1SkamilATF_TC(signal3);
43071.1SkamilATF_TC_HEAD(signal3, tc)
43081.1Skamil{
43091.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
43101.1Skamil	atf_tc_set_md_var(tc, "descr",
43111.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43121.1Skamil	    "catching software breakpoints");
43131.1Skamil}
43141.1Skamil
43151.1SkamilATF_TC_BODY(signal3, tc)
43161.1Skamil{
43171.1Skamil	const int exitval = 5;
43181.1Skamil	const int sigval = SIGSTOP;
43191.1Skamil	const int sigmasked = SIGTRAP;
43201.1Skamil	pid_t child, wpid;
43211.1Skamil#if defined(TWAIT_HAVE_STATUS)
43221.1Skamil	int status;
43231.1Skamil#endif
43241.1Skamil	sigset_t intmask;
43251.1Skamil
43261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43281.1Skamil	if (child == 0) {
43291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43311.1Skamil
43321.1Skamil		sigemptyset(&intmask);
43331.1Skamil		sigaddset(&intmask, sigmasked);
43341.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43351.1Skamil
43361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43381.1Skamil
43391.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
43401.52Skamil		trigger_trap();
43411.1Skamil
43421.13Schristos		DPRINTF("Before exiting of the child process\n");
43431.1Skamil		_exit(exitval);
43441.1Skamil	}
43451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43461.1Skamil
43471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43491.1Skamil
43501.1Skamil	validate_status_stopped(status, sigval);
43511.1Skamil
43521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43531.1Skamil	    "without signal to be sent\n");
43541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43551.1Skamil
43561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43581.1Skamil
43591.1Skamil	validate_status_stopped(status, sigmasked);
43601.1Skamil
43611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43621.1Skamil	    "without signal to be sent\n");
43631.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
43641.1Skamil
43651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43671.1Skamil
43681.49Skamil	validate_status_signaled(status, SIGKILL, 0);
43691.1Skamil
43701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43721.1Skamil}
43731.1Skamil
43741.1Skamil#if defined(PT_STEP)
43751.1SkamilATF_TC(signal4);
43761.1SkamilATF_TC_HEAD(signal4, tc)
43771.1Skamil{
43781.1Skamil	atf_tc_set_md_var(tc, "descr",
43791.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43801.1Skamil	    "catching single step trap");
43811.1Skamil}
43821.1Skamil
43831.1SkamilATF_TC_BODY(signal4, tc)
43841.1Skamil{
43851.1Skamil	const int exitval = 5;
43861.1Skamil	const int sigval = SIGSTOP;
43871.1Skamil	const int sigmasked = SIGTRAP;
43881.1Skamil	pid_t child, wpid;
43891.1Skamil#if defined(TWAIT_HAVE_STATUS)
43901.1Skamil	int status;
43911.1Skamil#endif
43921.1Skamil	sigset_t intmask;
43931.1Skamil	int happy;
43941.1Skamil
43951.1Skamil#if defined(__arm__)
43961.5Skamil	/* PT_STEP not supported on arm 32-bit */
43971.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
43981.1Skamil#endif
43991.1Skamil
44001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44021.1Skamil	if (child == 0) {
44031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44051.1Skamil
44061.1Skamil		happy = check_happy(100);
44071.1Skamil
44081.1Skamil		sigemptyset(&intmask);
44091.1Skamil		sigaddset(&intmask, sigmasked);
44101.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44111.1Skamil
44121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44141.1Skamil
44151.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
44161.1Skamil
44171.13Schristos		DPRINTF("Before exiting of the child process\n");
44181.1Skamil		_exit(exitval);
44191.1Skamil	}
44201.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44211.1Skamil
44221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44241.1Skamil
44251.1Skamil	validate_status_stopped(status, sigval);
44261.1Skamil
44271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44281.1Skamil	    "without signal to be sent\n");
44291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
44301.1Skamil
44311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44331.1Skamil
44341.1Skamil	validate_status_stopped(status, sigmasked);
44351.1Skamil
44361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44371.1Skamil	    "without signal to be sent\n");
44381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44391.1Skamil
44401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44421.1Skamil
44431.1Skamil	validate_status_exited(status, exitval);
44441.1Skamil
44451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44471.1Skamil}
44481.1Skamil#endif
44491.1Skamil
44501.1SkamilATF_TC(signal5);
44511.1SkamilATF_TC_HEAD(signal5, tc)
44521.1Skamil{
44531.1Skamil	atf_tc_set_md_var(tc, "descr",
44541.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44551.1Skamil	    "catching exec() breakpoint");
44561.1Skamil}
44571.1Skamil
44581.1SkamilATF_TC_BODY(signal5, tc)
44591.1Skamil{
44601.1Skamil	const int sigval = SIGSTOP;
44611.1Skamil	const int sigmasked = SIGTRAP;
44621.1Skamil	pid_t child, wpid;
44631.1Skamil#if defined(TWAIT_HAVE_STATUS)
44641.1Skamil	int status;
44651.1Skamil#endif
44661.58Skamil	struct ptrace_siginfo info;
44671.1Skamil	sigset_t intmask;
44681.1Skamil
44691.58Skamil	memset(&info, 0, sizeof(info));
44701.14Schristos
44711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44731.1Skamil	if (child == 0) {
44741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44761.1Skamil
44771.1Skamil		sigemptyset(&intmask);
44781.1Skamil		sigaddset(&intmask, sigmasked);
44791.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44801.1Skamil
44811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44831.1Skamil
44841.13Schristos		DPRINTF("Before calling execve(2) from child\n");
44851.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
44861.1Skamil
44871.58Skamil		/* NOTREACHED */
44881.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
44891.1Skamil	}
44901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44911.1Skamil
44921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44941.1Skamil
44951.1Skamil	validate_status_stopped(status, sigval);
44961.1Skamil
44971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44981.1Skamil	    "without signal to be sent\n");
44991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45001.1Skamil
45011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45031.1Skamil
45041.1Skamil	validate_status_stopped(status, sigmasked);
45051.1Skamil
45061.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45071.61Skre	SYSCALL_REQUIRE(
45081.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45091.58Skamil
45101.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45111.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
45121.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45131.58Skamil	    info.psi_siginfo.si_errno);
45141.58Skamil
45151.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
45161.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
45171.58Skamil
45181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45191.1Skamil	    "without signal to be sent\n");
45201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45211.1Skamil
45221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45241.1Skamil
45251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45271.1Skamil}
45281.1Skamil
45291.1Skamil#if defined(TWAIT_HAVE_PID)
45301.1SkamilATF_TC(signal6);
45311.1SkamilATF_TC_HEAD(signal6, tc)
45321.1Skamil{
45331.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
45341.1Skamil	atf_tc_set_md_var(tc, "descr",
45351.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45361.1Skamil	    "catching PTRACE_FORK breakpoint");
45371.1Skamil}
45381.1Skamil
45391.1SkamilATF_TC_BODY(signal6, tc)
45401.1Skamil{
45411.1Skamil	const int exitval = 5;
45421.1Skamil	const int exitval2 = 15;
45431.1Skamil	const int sigval = SIGSTOP;
45441.1Skamil	const int sigmasked = SIGTRAP;
45451.1Skamil	pid_t child, child2, wpid;
45461.1Skamil#if defined(TWAIT_HAVE_STATUS)
45471.1Skamil	int status;
45481.1Skamil#endif
45491.1Skamil	sigset_t intmask;
45501.1Skamil	ptrace_state_t state;
45511.1Skamil	const int slen = sizeof(state);
45521.1Skamil	ptrace_event_t event;
45531.1Skamil	const int elen = sizeof(event);
45541.1Skamil
45551.38Skamil	atf_tc_expect_fail("PR kern/51918");
45561.14Schristos
45571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45591.1Skamil	if (child == 0) {
45601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45621.1Skamil
45631.1Skamil		sigemptyset(&intmask);
45641.1Skamil		sigaddset(&intmask, sigmasked);
45651.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45661.1Skamil
45671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45691.1Skamil
45701.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
45711.1Skamil
45721.1Skamil		if (child2 == 0)
45731.1Skamil			_exit(exitval2);
45741.1Skamil
45751.1Skamil		FORKEE_REQUIRE_SUCCESS
45761.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
45771.1Skamil
45781.1Skamil		forkee_status_exited(status, exitval2);
45791.1Skamil
45801.13Schristos		DPRINTF("Before exiting of the child process\n");
45811.1Skamil		_exit(exitval);
45821.1Skamil	}
45831.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45841.1Skamil
45851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45871.1Skamil
45881.1Skamil	validate_status_stopped(status, sigval);
45891.1Skamil
45901.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
45911.1Skamil	event.pe_set_event = PTRACE_FORK;
45921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
45931.1Skamil
45941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45951.1Skamil	    "without signal to be sent\n");
45961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45971.1Skamil
45981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46001.1Skamil
46011.1Skamil	validate_status_stopped(status, sigmasked);
46021.1Skamil
46031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
46041.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
46051.1Skamil
46061.1Skamil	child2 = state.pe_other_pid;
46071.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
46081.1Skamil
46091.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
46101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46111.1Skamil	    child2);
46121.1Skamil
46131.1Skamil	validate_status_stopped(status, SIGTRAP);
46141.1Skamil
46151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
46161.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
46171.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
46181.1Skamil
46191.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
46201.1Skamil	    "without signal to be sent\n");
46211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
46221.1Skamil
46231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46241.1Skamil	    "without signal to be sent\n");
46251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46261.1Skamil
46271.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
46281.1Skamil	    TWAIT_FNAME);
46291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46301.57Skamil	    child2);
46311.1Skamil
46321.1Skamil	validate_status_exited(status, exitval2);
46331.1Skamil
46341.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
46351.1Skamil	    TWAIT_FNAME);
46361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
46371.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
46381.1Skamil
46391.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
46401.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
46411.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46421.1Skamil
46431.1Skamil	validate_status_stopped(status, SIGCHLD);
46441.1Skamil
46451.57Skamil	DPRINTF("Before resuming the child process where it left off and "
46461.1Skamil	    "without signal to be sent\n");
46471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46481.1Skamil
46491.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
46501.1Skamil	    TWAIT_FNAME);
46511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46521.1Skamil
46531.1Skamil	validate_status_exited(status, exitval);
46541.1Skamil
46551.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
46561.57Skamil	    TWAIT_FNAME);
46571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46581.1Skamil}
46591.1Skamil#endif
46601.1Skamil
46611.1Skamil#if defined(TWAIT_HAVE_PID)
46621.1SkamilATF_TC(signal7);
46631.1SkamilATF_TC_HEAD(signal7, tc)
46641.1Skamil{
46651.1Skamil	atf_tc_set_md_var(tc, "descr",
46661.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
46671.1Skamil	    "catching PTRACE_VFORK breakpoint");
46681.1Skamil}
46691.1Skamil
46701.1SkamilATF_TC_BODY(signal7, tc)
46711.1Skamil{
46721.1Skamil	const int exitval = 5;
46731.1Skamil	const int exitval2 = 15;
46741.1Skamil	const int sigval = SIGSTOP;
46751.1Skamil	const int sigmasked = SIGTRAP;
46761.1Skamil	pid_t child, child2, wpid;
46771.1Skamil#if defined(TWAIT_HAVE_STATUS)
46781.1Skamil	int status;
46791.1Skamil#endif
46801.1Skamil	sigset_t intmask;
46811.1Skamil	ptrace_state_t state;
46821.1Skamil	const int slen = sizeof(state);
46831.1Skamil	ptrace_event_t event;
46841.1Skamil	const int elen = sizeof(event);
46851.1Skamil
46861.38Skamil	atf_tc_expect_fail("PR kern/51918");
46871.14Schristos
46881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46901.1Skamil	if (child == 0) {
46911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46931.1Skamil
46941.1Skamil		sigemptyset(&intmask);
46951.1Skamil		sigaddset(&intmask, sigmasked);
46961.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46971.1Skamil
46981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47001.1Skamil
47011.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
47021.1Skamil
47031.1Skamil		if (child2 == 0)
47041.1Skamil			_exit(exitval2);
47051.1Skamil
47061.1Skamil		FORKEE_REQUIRE_SUCCESS
47071.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
47081.1Skamil
47091.1Skamil		forkee_status_exited(status, exitval2);
47101.1Skamil
47111.13Schristos		DPRINTF("Before exiting of the child process\n");
47121.1Skamil		_exit(exitval);
47131.1Skamil	}
47141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47151.1Skamil
47161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47181.1Skamil
47191.1Skamil	validate_status_stopped(status, sigval);
47201.1Skamil
47211.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
47221.1Skamil	event.pe_set_event = PTRACE_VFORK;
47231.61Skre	SYSCALL_REQUIRE(
47241.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
47251.61Skre	    errno == ENOTSUP);
47261.1Skamil
47271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47281.1Skamil	    "without signal to be sent\n");
47291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47301.1Skamil
47311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47331.1Skamil
47341.1Skamil	validate_status_stopped(status, sigmasked);
47351.1Skamil
47361.61Skre	SYSCALL_REQUIRE(
47371.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
47381.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
47391.1Skamil
47401.1Skamil	child2 = state.pe_other_pid;
47411.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
47421.1Skamil
47431.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
47441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
47451.1Skamil	    child2);
47461.1Skamil
47471.1Skamil	validate_status_stopped(status, SIGTRAP);
47481.1Skamil
47491.61Skre	SYSCALL_REQUIRE(
47501.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
47511.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
47521.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
47531.1Skamil
47541.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
47551.1Skamil	    "without signal to be sent\n");
47561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
47571.1Skamil
47581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47591.1Skamil	    "without signal to be sent\n");
47601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47611.1Skamil
47621.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
47631.1Skamil	    TWAIT_FNAME);
47641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
47651.57Skamil	    child2);
47661.1Skamil
47671.1Skamil	validate_status_exited(status, exitval2);
47681.1Skamil
47691.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
47701.1Skamil	    TWAIT_FNAME);
47711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
47721.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
47731.1Skamil
47741.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
47751.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
47761.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47771.1Skamil
47781.1Skamil	validate_status_stopped(status, SIGCHLD);
47791.1Skamil
47801.57Skamil	DPRINTF("Before resuming the child process where it left off and "
47811.1Skamil	    "without signal to be sent\n");
47821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47831.1Skamil
47841.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
47851.1Skamil	    TWAIT_FNAME);
47861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47871.1Skamil
47881.1Skamil	validate_status_exited(status, exitval);
47891.1Skamil
47901.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
47911.57Skamil	    TWAIT_FNAME);
47921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47931.1Skamil}
47941.1Skamil#endif
47951.1Skamil
47961.1SkamilATF_TC(signal8);
47971.1SkamilATF_TC_HEAD(signal8, tc)
47981.1Skamil{
47991.1Skamil	atf_tc_set_md_var(tc, "descr",
48001.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
48011.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
48021.1Skamil}
48031.1Skamil
48041.1SkamilATF_TC_BODY(signal8, tc)
48051.1Skamil{
48061.1Skamil	const int exitval = 5;
48071.1Skamil	const int exitval2 = 15;
48081.1Skamil	const int sigval = SIGSTOP;
48091.1Skamil	const int sigmasked = SIGTRAP;
48101.1Skamil	pid_t child, child2, wpid;
48111.1Skamil#if defined(TWAIT_HAVE_STATUS)
48121.1Skamil	int status;
48131.1Skamil#endif
48141.1Skamil	sigset_t intmask;
48151.1Skamil	ptrace_state_t state;
48161.1Skamil	const int slen = sizeof(state);
48171.1Skamil	ptrace_event_t event;
48181.1Skamil	const int elen = sizeof(event);
48191.1Skamil
48201.14Schristos	atf_tc_expect_fail("PR kern/51918");
48211.14Schristos
48221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48241.1Skamil	if (child == 0) {
48251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48271.1Skamil
48281.1Skamil		sigemptyset(&intmask);
48291.1Skamil		sigaddset(&intmask, sigmasked);
48301.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
48311.1Skamil
48321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48341.1Skamil
48351.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
48361.1Skamil
48371.1Skamil		if (child2 == 0)
48381.1Skamil			_exit(exitval2);
48391.1Skamil
48401.1Skamil		FORKEE_REQUIRE_SUCCESS
48411.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
48421.1Skamil
48431.1Skamil		forkee_status_exited(status, exitval2);
48441.1Skamil
48451.13Schristos		DPRINTF("Before exiting of the child process\n");
48461.1Skamil		_exit(exitval);
48471.1Skamil	}
48481.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48491.1Skamil
48501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48521.1Skamil
48531.1Skamil	validate_status_stopped(status, sigval);
48541.1Skamil
48551.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
48561.1Skamil	    child);
48571.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
48581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
48591.1Skamil
48601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48611.1Skamil	    "without signal to be sent\n");
48621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48631.1Skamil
48641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48661.1Skamil
48671.1Skamil	validate_status_stopped(status, sigmasked);
48681.1Skamil
48691.61Skre	SYSCALL_REQUIRE(
48701.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
48711.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
48721.1Skamil
48731.1Skamil	child2 = state.pe_other_pid;
48741.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
48751.1Skamil
48761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48771.1Skamil	    "without signal to be sent\n");
48781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48791.1Skamil
48801.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48811.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
48821.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48831.1Skamil
48841.1Skamil	validate_status_stopped(status, SIGCHLD);
48851.1Skamil
48861.57Skamil	DPRINTF("Before resuming the child process where it left off and "
48871.1Skamil	    "without signal to be sent\n");
48881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48891.1Skamil
48901.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48911.1Skamil	    TWAIT_FNAME);
48921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48931.1Skamil
48941.1Skamil	validate_status_exited(status, exitval);
48951.1Skamil
48961.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48971.57Skamil	    TWAIT_FNAME);
48981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48991.1Skamil}
49001.1Skamil
49011.83Skamilvolatile lwpid_t the_lwp_id = 0;
49021.83Skamil
49031.83Skamilstatic void
49041.83Skamillwp_main_func(void *arg)
49051.83Skamil{
49061.83Skamil	the_lwp_id = _lwp_self();
49071.83Skamil	_lwp_exit();
49081.83Skamil}
49091.83Skamil
49101.1SkamilATF_TC(signal9);
49111.1SkamilATF_TC_HEAD(signal9, tc)
49121.1Skamil{
49131.1Skamil	atf_tc_set_md_var(tc, "descr",
49141.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
49151.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
49161.1Skamil}
49171.1Skamil
49181.1SkamilATF_TC_BODY(signal9, tc)
49191.1Skamil{
49201.1Skamil	const int exitval = 5;
49211.1Skamil	const int sigval = SIGSTOP;
49221.1Skamil	const int sigmasked = SIGTRAP;
49231.1Skamil	pid_t child, wpid;
49241.1Skamil#if defined(TWAIT_HAVE_STATUS)
49251.1Skamil	int status;
49261.1Skamil#endif
49271.1Skamil	sigset_t intmask;
49281.1Skamil	ptrace_state_t state;
49291.1Skamil	const int slen = sizeof(state);
49301.1Skamil	ptrace_event_t event;
49311.1Skamil	const int elen = sizeof(event);
49321.1Skamil	ucontext_t uc;
49331.1Skamil	lwpid_t lid;
49341.1Skamil	static const size_t ssize = 16*1024;
49351.1Skamil	void *stack;
49361.1Skamil
49371.14Schristos	atf_tc_expect_fail("PR kern/51918");
49381.14Schristos
49391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49411.1Skamil	if (child == 0) {
49421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49441.1Skamil
49451.1Skamil		sigemptyset(&intmask);
49461.1Skamil		sigaddset(&intmask, sigmasked);
49471.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
49481.1Skamil
49491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49511.1Skamil
49521.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
49531.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
49541.1Skamil
49551.13Schristos		DPRINTF("Before making context for new lwp in child\n");
49561.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
49571.1Skamil
49581.13Schristos		DPRINTF("Before creating new in child\n");
49591.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
49601.1Skamil
49611.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
49621.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
49631.1Skamil
49641.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
49651.1Skamil		    "are the same\n", lid, the_lwp_id);
49661.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
49671.1Skamil
49681.13Schristos		DPRINTF("Before exiting of the child process\n");
49691.1Skamil		_exit(exitval);
49701.1Skamil	}
49711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49721.1Skamil
49731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49751.1Skamil
49761.1Skamil	validate_status_stopped(status, sigval);
49771.1Skamil
49781.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
49791.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
49801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
49811.1Skamil
49821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49831.1Skamil	    "without signal to be sent\n");
49841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49851.1Skamil
49861.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49871.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
49881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49891.1Skamil
49901.1Skamil	validate_status_stopped(status, sigmasked);
49911.1Skamil
49921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
49931.1Skamil
49941.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
49951.1Skamil
49961.1Skamil	lid = state.pe_lwp;
49971.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
49981.1Skamil
49991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50001.1Skamil	    "without signal to be sent\n");
50011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50021.1Skamil
50031.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
50041.1Skamil	    TWAIT_FNAME);
50051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50061.1Skamil
50071.1Skamil	validate_status_exited(status, exitval);
50081.1Skamil
50091.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
50101.1Skamil	    TWAIT_FNAME);
50111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50121.1Skamil}
50131.1Skamil
50141.1SkamilATF_TC(signal10);
50151.1SkamilATF_TC_HEAD(signal10, tc)
50161.1Skamil{
50171.1Skamil	atf_tc_set_md_var(tc, "descr",
50181.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
50191.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
50201.1Skamil}
50211.1Skamil
50221.1SkamilATF_TC_BODY(signal10, tc)
50231.1Skamil{
50241.1Skamil	const int exitval = 5;
50251.1Skamil	const int sigval = SIGSTOP;
50261.1Skamil	const int sigmasked = SIGTRAP;
50271.1Skamil	pid_t child, wpid;
50281.1Skamil#if defined(TWAIT_HAVE_STATUS)
50291.1Skamil	int status;
50301.1Skamil#endif
50311.1Skamil	sigset_t intmask;
50321.1Skamil	ptrace_state_t state;
50331.1Skamil	const int slen = sizeof(state);
50341.1Skamil	ptrace_event_t event;
50351.1Skamil	const int elen = sizeof(event);
50361.1Skamil	ucontext_t uc;
50371.1Skamil	lwpid_t lid;
50381.1Skamil	static const size_t ssize = 16*1024;
50391.1Skamil	void *stack;
50401.1Skamil
50411.14Schristos	atf_tc_expect_fail("PR kern/51918");
50421.14Schristos
50431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50451.1Skamil	if (child == 0) {
50461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50481.1Skamil
50491.1Skamil		sigemptyset(&intmask);
50501.1Skamil		sigaddset(&intmask, sigmasked);
50511.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
50521.1Skamil
50531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50551.1Skamil
50561.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
50571.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
50581.1Skamil
50591.13Schristos		DPRINTF("Before making context for new lwp in child\n");
50601.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
50611.1Skamil
50621.13Schristos		DPRINTF("Before creating new in child\n");
50631.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
50641.1Skamil
50651.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
50661.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
50671.1Skamil
50681.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
50691.1Skamil		    "are the same\n", lid, the_lwp_id);
50701.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
50711.1Skamil
50721.13Schristos		DPRINTF("Before exiting of the child process\n");
50731.1Skamil		_exit(exitval);
50741.1Skamil	}
50751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50761.1Skamil
50771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50791.1Skamil
50801.1Skamil	validate_status_stopped(status, sigval);
50811.1Skamil
50821.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
50831.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
50841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50851.1Skamil
50861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50871.1Skamil	    "without signal to be sent\n");
50881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50891.1Skamil
50901.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50911.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
50921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50931.1Skamil
50941.1Skamil	validate_status_stopped(status, sigmasked);
50951.1Skamil
50961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50971.1Skamil
50981.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
50991.1Skamil
51001.1Skamil	lid = state.pe_lwp;
51011.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
51021.1Skamil
51031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51041.1Skamil	    "without signal to be sent\n");
51051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51061.1Skamil
51071.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51081.1Skamil	    TWAIT_FNAME);
51091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51101.1Skamil
51111.1Skamil	validate_status_exited(status, exitval);
51121.1Skamil
51131.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51141.1Skamil	    TWAIT_FNAME);
51151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51161.1Skamil}
51171.1Skamil
51181.1Skamilstatic void
51191.1Skamillwp_main_stop(void *arg)
51201.1Skamil{
51211.1Skamil	the_lwp_id = _lwp_self();
51221.1Skamil
51231.1Skamil	raise(SIGTRAP);
51241.1Skamil
51251.1Skamil	_lwp_exit();
51261.1Skamil}
51271.1Skamil
51281.1SkamilATF_TC(suspend1);
51291.1SkamilATF_TC_HEAD(suspend1, tc)
51301.1Skamil{
51311.1Skamil	atf_tc_set_md_var(tc, "descr",
51321.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
51331.1Skamil	    "resumed by a tracee");
51341.1Skamil}
51351.1Skamil
51361.1SkamilATF_TC_BODY(suspend1, tc)
51371.1Skamil{
51381.1Skamil	const int exitval = 5;
51391.1Skamil	const int sigval = SIGSTOP;
51401.1Skamil	pid_t child, wpid;
51411.1Skamil#if defined(TWAIT_HAVE_STATUS)
51421.1Skamil	int status;
51431.1Skamil#endif
51441.1Skamil	ucontext_t uc;
51451.1Skamil	lwpid_t lid;
51461.1Skamil	static const size_t ssize = 16*1024;
51471.1Skamil	void *stack;
51481.1Skamil	struct ptrace_lwpinfo pl;
51491.1Skamil	struct ptrace_siginfo psi;
51501.1Skamil	volatile int go = 0;
51511.1Skamil
51521.17Skamil	// Feature pending for refactoring
51531.17Skamil	atf_tc_expect_fail("PR kern/51995");
51541.17Skamil
51551.16Skamil	// Hangs with qemu
51561.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
51571.16Skamil
51581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51601.1Skamil	if (child == 0) {
51611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51631.1Skamil
51641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51661.1Skamil
51671.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
51681.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
51691.1Skamil
51701.13Schristos		DPRINTF("Before making context for new lwp in child\n");
51711.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
51721.1Skamil
51731.13Schristos		DPRINTF("Before creating new in child\n");
51741.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
51751.1Skamil
51761.1Skamil		while (go == 0)
51771.1Skamil			continue;
51781.1Skamil
51791.1Skamil		raise(SIGINT);
51801.1Skamil
51811.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
51821.1Skamil
51831.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
51841.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
51851.1Skamil
51861.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
51871.1Skamil		    "are the same\n", lid, the_lwp_id);
51881.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
51891.1Skamil
51901.13Schristos		DPRINTF("Before exiting of the child process\n");
51911.1Skamil		_exit(exitval);
51921.1Skamil	}
51931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51941.1Skamil
51951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51971.1Skamil
51981.1Skamil	validate_status_stopped(status, sigval);
51991.1Skamil
52001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52011.1Skamil	    "without signal to be sent\n");
52021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52031.1Skamil
52041.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52051.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
52061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52071.1Skamil
52081.1Skamil	validate_status_stopped(status, SIGTRAP);
52091.1Skamil
52101.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
52111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
52121.1Skamil
52131.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
52141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
52151.1Skamil
52161.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
52171.1Skamil	    child, getpid());
52181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
52191.1Skamil
52201.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52211.1Skamil	    "without signal to be sent\n");
52221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52231.1Skamil
52241.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52251.1Skamil	    "SIGINT\n", TWAIT_FNAME);
52261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52271.1Skamil
52281.1Skamil	validate_status_stopped(status, SIGINT);
52291.1Skamil
52301.1Skamil	pl.pl_lwpid = 0;
52311.1Skamil
52321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
52331.1Skamil	while (pl.pl_lwpid != 0) {
52341.1Skamil
52351.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
52361.1Skamil		switch (pl.pl_lwpid) {
52371.1Skamil		case 1:
52381.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
52391.1Skamil			break;
52401.1Skamil		case 2:
52411.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
52421.1Skamil			break;
52431.1Skamil		}
52441.1Skamil	}
52451.1Skamil
52461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52471.1Skamil	    "without signal to be sent\n");
52481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52491.1Skamil
52501.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52511.1Skamil	    TWAIT_FNAME);
52521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52531.1Skamil
52541.1Skamil	validate_status_exited(status, exitval);
52551.1Skamil
52561.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52571.1Skamil	    TWAIT_FNAME);
52581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52591.1Skamil}
52601.1Skamil
52611.1SkamilATF_TC(suspend2);
52621.1SkamilATF_TC_HEAD(suspend2, tc)
52631.1Skamil{
52641.1Skamil	atf_tc_set_md_var(tc, "descr",
52651.1Skamil	    "Verify that the while the only thread within a process is "
52661.1Skamil	    "suspended, the whole process cannot be unstopped");
52671.1Skamil}
52681.1Skamil
52691.1SkamilATF_TC_BODY(suspend2, tc)
52701.1Skamil{
52711.1Skamil	const int exitval = 5;
52721.1Skamil	const int sigval = SIGSTOP;
52731.1Skamil	pid_t child, wpid;
52741.1Skamil#if defined(TWAIT_HAVE_STATUS)
52751.1Skamil	int status;
52761.1Skamil#endif
52771.1Skamil	struct ptrace_siginfo psi;
52781.1Skamil
52791.17Skamil	// Feature pending for refactoring
52801.17Skamil	atf_tc_expect_fail("PR kern/51995");
52811.17Skamil
52821.16Skamil	// Hangs with qemu
52831.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
52841.16Skamil
52851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52871.1Skamil	if (child == 0) {
52881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52901.1Skamil
52911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52931.1Skamil
52941.13Schristos		DPRINTF("Before exiting of the child process\n");
52951.1Skamil		_exit(exitval);
52961.1Skamil	}
52971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52981.1Skamil
52991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53011.1Skamil
53021.1Skamil	validate_status_stopped(status, sigval);
53031.1Skamil
53041.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
53051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
53061.1Skamil
53071.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
53081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
53091.1Skamil
53101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53111.1Skamil	    "without signal to be sent\n");
53121.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
53131.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
53141.1Skamil
53151.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
53161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
53171.1Skamil
53181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53191.1Skamil	    "without signal to be sent\n");
53201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53211.1Skamil
53221.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53231.1Skamil	    TWAIT_FNAME);
53241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53251.1Skamil
53261.1Skamil	validate_status_exited(status, exitval);
53271.1Skamil
53281.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53291.1Skamil	    TWAIT_FNAME);
53301.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53311.1Skamil}
53321.1Skamil
53331.1SkamilATF_TC(resume1);
53341.1SkamilATF_TC_HEAD(resume1, tc)
53351.1Skamil{
53361.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
53371.1Skamil	atf_tc_set_md_var(tc, "descr",
53381.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
53391.1Skamil	    "resumed by the debugger");
53401.1Skamil}
53411.1Skamil
53421.1SkamilATF_TC_BODY(resume1, tc)
53431.1Skamil{
53441.1Skamil	struct msg_fds fds;
53451.1Skamil	const int exitval = 5;
53461.1Skamil	const int sigval = SIGSTOP;
53471.1Skamil	pid_t child, wpid;
53481.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
53491.1Skamil#if defined(TWAIT_HAVE_STATUS)
53501.1Skamil	int status;
53511.1Skamil#endif
53521.1Skamil	ucontext_t uc;
53531.1Skamil	lwpid_t lid;
53541.1Skamil	static const size_t ssize = 16*1024;
53551.1Skamil	void *stack;
53561.1Skamil	struct ptrace_lwpinfo pl;
53571.1Skamil	struct ptrace_siginfo psi;
53581.1Skamil
53591.17Skamil	// Feature pending for refactoring
53601.17Skamil	atf_tc_expect_fail("PR kern/51995");
53611.17Skamil
53621.15Schristos	// Hangs with qemu
53631.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
53641.1Skamil
53651.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
53661.1Skamil
53671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53691.1Skamil	if (child == 0) {
53701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53721.1Skamil
53731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53751.1Skamil
53761.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
53771.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53781.1Skamil
53791.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53801.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
53811.1Skamil
53821.13Schristos		DPRINTF("Before creating new in child\n");
53831.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
53841.1Skamil
53851.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
53861.1Skamil
53871.1Skamil		raise(SIGINT);
53881.1Skamil
53891.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
53901.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
53911.1Skamil
53921.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
53931.1Skamil		    "are the same\n", lid, the_lwp_id);
53941.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
53951.1Skamil
53961.13Schristos		DPRINTF("Before exiting of the child process\n");
53971.1Skamil		_exit(exitval);
53981.1Skamil	}
53991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54001.1Skamil
54011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54031.1Skamil
54041.1Skamil	validate_status_stopped(status, sigval);
54051.1Skamil
54061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54071.1Skamil	    "without signal to be sent\n");
54081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54091.1Skamil
54101.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54111.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54131.1Skamil
54141.1Skamil	validate_status_stopped(status, SIGTRAP);
54151.1Skamil
54161.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
54171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
54181.1Skamil
54191.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
54201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
54211.1Skamil
54221.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
54231.1Skamil
54241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54251.1Skamil	    "without signal to be sent\n");
54261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54271.1Skamil
54281.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54291.1Skamil	    "SIGINT\n", TWAIT_FNAME);
54301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54311.1Skamil
54321.1Skamil	validate_status_stopped(status, SIGINT);
54331.1Skamil
54341.1Skamil	pl.pl_lwpid = 0;
54351.1Skamil
54361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54371.1Skamil	while (pl.pl_lwpid != 0) {
54381.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54391.1Skamil		switch (pl.pl_lwpid) {
54401.1Skamil		case 1:
54411.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
54421.1Skamil			break;
54431.1Skamil		case 2:
54441.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
54451.1Skamil			break;
54461.1Skamil		}
54471.1Skamil	}
54481.1Skamil
54491.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
54501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
54511.1Skamil
54521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54531.1Skamil	    "without signal to be sent\n");
54541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54551.1Skamil
54561.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54571.1Skamil	    TWAIT_FNAME);
54581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54591.1Skamil
54601.1Skamil	validate_status_exited(status, exitval);
54611.1Skamil
54621.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54631.1Skamil	    TWAIT_FNAME);
54641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54651.1Skamil
54661.1Skamil	msg_close(&fds);
54671.1Skamil
54681.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
54691.1Skamil	sleep(10);
54701.1Skamil}
54711.1Skamil
54721.1SkamilATF_TC(syscall1);
54731.1SkamilATF_TC_HEAD(syscall1, tc)
54741.1Skamil{
54751.1Skamil	atf_tc_set_md_var(tc, "descr",
54761.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
54771.1Skamil}
54781.1Skamil
54791.1SkamilATF_TC_BODY(syscall1, tc)
54801.1Skamil{
54811.1Skamil	const int exitval = 5;
54821.1Skamil	const int sigval = SIGSTOP;
54831.1Skamil	pid_t child, wpid;
54841.1Skamil#if defined(TWAIT_HAVE_STATUS)
54851.1Skamil	int status;
54861.1Skamil#endif
54871.1Skamil	struct ptrace_siginfo info;
54881.1Skamil	memset(&info, 0, sizeof(info));
54891.1Skamil
54901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54921.1Skamil	if (child == 0) {
54931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54951.1Skamil
54961.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54971.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54981.1Skamil
54991.1Skamil		syscall(SYS_getpid);
55001.1Skamil
55011.13Schristos		DPRINTF("Before exiting of the child process\n");
55021.1Skamil		_exit(exitval);
55031.1Skamil	}
55041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55051.1Skamil
55061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55081.1Skamil
55091.1Skamil	validate_status_stopped(status, sigval);
55101.1Skamil
55111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55121.1Skamil	    "without signal to be sent\n");
55131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
55141.1Skamil
55151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55171.1Skamil
55181.1Skamil	validate_status_stopped(status, SIGTRAP);
55191.1Skamil
55201.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55221.1Skamil
55231.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
55241.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
55251.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55261.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
55271.1Skamil
55281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55291.1Skamil	    "without signal to be sent\n");
55301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
55311.1Skamil
55321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55341.1Skamil
55351.1Skamil	validate_status_stopped(status, SIGTRAP);
55361.1Skamil
55371.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55391.1Skamil
55401.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
55411.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
55421.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55431.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
55441.1Skamil
55451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55461.1Skamil	    "without signal to be sent\n");
55471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55481.1Skamil
55491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55511.1Skamil
55521.1Skamil	validate_status_exited(status, exitval);
55531.1Skamil
55541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55561.1Skamil}
55571.1Skamil
55581.1SkamilATF_TC(syscallemu1);
55591.1SkamilATF_TC_HEAD(syscallemu1, tc)
55601.1Skamil{
55611.1Skamil	atf_tc_set_md_var(tc, "descr",
55621.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
55631.1Skamil}
55641.1Skamil
55651.1SkamilATF_TC_BODY(syscallemu1, tc)
55661.1Skamil{
55671.1Skamil	const int exitval = 5;
55681.1Skamil	const int sigval = SIGSTOP;
55691.1Skamil	pid_t child, wpid;
55701.1Skamil#if defined(TWAIT_HAVE_STATUS)
55711.1Skamil	int status;
55721.1Skamil#endif
55731.1Skamil
55741.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
55751.6Skamil	/* syscallemu does not work on sparc (32-bit) */
55761.6Skamil	atf_tc_expect_fail("PR kern/52166");
55771.6Skamil#endif
55781.6Skamil
55791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55811.1Skamil	if (child == 0) {
55821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55841.1Skamil
55851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55871.1Skamil
55881.1Skamil		syscall(SYS_exit, 100);
55891.1Skamil
55901.13Schristos		DPRINTF("Before exiting of the child process\n");
55911.1Skamil		_exit(exitval);
55921.1Skamil	}
55931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55941.1Skamil
55951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55971.1Skamil
55981.1Skamil	validate_status_stopped(status, sigval);
55991.1Skamil
56001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56011.1Skamil	    "without signal to be sent\n");
56021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
56031.1Skamil
56041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56061.1Skamil
56071.1Skamil	validate_status_stopped(status, SIGTRAP);
56081.1Skamil
56091.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
56101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
56111.1Skamil
56121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56131.1Skamil	    "without signal to be sent\n");
56141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
56151.1Skamil
56161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56181.1Skamil
56191.1Skamil	validate_status_stopped(status, SIGTRAP);
56201.1Skamil
56211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56221.1Skamil	    "without signal to be sent\n");
56231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56241.1Skamil
56251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56271.1Skamil
56281.1Skamil	validate_status_exited(status, exitval);
56291.1Skamil
56301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56321.1Skamil}
56331.1Skamil
56341.1Skamil#include "t_ptrace_amd64_wait.h"
56351.1Skamil#include "t_ptrace_i386_wait.h"
56361.1Skamil#include "t_ptrace_x86_wait.h"
56371.1Skamil
56381.1SkamilATF_TP_ADD_TCS(tp)
56391.1Skamil{
56401.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
56411.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
56421.33Skamil
56431.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
56441.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
56451.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
56461.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
56471.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
56481.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
56491.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
56501.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
56511.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
56521.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
56531.33Skamil
56541.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
56551.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
56561.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
56571.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
56581.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
56591.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
56601.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
56611.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
56621.87Skamil
56631.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
56641.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
56651.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
56661.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
56671.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
56681.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
56691.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
56701.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
56711.86Skamil
56721.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
56731.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
56741.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
56751.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
56761.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
56771.59Skamil
56781.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
56791.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
56801.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
56811.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
56821.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
56831.88Skamil
56841.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
56851.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
56861.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
56871.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
56881.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
56891.88Skamil
56901.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
56911.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
56921.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
56931.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
56941.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
56951.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
56961.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
56971.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
56981.50Skamil
56991.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
57001.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
57011.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
57021.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
57031.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
57041.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
57051.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
57061.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
57071.50Skamil
57081.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
57091.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
57101.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
57111.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
57121.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
57131.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
57141.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
57151.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
57161.50Skamil
57171.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
57181.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
57191.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
57201.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
57211.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
57221.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
57231.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
57241.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
57251.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
57261.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
57271.1Skamil
57281.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
57291.37Skamil
57301.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
57311.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
57321.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
57331.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
57341.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
57351.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
57361.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
57371.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
57381.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
57391.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
57401.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
57411.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
57421.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
57431.40Skamil
57441.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
57451.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
57461.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
57471.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
57481.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
57491.41Skamil
57501.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
57511.43Skamil
57521.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
57531.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
57541.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
57551.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
57561.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
57571.59Skamil
57581.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
57591.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
57601.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
57611.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
57621.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
57631.51Skamil
57641.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
57651.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
57661.51Skamil
57671.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
57681.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
57691.51Skamil
57701.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57711.51Skamil		tracee_sees_its_original_parent_getppid);
57721.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57731.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
57741.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57751.51Skamil		tracee_sees_its_original_parent_procfs_status);
57761.1Skamil
57771.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
57781.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
57791.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
57801.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
57811.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
57821.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
57831.1Skamil
57841.31Skamil	ATF_TP_ADD_TC(tp, fork1);
57851.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
57861.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
57871.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
57881.31Skamil	ATF_TP_ADD_TC(tp, fork5);
57891.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
57901.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
57911.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
57921.31Skamil
57931.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
57941.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
57951.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
57961.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
57971.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
57981.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
57991.64Smartin// thes tests hang on SMP machines, disable them for now
58001.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
58011.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
58021.1Skamil
58031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
58041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
58051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
58061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
58071.54Skamil
58081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
58091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
58101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
58111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
58121.54Skamil
58131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
58141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
58151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
58161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
58171.54Skamil
58181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
58191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
58201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
58211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
58221.54Skamil
58231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
58241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
58251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
58261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
58271.54Skamil
58281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
58291.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
58301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
58311.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
58321.54Skamil
58331.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
58341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
58351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
58361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
58371.54Skamil
58381.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
58391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
58401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
58411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
58421.54Skamil
58431.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
58441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
58451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
58461.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
58471.54Skamil
58481.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
58491.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
58501.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
58511.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
58521.1Skamil
58531.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
58541.1Skamil
58551.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
58561.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
58571.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
58581.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
58591.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
58601.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
58611.1Skamil
58621.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
58631.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
58641.1Skamil
58651.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
58661.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
58671.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
58681.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
58691.1Skamil
58701.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
58711.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
58721.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
58731.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
58741.2Skamil
58751.1Skamil	ATF_TP_ADD_TC(tp, kill1);
58761.1Skamil	ATF_TP_ADD_TC(tp, kill2);
58771.75Skamil	ATF_TP_ADD_TC(tp, kill3);
58781.1Skamil
58791.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
58801.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
58811.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
58821.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
58831.77Skamil
58841.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
58851.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
58861.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
58871.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
58881.1Skamil
58891.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
58901.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
58911.79Skamil
58921.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
58931.1Skamil
58941.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
58951.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
58961.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
58971.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
58981.1Skamil
58991.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
59001.84Skamil
59011.1Skamil	ATF_TP_ADD_TC(tp, signal3);
59021.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
59031.1Skamil	ATF_TP_ADD_TC(tp, signal5);
59041.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
59051.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
59061.1Skamil	ATF_TP_ADD_TC(tp, signal8);
59071.1Skamil	ATF_TP_ADD_TC(tp, signal9);
59081.1Skamil	ATF_TP_ADD_TC(tp, signal10);
59091.1Skamil
59101.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
59111.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
59121.1Skamil
59131.1Skamil	ATF_TP_ADD_TC(tp, resume1);
59141.1Skamil
59151.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
59161.1Skamil
59171.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
59181.1Skamil
59191.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
59201.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
59211.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
59221.1Skamil
59231.1Skamil	return atf_no_error();
59241.1Skamil}
5925