t_ptrace_wait.c revision 1.92
11.92Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.92 2019/02/17 09:29:35 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.92Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.92 2019/02/17 09:29:35 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.77Skamil#include <pthread.h>
471.1Skamil#include <sched.h>
481.1Skamil#include <signal.h>
491.1Skamil#include <stdint.h>
501.1Skamil#include <stdio.h>
511.1Skamil#include <stdlib.h>
521.1Skamil#include <strings.h>
531.26Skamil#include <time.h>
541.1Skamil#include <unistd.h>
551.1Skamil
561.1Skamil#include <atf-c.h>
571.1Skamil
581.1Skamil#include "h_macros.h"
591.1Skamil
601.1Skamil#include "t_ptrace_wait.h"
611.1Skamil#include "msg.h"
621.1Skamil
631.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
641.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
651.61Skre	sizeof(msg)) == 0)
661.1Skamil
671.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
681.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
691.61Skre	sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
721.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
731.61Skre	sizeof(msg)) == 0)
741.1Skamil
751.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
761.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
771.61Skre	sizeof(msg)) == 0)
781.13Schristos
791.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
801.13Schristos    strerror(errno))
811.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
821.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
831.13Schristos
841.13Schristosstatic int debug = 0;
851.13Schristos
861.13Schristos#define DPRINTF(a, ...)	do  \
871.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
881.13Schristos    while (/*CONSTCOND*/0)
891.1Skamil
901.34Skamil/// ----------------------------------------------------------------------------
911.34Skamil
921.33Skamilstatic void
931.33Skamiltraceme_raise(int sigval)
941.1Skamil{
951.1Skamil	const int exitval = 5;
961.1Skamil	pid_t child, wpid;
971.1Skamil#if defined(TWAIT_HAVE_STATUS)
981.1Skamil	int status;
991.1Skamil#endif
1001.1Skamil
1011.45Skamil	struct ptrace_siginfo info;
1021.45Skamil	memset(&info, 0, sizeof(info));
1031.45Skamil
1041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1061.1Skamil	if (child == 0) {
1071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1091.1Skamil
1101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1121.1Skamil
1131.36Skamil		switch (sigval) {
1141.36Skamil		case SIGKILL:
1151.36Skamil			/* NOTREACHED */
1161.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1171.70Smrg			__unreachable();
1181.36Skamil		default:
1191.36Skamil			DPRINTF("Before exiting of the child process\n");
1201.36Skamil			_exit(exitval);
1211.36Skamil		}
1221.1Skamil	}
1231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1241.1Skamil
1251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1271.1Skamil
1281.36Skamil	switch (sigval) {
1291.36Skamil	case SIGKILL:
1301.36Skamil		validate_status_signaled(status, sigval, 0);
1311.36Skamil		break;
1321.36Skamil	default:
1331.36Skamil		validate_status_stopped(status, sigval);
1341.1Skamil
1351.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1361.61Skre			"child\n");
1371.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1381.61Skre			sizeof(info)) != -1);
1391.45Skamil
1401.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1411.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1421.61Skre			"si_errno=%#x\n",
1431.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1441.61Skre			info.psi_siginfo.si_errno);
1451.45Skamil
1461.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1471.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1481.45Skamil
1491.36Skamil		DPRINTF("Before resuming the child process where it left off "
1501.36Skamil		    "and without signal to be sent\n");
1511.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1521.1Skamil
1531.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1541.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1551.61Skre		    child);
1561.36Skamil		break;
1571.36Skamil	}
1581.1Skamil
1591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1611.1Skamil}
1621.1Skamil
1631.61Skre#define TRACEME_RAISE(test, sig)					\
1641.61SkreATF_TC(test);								\
1651.61SkreATF_TC_HEAD(test, tc)							\
1661.61Skre{									\
1671.61Skre	atf_tc_set_md_var(tc, "descr",					\
1681.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1691.61Skre}									\
1701.61Skre									\
1711.61SkreATF_TC_BODY(test, tc)							\
1721.61Skre{									\
1731.61Skre									\
1741.61Skre	traceme_raise(sig);						\
1751.33Skamil}
1761.33Skamil
1771.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1781.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1791.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1801.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1811.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1821.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1831.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1841.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1851.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
1861.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
1871.33Skamil
1881.34Skamil/// ----------------------------------------------------------------------------
1891.1Skamil
1901.1Skamilstatic void
1911.87Skamiltraceme_raisesignal_ignored(int sigignored)
1921.87Skamil{
1931.87Skamil	const int exitval = 5;
1941.87Skamil	const int sigval = SIGSTOP;
1951.87Skamil	pid_t child, wpid;
1961.87Skamil	struct sigaction sa;
1971.87Skamil#if defined(TWAIT_HAVE_STATUS)
1981.87Skamil	int status;
1991.87Skamil#endif
2001.87Skamil	struct ptrace_siginfo info;
2011.87Skamil
2021.87Skamil	memset(&info, 0, sizeof(info));
2031.87Skamil
2041.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2051.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2061.87Skamil	if (child == 0) {
2071.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2081.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2091.87Skamil
2101.87Skamil		memset(&sa, 0, sizeof(sa));
2111.87Skamil		sa.sa_handler = SIG_IGN;
2121.87Skamil		sigemptyset(&sa.sa_mask);
2131.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2141.87Skamil
2151.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2161.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2171.87Skamil
2181.87Skamil		DPRINTF("Before raising %s from child\n",
2191.87Skamil		    strsignal(sigignored));
2201.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2211.87Skamil
2221.87Skamil		DPRINTF("Before exiting of the child process\n");
2231.87Skamil		_exit(exitval);
2241.87Skamil	}
2251.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2261.87Skamil
2271.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2281.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2291.87Skamil
2301.87Skamil	validate_status_stopped(status, sigval);
2311.87Skamil
2321.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2331.87Skamil	SYSCALL_REQUIRE(
2341.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2351.87Skamil
2361.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2371.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2381.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2391.87Skamil	    info.psi_siginfo.si_errno);
2401.87Skamil
2411.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2421.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2431.87Skamil
2441.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2451.87Skamil	    "without signal to be sent\n");
2461.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2471.87Skamil
2481.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2491.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2501.87Skamil
2511.87Skamil	validate_status_stopped(status, sigignored);
2521.87Skamil
2531.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2541.87Skamil	SYSCALL_REQUIRE(
2551.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2561.87Skamil
2571.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2581.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2591.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2601.87Skamil	    info.psi_siginfo.si_errno);
2611.87Skamil
2621.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2631.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2641.87Skamil
2651.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2661.87Skamil	    "without signal to be sent\n");
2671.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2681.87Skamil
2691.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2701.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2711.87Skamil
2721.87Skamil	validate_status_exited(status, exitval);
2731.87Skamil
2741.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2751.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2761.87Skamil}
2771.87Skamil
2781.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2791.87SkamilATF_TC(test);								\
2801.87SkamilATF_TC_HEAD(test, tc)							\
2811.87Skamil{									\
2821.87Skamil	atf_tc_set_md_var(tc, "descr",					\
2831.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
2841.87Skamil	    "does not stop tracer from catching this raised signal");	\
2851.87Skamil}									\
2861.87Skamil									\
2871.87SkamilATF_TC_BODY(test, tc)							\
2881.87Skamil{									\
2891.87Skamil									\
2901.87Skamil	traceme_raisesignal_ignored(sig);				\
2911.87Skamil}
2921.87Skamil
2931.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
2941.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
2951.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
2961.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
2971.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
2981.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
2991.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3001.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3011.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3021.87Skamil
3031.87Skamil/// ----------------------------------------------------------------------------
3041.87Skamil
3051.87Skamilstatic void
3061.86Skamiltraceme_raisesignal_masked(int sigmasked)
3071.86Skamil{
3081.86Skamil	const int exitval = 5;
3091.86Skamil	const int sigval = SIGSTOP;
3101.86Skamil	pid_t child, wpid;
3111.86Skamil#if defined(TWAIT_HAVE_STATUS)
3121.86Skamil	int status;
3131.86Skamil#endif
3141.86Skamil	sigset_t intmask;
3151.86Skamil	struct ptrace_siginfo info;
3161.86Skamil
3171.86Skamil	memset(&info, 0, sizeof(info));
3181.86Skamil
3191.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3201.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3211.86Skamil	if (child == 0) {
3221.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3231.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3241.86Skamil
3251.86Skamil		sigemptyset(&intmask);
3261.86Skamil		sigaddset(&intmask, sigmasked);
3271.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3281.86Skamil
3291.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3301.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3311.86Skamil
3321.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3331.86Skamil		    strsignal(sigmasked));
3341.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3351.86Skamil
3361.86Skamil		DPRINTF("Before exiting of the child process\n");
3371.86Skamil		_exit(exitval);
3381.86Skamil	}
3391.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3401.86Skamil
3411.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3421.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3431.86Skamil
3441.86Skamil	validate_status_stopped(status, sigval);
3451.86Skamil
3461.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3471.86Skamil	SYSCALL_REQUIRE(
3481.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3491.86Skamil
3501.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3511.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3521.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3531.86Skamil	    info.psi_siginfo.si_errno);
3541.86Skamil
3551.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3561.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3571.86Skamil
3581.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3591.86Skamil	    "without signal to be sent\n");
3601.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3611.86Skamil
3621.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3631.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3641.86Skamil
3651.86Skamil	validate_status_exited(status, exitval);
3661.86Skamil
3671.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3681.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3691.86Skamil}
3701.86Skamil
3711.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3721.86SkamilATF_TC(test);								\
3731.86SkamilATF_TC_HEAD(test, tc)							\
3741.86Skamil{									\
3751.86Skamil	atf_tc_set_md_var(tc, "descr",					\
3761.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3771.86Skamil	    "stops tracer from catching this raised signal");		\
3781.86Skamil}									\
3791.86Skamil									\
3801.86SkamilATF_TC_BODY(test, tc)							\
3811.86Skamil{									\
3821.86Skamil									\
3831.86Skamil	traceme_raisesignal_masked(sig);				\
3841.86Skamil}
3851.86Skamil
3861.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
3871.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
3881.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
3891.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
3901.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
3911.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
3921.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
3931.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
3941.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
3951.86Skamil
3961.86Skamil/// ----------------------------------------------------------------------------
3971.86Skamil
3981.86Skamilstatic void
3991.59Skamiltraceme_crash(int sig)
4001.59Skamil{
4011.59Skamil	pid_t child, wpid;
4021.59Skamil#if defined(TWAIT_HAVE_STATUS)
4031.59Skamil	int status;
4041.59Skamil#endif
4051.59Skamil	struct ptrace_siginfo info;
4061.61Skre
4071.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4081.71Skamil	if (sig == SIGILL)
4091.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4101.71Skamil#endif
4111.71Skamil
4121.59Skamil	memset(&info, 0, sizeof(info));
4131.59Skamil
4141.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4151.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4161.59Skamil	if (child == 0) {
4171.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4181.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4191.59Skamil
4201.59Skamil		DPRINTF("Before executing a trap\n");
4211.59Skamil		switch (sig) {
4221.59Skamil		case SIGTRAP:
4231.59Skamil			trigger_trap();
4241.59Skamil			break;
4251.59Skamil		case SIGSEGV:
4261.59Skamil			trigger_segv();
4271.59Skamil			break;
4281.59Skamil		case SIGILL:
4291.59Skamil			trigger_ill();
4301.59Skamil			break;
4311.59Skamil		case SIGFPE:
4321.59Skamil			trigger_fpe();
4331.59Skamil			break;
4341.59Skamil		case SIGBUS:
4351.59Skamil			trigger_bus();
4361.59Skamil			break;
4371.59Skamil		default:
4381.59Skamil			/* NOTREACHED */
4391.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4401.59Skamil		}
4411.59Skamil
4421.59Skamil		/* NOTREACHED */
4431.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4441.59Skamil	}
4451.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4461.59Skamil
4471.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4481.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4491.59Skamil
4501.59Skamil	validate_status_stopped(status, sig);
4511.59Skamil
4521.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4531.61Skre	SYSCALL_REQUIRE(
4541.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4551.59Skamil
4561.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4571.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4581.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4591.61Skre	    info.psi_siginfo.si_errno);
4601.59Skamil
4611.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4621.59Skamil	switch (sig) {
4631.59Skamil	case SIGTRAP:
4641.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4651.59Skamil		break;
4661.59Skamil	case SIGSEGV:
4671.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4681.59Skamil		break;
4691.71Skamil	case SIGILL:
4701.71Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
4711.71Skamil		break;
4721.59Skamil	case SIGFPE:
4731.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4741.59Skamil		break;
4751.59Skamil	case SIGBUS:
4761.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
4771.59Skamil		break;
4781.59Skamil	}
4791.59Skamil
4801.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
4811.59Skamil
4821.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4831.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4841.59Skamil
4851.59Skamil	validate_status_signaled(status, SIGKILL, 0);
4861.59Skamil
4871.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4881.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4891.59Skamil}
4901.59Skamil
4911.61Skre#define TRACEME_CRASH(test, sig)					\
4921.61SkreATF_TC(test);								\
4931.61SkreATF_TC_HEAD(test, tc)							\
4941.61Skre{									\
4951.61Skre	atf_tc_set_md_var(tc, "descr",					\
4961.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
4971.61Skre}									\
4981.61Skre									\
4991.61SkreATF_TC_BODY(test, tc)							\
5001.61Skre{									\
5011.61Skre									\
5021.61Skre	traceme_crash(sig);						\
5031.59Skamil}
5041.59Skamil
5051.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5061.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5071.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5081.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5091.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5101.59Skamil
5111.59Skamil/// ----------------------------------------------------------------------------
5121.59Skamil
5131.59Skamilstatic void
5141.88Skamiltraceme_signalmasked_crash(int sig)
5151.88Skamil{
5161.89Skamil	const int sigval = SIGSTOP;
5171.88Skamil	pid_t child, wpid;
5181.88Skamil#if defined(TWAIT_HAVE_STATUS)
5191.88Skamil	int status;
5201.88Skamil#endif
5211.88Skamil	struct ptrace_siginfo info;
5221.88Skamil	sigset_t intmask;
5231.89Skamil	struct kinfo_proc2 kp;
5241.89Skamil	size_t len = sizeof(kp);
5251.89Skamil
5261.89Skamil	int name[6];
5271.89Skamil	const size_t namelen = __arraycount(name);
5281.89Skamil	ki_sigset_t kp_sigmask;
5291.88Skamil
5301.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5311.88Skamil	if (sig == SIGILL)
5321.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5331.88Skamil#endif
5341.88Skamil
5351.88Skamil	memset(&info, 0, sizeof(info));
5361.88Skamil
5371.89Skamil	atf_tc_expect_fail("Unexpected sigmask reset on crash under debugger");
5381.89Skamil
5391.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5401.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5411.88Skamil	if (child == 0) {
5421.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5431.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5441.88Skamil
5451.88Skamil		sigemptyset(&intmask);
5461.88Skamil		sigaddset(&intmask, sig);
5471.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5481.88Skamil
5491.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5501.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5511.89Skamil
5521.88Skamil		DPRINTF("Before executing a trap\n");
5531.88Skamil		switch (sig) {
5541.88Skamil		case SIGTRAP:
5551.88Skamil			trigger_trap();
5561.88Skamil			break;
5571.88Skamil		case SIGSEGV:
5581.88Skamil			trigger_segv();
5591.88Skamil			break;
5601.88Skamil		case SIGILL:
5611.88Skamil			trigger_ill();
5621.88Skamil			break;
5631.88Skamil		case SIGFPE:
5641.88Skamil			trigger_fpe();
5651.88Skamil			break;
5661.88Skamil		case SIGBUS:
5671.88Skamil			trigger_bus();
5681.88Skamil			break;
5691.88Skamil		default:
5701.88Skamil			/* NOTREACHED */
5711.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5721.88Skamil		}
5731.88Skamil
5741.88Skamil		/* NOTREACHED */
5751.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5761.88Skamil	}
5771.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5781.88Skamil
5791.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5801.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5811.88Skamil
5821.89Skamil	validate_status_stopped(status, sigval);
5831.89Skamil
5841.89Skamil	name[0] = CTL_KERN,
5851.89Skamil	name[1] = KERN_PROC2,
5861.89Skamil	name[2] = KERN_PROC_PID;
5871.89Skamil	name[3] = child;
5881.89Skamil	name[4] = sizeof(kp);
5891.89Skamil	name[5] = 1;
5901.89Skamil
5911.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
5921.89Skamil
5931.89Skamil	kp_sigmask = kp.p_sigmask;
5941.89Skamil
5951.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5961.89Skamil	SYSCALL_REQUIRE(
5971.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5981.89Skamil
5991.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6001.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6011.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6021.89Skamil	    info.psi_siginfo.si_errno);
6031.89Skamil
6041.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6051.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6061.89Skamil
6071.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6081.89Skamil	    "without signal to be sent\n");
6091.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6101.89Skamil
6111.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6121.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6131.89Skamil
6141.88Skamil	validate_status_stopped(status, sig);
6151.88Skamil
6161.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6171.88Skamil	SYSCALL_REQUIRE(
6181.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6191.88Skamil
6201.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6211.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6221.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6231.88Skamil	    info.psi_siginfo.si_errno);
6241.88Skamil
6251.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6261.89Skamil
6271.89Skamil	DPRINTF("kp_sigmask="
6281.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6291.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6301.89Skamil	    kp_sigmask.__bits[3]);
6311.89Skamil
6321.89Skamil	DPRINTF("kp.p_sigmask="
6331.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6341.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6351.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6361.89Skamil
6371.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6381.89Skamil
6391.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6401.88Skamil	switch (sig) {
6411.88Skamil	case SIGTRAP:
6421.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6431.88Skamil		break;
6441.88Skamil	case SIGSEGV:
6451.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6461.88Skamil		break;
6471.88Skamil	case SIGILL:
6481.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
6491.88Skamil		break;
6501.88Skamil	case SIGFPE:
6511.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6521.88Skamil		break;
6531.88Skamil	case SIGBUS:
6541.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6551.88Skamil		break;
6561.88Skamil	}
6571.88Skamil
6581.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6591.88Skamil
6601.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6611.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6621.88Skamil
6631.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6641.88Skamil
6651.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6661.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6671.88Skamil}
6681.88Skamil
6691.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6701.88SkamilATF_TC(test);								\
6711.88SkamilATF_TC_HEAD(test, tc)							\
6721.88Skamil{									\
6731.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6741.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6751.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6761.88Skamil}									\
6771.88Skamil									\
6781.88SkamilATF_TC_BODY(test, tc)							\
6791.88Skamil{									\
6801.88Skamil									\
6811.88Skamil	traceme_signalmasked_crash(sig);				\
6821.88Skamil}
6831.88Skamil
6841.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
6851.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
6861.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
6871.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
6881.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
6891.88Skamil
6901.88Skamil/// ----------------------------------------------------------------------------
6911.88Skamil
6921.88Skamilstatic void
6931.88Skamiltraceme_signalignored_crash(int sig)
6941.88Skamil{
6951.90Skamil	const int sigval = SIGSTOP;
6961.88Skamil	pid_t child, wpid;
6971.88Skamil#if defined(TWAIT_HAVE_STATUS)
6981.88Skamil	int status;
6991.88Skamil#endif
7001.88Skamil	struct sigaction sa;
7011.88Skamil	struct ptrace_siginfo info;
7021.90Skamil	struct kinfo_proc2 kp;
7031.90Skamil	size_t len = sizeof(kp);
7041.90Skamil
7051.90Skamil	int name[6];
7061.90Skamil	const size_t namelen = __arraycount(name);
7071.90Skamil	ki_sigset_t kp_sigignore;
7081.88Skamil
7091.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7101.88Skamil	if (sig == SIGILL)
7111.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7121.88Skamil#endif
7131.88Skamil
7141.90Skamil	atf_tc_expect_fail("Unexpected sigmask reset on crash under debugger");
7151.90Skamil
7161.88Skamil	memset(&info, 0, sizeof(info));
7171.88Skamil
7181.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7191.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7201.88Skamil	if (child == 0) {
7211.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7221.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7231.88Skamil
7241.88Skamil		memset(&sa, 0, sizeof(sa));
7251.88Skamil		sa.sa_handler = SIG_IGN;
7261.88Skamil		sigemptyset(&sa.sa_mask);
7271.88Skamil
7281.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7291.88Skamil
7301.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7311.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7321.90Skamil
7331.88Skamil		DPRINTF("Before executing a trap\n");
7341.88Skamil		switch (sig) {
7351.88Skamil		case SIGTRAP:
7361.88Skamil			trigger_trap();
7371.88Skamil			break;
7381.88Skamil		case SIGSEGV:
7391.88Skamil			trigger_segv();
7401.88Skamil			break;
7411.88Skamil		case SIGILL:
7421.88Skamil			trigger_ill();
7431.88Skamil			break;
7441.88Skamil		case SIGFPE:
7451.88Skamil			trigger_fpe();
7461.88Skamil			break;
7471.88Skamil		case SIGBUS:
7481.88Skamil			trigger_bus();
7491.88Skamil			break;
7501.88Skamil		default:
7511.88Skamil			/* NOTREACHED */
7521.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7531.88Skamil		}
7541.88Skamil
7551.88Skamil		/* NOTREACHED */
7561.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7571.88Skamil	}
7581.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7591.88Skamil
7601.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7611.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7621.88Skamil
7631.90Skamil	validate_status_stopped(status, sigval);
7641.90Skamil
7651.90Skamil	name[0] = CTL_KERN,
7661.90Skamil	name[1] = KERN_PROC2,
7671.90Skamil	name[2] = KERN_PROC_PID;
7681.90Skamil	name[3] = child;
7691.90Skamil	name[4] = sizeof(kp);
7701.90Skamil	name[5] = 1;
7711.90Skamil
7721.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
7731.90Skamil
7741.90Skamil	kp_sigignore = kp.p_sigignore;
7751.90Skamil
7761.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7771.90Skamil	SYSCALL_REQUIRE(
7781.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7791.90Skamil
7801.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7811.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7821.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7831.90Skamil	    info.psi_siginfo.si_errno);
7841.90Skamil
7851.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
7861.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
7871.90Skamil
7881.90Skamil	DPRINTF("Before resuming the child process where it left off and "
7891.90Skamil	    "without signal to be sent\n");
7901.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
7911.90Skamil
7921.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7931.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7941.90Skamil
7951.88Skamil	validate_status_stopped(status, sig);
7961.88Skamil
7971.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
7981.88Skamil	SYSCALL_REQUIRE(
7991.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8001.88Skamil
8011.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8021.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8031.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8041.88Skamil	    info.psi_siginfo.si_errno);
8051.88Skamil
8061.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8071.90Skamil
8081.90Skamil	DPRINTF("kp_sigignore="
8091.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8101.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8111.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8121.90Skamil
8131.90Skamil	DPRINTF("kp.p_sigignore="
8141.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8151.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8161.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8171.90Skamil
8181.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8191.90Skamil
8201.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8211.88Skamil	switch (sig) {
8221.88Skamil	case SIGTRAP:
8231.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8241.88Skamil		break;
8251.88Skamil	case SIGSEGV:
8261.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8271.88Skamil		break;
8281.88Skamil	case SIGILL:
8291.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
8301.88Skamil		break;
8311.88Skamil	case SIGFPE:
8321.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8331.88Skamil		break;
8341.88Skamil	case SIGBUS:
8351.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8361.88Skamil		break;
8371.88Skamil	}
8381.88Skamil
8391.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8401.88Skamil
8411.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8421.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8431.88Skamil
8441.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8451.88Skamil
8461.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8471.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8481.88Skamil}
8491.88Skamil
8501.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8511.88SkamilATF_TC(test);								\
8521.88SkamilATF_TC_HEAD(test, tc)							\
8531.88Skamil{									\
8541.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8551.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8561.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8571.88Skamil}									\
8581.88Skamil									\
8591.88SkamilATF_TC_BODY(test, tc)							\
8601.88Skamil{									\
8611.88Skamil									\
8621.88Skamil	traceme_signalignored_crash(sig);				\
8631.88Skamil}
8641.88Skamil
8651.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8661.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8671.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8681.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8691.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8701.88Skamil
8711.88Skamil/// ----------------------------------------------------------------------------
8721.88Skamil
8731.88Skamilstatic void
8741.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
8751.1Skamil{
8761.1Skamil	const int exitval = 5;
8771.34Skamil	const int sigval = SIGSTOP;
8781.1Skamil	pid_t child, wpid;
8791.1Skamil	struct sigaction sa;
8801.1Skamil#if defined(TWAIT_HAVE_STATUS)
8811.1Skamil	int status;
8821.1Skamil#endif
8831.61Skre	struct ptrace_siginfo info;
8841.1Skamil
8851.45Skamil	memset(&info, 0, sizeof(info));
8861.45Skamil
8871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
8881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
8891.1Skamil	if (child == 0) {
8901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8921.1Skamil
8931.34Skamil		sa.sa_handler = sah;
8941.1Skamil		sa.sa_flags = SA_SIGINFO;
8951.1Skamil		sigemptyset(&sa.sa_mask);
8961.1Skamil
8971.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
8981.1Skamil
8991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9011.1Skamil
9021.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9031.1Skamil
9041.13Schristos		DPRINTF("Before exiting of the child process\n");
9051.1Skamil		_exit(exitval);
9061.1Skamil	}
9071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9081.1Skamil
9091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9111.1Skamil
9121.1Skamil	validate_status_stopped(status, sigval);
9131.1Skamil
9141.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9151.61Skre	SYSCALL_REQUIRE(
9161.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9171.45Skamil
9181.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9191.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9201.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9211.45Skamil	    info.psi_siginfo.si_errno);
9221.45Skamil
9231.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9241.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9251.45Skamil
9261.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9271.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9291.1Skamil
9301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9321.1Skamil
9331.1Skamil	validate_status_exited(status, exitval);
9341.1Skamil
9351.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9371.1Skamil}
9381.1Skamil
9391.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9401.61SkreATF_TC(test);								\
9411.61SkreATF_TC_HEAD(test, tc)							\
9421.61Skre{									\
9431.61Skre	atf_tc_set_md_var(tc, "descr",					\
9441.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9451.61Skre	    "handled correctly and caught by a signal handler");	\
9461.61Skre}									\
9471.61Skre									\
9481.61Skrestatic int test##_caught = 0;						\
9491.61Skre									\
9501.61Skrestatic void								\
9511.61Skretest##_sighandler(int arg)						\
9521.61Skre{									\
9531.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9541.61Skre									\
9551.61Skre	++ test##_caught;						\
9561.61Skre}									\
9571.61Skre									\
9581.61SkreATF_TC_BODY(test, tc)							\
9591.61Skre{									\
9601.61Skre									\
9611.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9621.34Skamil}
9631.34Skamil
9641.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9651.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9661.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9671.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9681.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9691.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9701.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9711.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
9721.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
9731.34Skamil
9741.34Skamil/// ----------------------------------------------------------------------------
9751.34Skamil
9761.35Skamilstatic void
9771.50Skamiltraceme_sendsignal_masked(int sigsent)
9781.50Skamil{
9791.50Skamil	const int exitval = 5;
9801.50Skamil	const int sigval = SIGSTOP;
9811.50Skamil	pid_t child, wpid;
9821.50Skamil	sigset_t set;
9831.50Skamil#if defined(TWAIT_HAVE_STATUS)
9841.50Skamil	int status;
9851.50Skamil#endif
9861.61Skre	struct ptrace_siginfo info;
9871.50Skamil
9881.50Skamil	memset(&info, 0, sizeof(info));
9891.50Skamil
9901.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9911.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
9921.50Skamil	if (child == 0) {
9931.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9941.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9951.50Skamil
9961.50Skamil		sigemptyset(&set);
9971.50Skamil		sigaddset(&set, sigsent);
9981.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
9991.50Skamil
10001.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10011.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10021.50Skamil
10031.50Skamil		_exit(exitval);
10041.50Skamil	}
10051.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10061.50Skamil
10071.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10081.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10091.50Skamil
10101.50Skamil	validate_status_stopped(status, sigval);
10111.50Skamil
10121.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10131.61Skre	SYSCALL_REQUIRE(
10141.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10151.50Skamil
10161.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10171.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10181.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10191.50Skamil	    info.psi_siginfo.si_errno);
10201.50Skamil
10211.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10221.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10231.50Skamil
10241.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10251.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10261.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10271.50Skamil
10281.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10291.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10301.50Skamil
10311.50Skamil	validate_status_exited(status, exitval);
10321.50Skamil
10331.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10341.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10351.50Skamil}
10361.50Skamil
10371.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10381.61SkreATF_TC(test);								\
10391.61SkreATF_TC_HEAD(test, tc)							\
10401.61Skre{									\
10411.61Skre	atf_tc_set_md_var(tc, "descr",					\
10421.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10431.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10441.61Skre}									\
10451.61Skre									\
10461.61SkreATF_TC_BODY(test, tc)							\
10471.61Skre{									\
10481.61Skre									\
10491.61Skre	traceme_sendsignal_masked(sig);					\
10501.50Skamil}
10511.50Skamil
10521.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10531.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10541.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10551.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10561.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10571.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10581.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10591.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10601.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10611.50Skamil
10621.50Skamil/// ----------------------------------------------------------------------------
10631.50Skamil
10641.50Skamilstatic void
10651.50Skamiltraceme_sendsignal_ignored(int sigsent)
10661.50Skamil{
10671.50Skamil	const int exitval = 5;
10681.50Skamil	const int sigval = SIGSTOP;
10691.50Skamil	pid_t child, wpid;
10701.50Skamil	struct sigaction sa;
10711.50Skamil#if defined(TWAIT_HAVE_STATUS)
10721.50Skamil	int status;
10731.50Skamil#endif
10741.61Skre	struct ptrace_siginfo info;
10751.50Skamil
10761.50Skamil	memset(&info, 0, sizeof(info));
10771.50Skamil
10781.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10791.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10801.50Skamil	if (child == 0) {
10811.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10821.61Skre
10831.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10841.50Skamil
10851.50Skamil		memset(&sa, 0, sizeof(sa));
10861.50Skamil		sa.sa_handler = SIG_IGN;
10871.50Skamil		sigemptyset(&sa.sa_mask);
10881.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
10891.50Skamil
10901.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10911.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10921.50Skamil
10931.50Skamil		_exit(exitval);
10941.50Skamil	}
10951.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10961.50Skamil
10971.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10981.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10991.50Skamil
11001.50Skamil	validate_status_stopped(status, sigval);
11011.50Skamil
11021.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11031.61Skre	SYSCALL_REQUIRE(
11041.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11051.50Skamil
11061.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11071.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11081.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11091.50Skamil	    info.psi_siginfo.si_errno);
11101.50Skamil
11111.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11121.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11131.50Skamil
11141.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11151.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11161.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11171.50Skamil
11181.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11191.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11201.50Skamil
11211.50Skamil	validate_status_exited(status, exitval);
11221.50Skamil
11231.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11241.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11251.50Skamil}
11261.50Skamil
11271.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11281.61SkreATF_TC(test);								\
11291.61SkreATF_TC_HEAD(test, tc)							\
11301.61Skre{									\
11311.61Skre	atf_tc_set_md_var(tc, "descr",					\
11321.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11331.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11341.61Skre}									\
11351.61Skre									\
11361.61SkreATF_TC_BODY(test, tc)							\
11371.61Skre{									\
11381.61Skre									\
11391.61Skre	traceme_sendsignal_ignored(sig);				\
11401.50Skamil}
11411.50Skamil
11421.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11431.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11441.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11451.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11461.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11471.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11481.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11491.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11501.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11511.50Skamil
11521.50Skamil/// ----------------------------------------------------------------------------
11531.50Skamil
11541.50Skamilstatic void
11551.50Skamiltraceme_sendsignal_simple(int sigsent)
11561.1Skamil{
11571.35Skamil	const int sigval = SIGSTOP;
11581.35Skamil	int exitval = 0;
11591.1Skamil	pid_t child, wpid;
11601.1Skamil#if defined(TWAIT_HAVE_STATUS)
11611.1Skamil	int status;
11621.85Skamil	int expect_core;
11631.85Skamil
11641.85Skamil	switch (sigsent) {
11651.85Skamil	case SIGABRT:
11661.85Skamil	case SIGTRAP:
11671.85Skamil	case SIGBUS:
11681.85Skamil	case SIGILL:
11691.85Skamil	case SIGFPE:
11701.85Skamil	case SIGSEGV:
11711.85Skamil		expect_core = 1;
11721.85Skamil		break;
11731.85Skamil	default:
11741.85Skamil		expect_core = 0;
11751.85Skamil		break;
11761.85Skamil	}
11771.1Skamil#endif
11781.61Skre	struct ptrace_siginfo info;
11791.1Skamil
11801.45Skamil	memset(&info, 0, sizeof(info));
11811.45Skamil
11821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
11831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
11841.1Skamil	if (child == 0) {
11851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11871.1Skamil
11881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11901.1Skamil
11911.35Skamil		switch (sigsent) {
11921.35Skamil		case SIGCONT:
11931.48Skamil		case SIGSTOP:
11941.35Skamil			_exit(exitval);
11951.35Skamil		default:
11961.35Skamil			/* NOTREACHED */
11971.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
11981.35Skamil		}
11991.1Skamil	}
12001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12011.1Skamil
12021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12041.1Skamil
12051.1Skamil	validate_status_stopped(status, sigval);
12061.1Skamil
12071.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12081.61Skre	SYSCALL_REQUIRE(
12091.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12101.45Skamil
12111.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12121.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12131.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12141.45Skamil	    info.psi_siginfo.si_errno);
12151.45Skamil
12161.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12171.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12181.45Skamil
12191.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12201.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12221.1Skamil
12231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12251.1Skamil
12261.35Skamil	switch (sigsent) {
12271.48Skamil	case SIGSTOP:
12281.48Skamil		validate_status_stopped(status, sigsent);
12291.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12301.61Skre		    "child\n");
12311.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12321.61Skre		    sizeof(info)) != -1);
12331.48Skamil
12341.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12351.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12361.61Skre		    "si_errno=%#x\n",
12371.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12381.61Skre		    info.psi_siginfo.si_errno);
12391.48Skamil
12401.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12411.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12421.48Skamil
12431.48Skamil		DPRINTF("Before resuming the child process where it left off "
12441.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12451.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12461.48Skamil
12471.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12481.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12491.61Skre		    child);
12501.48Skamil		/* FALLTHROUGH */
12511.35Skamil	case SIGCONT:
12521.35Skamil		validate_status_exited(status, exitval);
12531.35Skamil		break;
12541.35Skamil	default:
12551.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12561.35Skamil		break;
12571.35Skamil	}
12581.1Skamil
12591.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12611.1Skamil}
12621.1Skamil
12631.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12641.61SkreATF_TC(test);								\
12651.61SkreATF_TC_HEAD(test, tc)							\
12661.61Skre{									\
12671.61Skre	atf_tc_set_md_var(tc, "descr",					\
12681.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12691.61Skre	    "handled correctly in a child without a signal handler");	\
12701.61Skre}									\
12711.61Skre									\
12721.61SkreATF_TC_BODY(test, tc)							\
12731.61Skre{									\
12741.61Skre									\
12751.61Skre	traceme_sendsignal_simple(sig);					\
12761.35Skamil}
12771.35Skamil
12781.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
12791.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
12801.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
12811.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
12821.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
12831.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
12841.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
12851.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
12861.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
12871.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
12881.35Skamil
12891.35Skamil/// ----------------------------------------------------------------------------
12901.35Skamil
12911.37SkamilATF_TC(traceme_pid1_parent);
12921.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
12931.37Skamil{
12941.37Skamil	atf_tc_set_md_var(tc, "descr",
12951.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
12961.37Skamil}
12971.37Skamil
12981.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
12991.37Skamil{
13001.37Skamil	struct msg_fds parent_child;
13011.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13021.37Skamil	pid_t child1, child2, wpid;
13031.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13041.37Skamil#if defined(TWAIT_HAVE_STATUS)
13051.37Skamil	int status;
13061.37Skamil#endif
13071.37Skamil
13081.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13091.37Skamil
13101.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13111.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13121.37Skamil	if (child1 == 0) {
13131.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13141.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13151.37Skamil		if (child2 != 0) {
13161.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13171.61Skre			    getpid(), child2);
13181.37Skamil			_exit(exitval_child1);
13191.37Skamil		}
13201.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13211.37Skamil
13221.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13231.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13241.37Skamil
13251.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13261.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13271.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13281.37Skamil
13291.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13301.37Skamil
13311.37Skamil		_exit(exitval_child2);
13321.37Skamil	}
13331.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13341.37Skamil
13351.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13361.61Skre	TWAIT_REQUIRE_SUCCESS(
13371.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13381.37Skamil
13391.37Skamil	validate_status_exited(status, exitval_child1);
13401.37Skamil
13411.37Skamil	DPRINTF("Notify that child1 is dead\n");
13421.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13431.37Skamil
13441.37Skamil	DPRINTF("Wait for exiting of child2\n");
13451.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13461.37Skamil}
13471.37Skamil
13481.37Skamil/// ----------------------------------------------------------------------------
13491.37Skamil
13501.40Skamilstatic void
13511.40Skamiltraceme_vfork_raise(int sigval)
13521.40Skamil{
13531.46Skamil	const int exitval = 5, exitval_watcher = 10;
13541.46Skamil	pid_t child, parent, watcher, wpid;
13551.46Skamil	int rv;
13561.40Skamil#if defined(TWAIT_HAVE_STATUS)
13571.40Skamil	int status;
13581.85Skamil
13591.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13601.85Skamil	volatile int expect_core;
13611.85Skamil
13621.85Skamil	switch (sigval) {
13631.85Skamil	case SIGABRT:
13641.85Skamil	case SIGTRAP:
13651.85Skamil	case SIGBUS:
13661.85Skamil	case SIGILL:
13671.85Skamil	case SIGFPE:
13681.85Skamil	case SIGSEGV:
13691.85Skamil		expect_core = 1;
13701.85Skamil		break;
13711.85Skamil	default:
13721.85Skamil		expect_core = 0;
13731.85Skamil		break;
13741.85Skamil	}
13751.40Skamil#endif
13761.40Skamil
13771.46Skamil	/*
13781.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
13791.46Skamil	 * the SIGKILL signal to it.
13801.46Skamil	 *
13811.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
13821.46Skamil	 * simpler to reparent this process to initproc and forget about it.
13831.46Skamil	 */
13841.46Skamil	if (sigval == SIGSTOP) {
13851.46Skamil		parent = getpid();
13861.46Skamil
13871.46Skamil		watcher = fork();
13881.46Skamil		ATF_REQUIRE(watcher != 1);
13891.46Skamil		if (watcher == 0) {
13901.46Skamil			/* Double fork(2) trick to reparent to initproc */
13911.46Skamil			watcher = fork();
13921.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
13931.46Skamil			if (watcher != 0)
13941.46Skamil				_exit(exitval_watcher);
13951.46Skamil
13961.46Skamil			child = await_stopped_child(parent);
13971.46Skamil
13981.46Skamil			errno = 0;
13991.46Skamil			rv = kill(child, SIGKILL);
14001.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
14011.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14021.46Skamil
14031.46Skamil			/* This exit value will be collected by initproc */
14041.46Skamil			_exit(0);
14051.46Skamil		}
14061.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14071.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14081.61Skre		    watcher);
14091.46Skamil
14101.46Skamil		validate_status_exited(status, exitval_watcher);
14111.46Skamil
14121.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14131.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14141.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14151.46Skamil	}
14161.46Skamil
14171.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14181.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14191.40Skamil	if (child == 0) {
14201.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14211.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14221.40Skamil
14231.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14241.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14251.40Skamil
14261.40Skamil		switch (sigval) {
14271.46Skamil		case SIGSTOP:
14281.40Skamil		case SIGKILL:
14291.40Skamil		case SIGABRT:
14301.40Skamil		case SIGHUP:
14311.85Skamil		case SIGTRAP:
14321.85Skamil		case SIGBUS:
14331.85Skamil		case SIGILL:
14341.85Skamil		case SIGFPE:
14351.85Skamil		case SIGSEGV:
14361.40Skamil			/* NOTREACHED */
14371.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14381.70Smrg			__unreachable();
14391.40Skamil		default:
14401.40Skamil			DPRINTF("Before exiting of the child process\n");
14411.40Skamil			_exit(exitval);
14421.40Skamil		}
14431.40Skamil	}
14441.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14451.40Skamil
14461.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14471.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14481.40Skamil
14491.40Skamil	switch (sigval) {
14501.40Skamil	case SIGKILL:
14511.40Skamil	case SIGABRT:
14521.40Skamil	case SIGHUP:
14531.85Skamil	case SIGTRAP:
14541.85Skamil	case SIGBUS:
14551.85Skamil	case SIGILL:
14561.85Skamil	case SIGFPE:
14571.85Skamil	case SIGSEGV:
14581.40Skamil		validate_status_signaled(status, sigval, expect_core);
14591.40Skamil		break;
14601.40Skamil	case SIGSTOP:
14611.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14621.46Skamil		break;
14631.40Skamil	case SIGCONT:
14641.47Skamil	case SIGTSTP:
14651.47Skamil	case SIGTTIN:
14661.47Skamil	case SIGTTOU:
14671.40Skamil		validate_status_exited(status, exitval);
14681.40Skamil		break;
14691.40Skamil	default:
14701.40Skamil		/* NOTREACHED */
14711.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
14721.40Skamil		break;
14731.40Skamil	}
14741.40Skamil
14751.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14761.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14771.40Skamil}
14781.40Skamil
14791.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
14801.61SkreATF_TC(test);								\
14811.61SkreATF_TC_HEAD(test, tc)							\
14821.61Skre{									\
14831.61Skre	atf_tc_set_md_var(tc, "descr",					\
14841.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
14851.61Skre	    "vfork(2)ed child");					\
14861.61Skre}									\
14871.61Skre									\
14881.61SkreATF_TC_BODY(test, tc)							\
14891.61Skre{									\
14901.61Skre									\
14911.61Skre	traceme_vfork_raise(sig);					\
14921.40Skamil}
14931.40Skamil
14941.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
14951.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
14961.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
14971.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
14981.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
14991.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
15001.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
15011.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15021.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15031.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15041.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15051.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15061.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15071.40Skamil
15081.40Skamil/// ----------------------------------------------------------------------------
15091.40Skamil
15101.52Skamilstatic void
15111.52Skamiltraceme_vfork_crash(int sig)
15121.41Skamil{
15131.41Skamil	pid_t child, wpid;
15141.41Skamil#if defined(TWAIT_HAVE_STATUS)
15151.41Skamil	int status;
15161.41Skamil#endif
15171.41Skamil
15181.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15191.71Skamil	if (sig == SIGILL)
15201.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15211.71Skamil#endif
15221.71Skamil
15231.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15241.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15251.41Skamil	if (child == 0) {
15261.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15271.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15281.41Skamil
15291.52Skamil		DPRINTF("Before executing a trap\n");
15301.52Skamil		switch (sig) {
15311.52Skamil		case SIGTRAP:
15321.52Skamil			trigger_trap();
15331.52Skamil			break;
15341.52Skamil		case SIGSEGV:
15351.52Skamil			trigger_segv();
15361.52Skamil			break;
15371.52Skamil		case SIGILL:
15381.52Skamil			trigger_ill();
15391.52Skamil			break;
15401.52Skamil		case SIGFPE:
15411.52Skamil			trigger_fpe();
15421.52Skamil			break;
15431.52Skamil		case SIGBUS:
15441.52Skamil			trigger_bus();
15451.52Skamil			break;
15461.52Skamil		default:
15471.52Skamil			/* NOTREACHED */
15481.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15491.52Skamil		}
15501.41Skamil
15511.41Skamil		/* NOTREACHED */
15521.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15531.41Skamil	}
15541.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15551.41Skamil
15561.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15571.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15581.41Skamil
15591.52Skamil	validate_status_signaled(status, sig, 1);
15601.41Skamil
15611.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15621.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15631.41Skamil}
15641.41Skamil
15651.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15661.61SkreATF_TC(test);								\
15671.61SkreATF_TC_HEAD(test, tc)							\
15681.61Skre{									\
15691.61Skre	atf_tc_set_md_var(tc, "descr",					\
15701.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
15711.61Skre	    "vfork(2)ed child");					\
15721.61Skre}									\
15731.61Skre									\
15741.61SkreATF_TC_BODY(test, tc)							\
15751.61Skre{									\
15761.61Skre									\
15771.61Skre	traceme_vfork_crash(sig);					\
15781.52Skamil}
15791.52Skamil
15801.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
15811.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
15821.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
15831.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
15841.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
15851.52Skamil
15861.41Skamil/// ----------------------------------------------------------------------------
15871.41Skamil
15881.92Skamilstatic void
15891.92Skamiltraceme_vfork_signalmasked_crash(int sig)
15901.92Skamil{
15911.92Skamil	pid_t child, wpid;
15921.92Skamil#if defined(TWAIT_HAVE_STATUS)
15931.92Skamil	int status;
15941.92Skamil#endif
15951.92Skamil	sigset_t intmask;
15961.92Skamil
15971.92Skamil#ifndef PTRACE_ILLEGAL_ASM
15981.92Skamil	if (sig == SIGILL)
15991.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16001.92Skamil#endif
16011.92Skamil
16021.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16031.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16041.92Skamil	if (child == 0) {
16051.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16061.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16071.92Skamil
16081.92Skamil		sigemptyset(&intmask);
16091.92Skamil		sigaddset(&intmask, sig);
16101.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16111.92Skamil
16121.92Skamil		DPRINTF("Before executing a trap\n");
16131.92Skamil		switch (sig) {
16141.92Skamil		case SIGTRAP:
16151.92Skamil			trigger_trap();
16161.92Skamil			break;
16171.92Skamil		case SIGSEGV:
16181.92Skamil			trigger_segv();
16191.92Skamil			break;
16201.92Skamil		case SIGILL:
16211.92Skamil			trigger_ill();
16221.92Skamil			break;
16231.92Skamil		case SIGFPE:
16241.92Skamil			trigger_fpe();
16251.92Skamil			break;
16261.92Skamil		case SIGBUS:
16271.92Skamil			trigger_bus();
16281.92Skamil			break;
16291.92Skamil		default:
16301.92Skamil			/* NOTREACHED */
16311.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16321.92Skamil		}
16331.92Skamil
16341.92Skamil		/* NOTREACHED */
16351.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16361.92Skamil	}
16371.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16381.92Skamil
16391.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16401.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16411.92Skamil
16421.92Skamil	validate_status_signaled(status, sig, 1);
16431.92Skamil
16441.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16451.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16461.92Skamil}
16471.92Skamil
16481.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16491.92SkamilATF_TC(test);								\
16501.92SkamilATF_TC_HEAD(test, tc)							\
16511.92Skamil{									\
16521.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16531.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16541.92Skamil	    "vfork(2)ed child with a masked signal");			\
16551.92Skamil}									\
16561.92Skamil									\
16571.92SkamilATF_TC_BODY(test, tc)							\
16581.92Skamil{									\
16591.92Skamil									\
16601.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16611.92Skamil}
16621.92Skamil
16631.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16641.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16651.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
16661.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
16671.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
16681.92Skamil
16691.92Skamil/// ----------------------------------------------------------------------------
16701.92Skamil
16711.92Skamilstatic void
16721.92Skamiltraceme_vfork_signalignored_crash(int sig)
16731.92Skamil{
16741.92Skamil	pid_t child, wpid;
16751.92Skamil#if defined(TWAIT_HAVE_STATUS)
16761.92Skamil	int status;
16771.92Skamil#endif
16781.92Skamil	struct sigaction sa;
16791.92Skamil
16801.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16811.92Skamil	if (sig == SIGILL)
16821.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16831.92Skamil#endif
16841.92Skamil
16851.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16861.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16871.92Skamil	if (child == 0) {
16881.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16891.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16901.92Skamil
16911.92Skamil		memset(&sa, 0, sizeof(sa));
16921.92Skamil		sa.sa_handler = SIG_IGN;
16931.92Skamil		sigemptyset(&sa.sa_mask);
16941.92Skamil
16951.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
16961.92Skamil
16971.92Skamil		DPRINTF("Before executing a trap\n");
16981.92Skamil		switch (sig) {
16991.92Skamil		case SIGTRAP:
17001.92Skamil			trigger_trap();
17011.92Skamil			break;
17021.92Skamil		case SIGSEGV:
17031.92Skamil			trigger_segv();
17041.92Skamil			break;
17051.92Skamil		case SIGILL:
17061.92Skamil			trigger_ill();
17071.92Skamil			break;
17081.92Skamil		case SIGFPE:
17091.92Skamil			trigger_fpe();
17101.92Skamil			break;
17111.92Skamil		case SIGBUS:
17121.92Skamil			trigger_bus();
17131.92Skamil			break;
17141.92Skamil		default:
17151.92Skamil			/* NOTREACHED */
17161.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17171.92Skamil		}
17181.92Skamil
17191.92Skamil		/* NOTREACHED */
17201.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17211.92Skamil	}
17221.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17231.92Skamil
17241.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17251.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17261.92Skamil
17271.92Skamil	validate_status_signaled(status, sig, 1);
17281.92Skamil
17291.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17301.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17311.92Skamil}
17321.92Skamil
17331.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17341.92SkamilATF_TC(test);								\
17351.92SkamilATF_TC_HEAD(test, tc)							\
17361.92Skamil{									\
17371.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17381.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17391.92Skamil	    "vfork(2)ed child with ignored signal");			\
17401.92Skamil}									\
17411.92Skamil									\
17421.92SkamilATF_TC_BODY(test, tc)							\
17431.92Skamil{									\
17441.92Skamil									\
17451.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17461.92Skamil}
17471.92Skamil
17481.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17491.92Skamil    SIGTRAP)
17501.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17511.92Skamil    SIGSEGV)
17521.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17531.92Skamil    SIGILL)
17541.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17551.92Skamil    SIGFPE)
17561.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17571.92Skamil    SIGBUS)
17581.92Skamil
17591.92Skamil/// ----------------------------------------------------------------------------
17601.92Skamil
17611.43SkamilATF_TC(traceme_vfork_exec);
17621.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
17631.43Skamil{
17641.43Skamil	atf_tc_set_md_var(tc, "descr",
17651.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
17661.43Skamil}
17671.43Skamil
17681.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
17691.43Skamil{
17701.43Skamil	const int sigval = SIGTRAP;
17711.43Skamil	pid_t child, wpid;
17721.43Skamil#if defined(TWAIT_HAVE_STATUS)
17731.43Skamil	int status;
17741.43Skamil#endif
17751.61Skre	struct ptrace_siginfo info;
17761.43Skamil
17771.43Skamil	memset(&info, 0, sizeof(info));
17781.43Skamil
17791.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17801.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17811.43Skamil	if (child == 0) {
17821.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17831.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17841.43Skamil
17851.43Skamil		DPRINTF("Before calling execve(2) from child\n");
17861.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
17871.43Skamil
17881.43Skamil		/* NOTREACHED */
17891.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
17901.43Skamil	}
17911.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17921.43Skamil
17931.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17941.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17951.43Skamil
17961.43Skamil	validate_status_stopped(status, sigval);
17971.43Skamil
17981.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
17991.61Skre	SYSCALL_REQUIRE(
18001.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
18011.43Skamil
18021.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
18031.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
18041.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
18051.43Skamil	    info.psi_siginfo.si_errno);
18061.43Skamil
18071.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
18081.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
18091.43Skamil
18101.43Skamil	DPRINTF("Before resuming the child process where it left off and "
18111.43Skamil	    "without signal to be sent\n");
18121.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18131.43Skamil
18141.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18151.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18161.43Skamil
18171.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18181.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18191.43Skamil}
18201.43Skamil
18211.43Skamil/// ----------------------------------------------------------------------------
18221.43Skamil
18231.1Skamil#if defined(TWAIT_HAVE_PID)
18241.51Skamilstatic void
18251.59Skamilunrelated_tracer_sees_crash(int sig)
18261.59Skamil{
18271.59Skamil	struct msg_fds parent_tracee, parent_tracer;
18281.59Skamil	const int exitval = 10;
18291.59Skamil	pid_t tracee, tracer, wpid;
18301.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
18311.59Skamil#if defined(TWAIT_HAVE_STATUS)
18321.59Skamil	int status;
18331.59Skamil#endif
18341.59Skamil	struct ptrace_siginfo info;
18351.61Skre
18361.71Skamil#ifndef PTRACE_ILLEGAL_ASM
18371.71Skamil	if (sig == SIGILL)
18381.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
18391.71Skamil#endif
18401.71Skamil
18411.59Skamil	memset(&info, 0, sizeof(info));
18421.59Skamil
18431.59Skamil	DPRINTF("Spawn tracee\n");
18441.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
18451.59Skamil	tracee = atf_utils_fork();
18461.59Skamil	if (tracee == 0) {
18471.59Skamil		// Wait for parent to let us crash
18481.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
18491.61Skre
18501.59Skamil		DPRINTF("Before executing a trap\n");
18511.59Skamil		switch (sig) {
18521.59Skamil		case SIGTRAP:
18531.59Skamil			trigger_trap();
18541.59Skamil			break;
18551.59Skamil		case SIGSEGV:
18561.59Skamil			trigger_segv();
18571.59Skamil			break;
18581.59Skamil		case SIGILL:
18591.59Skamil			trigger_ill();
18601.59Skamil			break;
18611.59Skamil		case SIGFPE:
18621.59Skamil			trigger_fpe();
18631.59Skamil			break;
18641.59Skamil		case SIGBUS:
18651.59Skamil			trigger_bus();
18661.59Skamil			break;
18671.59Skamil		default:
18681.59Skamil			/* NOTREACHED */
18691.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
18701.59Skamil		}
18711.59Skamil
18721.59Skamil		/* NOTREACHED */
18731.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
18741.59Skamil	}
18751.59Skamil
18761.59Skamil	DPRINTF("Spawn debugger\n");
18771.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
18781.59Skamil	tracer = atf_utils_fork();
18791.59Skamil	if (tracer == 0) {
18801.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
18811.59Skamil		tracer = atf_utils_fork();
18821.59Skamil		if (tracer != 0)
18831.61Skre			_exit(exitval);
18841.59Skamil
18851.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
18861.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
18871.59Skamil
18881.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
18891.59Skamil		FORKEE_REQUIRE_SUCCESS(
18901.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
18911.59Skamil
18921.59Skamil		forkee_status_stopped(status, SIGSTOP);
18931.59Skamil
18941.59Skamil		/* Resume tracee with PT_CONTINUE */
18951.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
18961.59Skamil
18971.59Skamil		/* Inform parent that tracer has attached to tracee */
18981.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
18991.59Skamil
19001.59Skamil		/* Wait for parent to tell use that tracee should have exited */
19011.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
19021.59Skamil
19031.59Skamil		/* Wait for tracee and assert that it exited */
19041.59Skamil		FORKEE_REQUIRE_SUCCESS(
19051.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
19061.59Skamil
19071.59Skamil		validate_status_stopped(status, sig);
19081.59Skamil
19091.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
19101.61Skre		    "traced process\n");
19111.61Skre		SYSCALL_REQUIRE(
19121.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
19131.59Skamil
19141.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
19151.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
19161.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
19171.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
19181.59Skamil
19191.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
19201.59Skamil		switch (sig) {
19211.59Skamil		case SIGTRAP:
19221.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
19231.59Skamil			break;
19241.59Skamil		case SIGSEGV:
19251.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
19261.59Skamil			break;
19271.71Skamil		case SIGILL:
19281.71Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
19291.71Skamil			break;
19301.59Skamil		case SIGFPE:
19311.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
19321.59Skamil			break;
19331.59Skamil		case SIGBUS:
19341.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
19351.59Skamil			break;
19361.59Skamil		}
19371.59Skamil
19381.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
19391.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
19401.61Skre		TWAIT_REQUIRE_SUCCESS(
19411.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
19421.59Skamil
19431.59Skamil		validate_status_signaled(status, SIGKILL, 0);
19441.59Skamil
19451.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
19461.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
19471.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
19481.59Skamil
19491.71Skamil		/* Inform parent that tracer is exiting normally */
19501.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
19511.71Skamil
19521.59Skamil		DPRINTF("Before exiting of the tracer process\n");
19531.59Skamil		_exit(0 /* collect by initproc */);
19541.59Skamil	}
19551.59Skamil
19561.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
19571.59Skamil	    "calling %s()\n", TWAIT_FNAME);
19581.59Skamil	TWAIT_REQUIRE_SUCCESS(
19591.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
19601.59Skamil
19611.59Skamil	validate_status_exited(status, exitval);
19621.59Skamil
19631.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
19641.59Skamil	    TWAIT_FNAME);
19651.59Skamil	TWAIT_REQUIRE_SUCCESS(
19661.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
19671.59Skamil
19681.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
19691.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
19701.59Skamil
19711.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
19721.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
19731.59Skamil
19741.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
19751.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
19761.59Skamil
19771.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
19781.59Skamil	    TWAIT_FNAME);
19791.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
19801.59Skamil
19811.59Skamil	validate_status_signaled(status, SIGKILL, 0);
19821.59Skamil
19831.71Skamil	DPRINTF("Await normal exit of tracer\n");
19841.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
19851.71Skamil
19861.59Skamil	msg_close(&parent_tracer);
19871.59Skamil	msg_close(&parent_tracee);
19881.59Skamil}
19891.59Skamil
19901.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
19911.61SkreATF_TC(test);								\
19921.61SkreATF_TC_HEAD(test, tc)							\
19931.61Skre{									\
19941.61Skre	atf_tc_set_md_var(tc, "descr",					\
19951.61Skre	    "Assert that an unrelated tracer sees crash signal from the " \
19961.61Skre	    "debuggee");						\
19971.61Skre}									\
19981.61Skre									\
19991.61SkreATF_TC_BODY(test, tc)							\
20001.61Skre{									\
20011.61Skre									\
20021.61Skre	unrelated_tracer_sees_crash(sig);				\
20031.59Skamil}
20041.59Skamil
20051.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
20061.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
20071.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
20081.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
20091.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
20101.59Skamil#endif
20111.59Skamil
20121.59Skamil/// ----------------------------------------------------------------------------
20131.59Skamil
20141.59Skamil#if defined(TWAIT_HAVE_PID)
20151.59Skamilstatic void
20161.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
20171.67Skamil                                             bool stopped)
20181.1Skamil{
20191.51Skamil	/*
20201.51Skamil	 * notimeout - disable timeout in await zombie function
20211.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
20221.67Skamil	 * stopped - attach to a stopped process
20231.51Skamil	 */
20241.1Skamil
20251.1Skamil	struct msg_fds parent_tracee, parent_tracer;
20261.1Skamil	const int exitval_tracee = 5;
20271.1Skamil	const int exitval_tracer = 10;
20281.1Skamil	pid_t tracee, tracer, wpid;
20291.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
20301.1Skamil#if defined(TWAIT_HAVE_STATUS)
20311.1Skamil	int status;
20321.1Skamil#endif
20331.1Skamil
20341.67Skamil	/*
20351.67Skamil	 * Only a subset of options are supported.
20361.67Skamil	 */
20371.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
20381.67Skamil	            (!notimeout && unrelated && !stopped) ||
20391.67Skamil	            (notimeout && !unrelated && !stopped) ||
20401.67Skamil	            (!notimeout && unrelated && stopped));
20411.67Skamil
20421.13Schristos	DPRINTF("Spawn tracee\n");
20431.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
20441.1Skamil	tracee = atf_utils_fork();
20451.1Skamil	if (tracee == 0) {
20461.67Skamil		if (stopped) {
20471.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
20481.67Skamil			raise(SIGSTOP);
20491.67Skamil		}
20501.67Skamil
20511.1Skamil		// Wait for parent to let us exit
20521.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
20531.1Skamil		_exit(exitval_tracee);
20541.1Skamil	}
20551.1Skamil
20561.13Schristos	DPRINTF("Spawn debugger\n");
20571.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
20581.1Skamil	tracer = atf_utils_fork();
20591.1Skamil	if (tracer == 0) {
20601.51Skamil		if(unrelated) {
20611.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
20621.51Skamil			tracer = atf_utils_fork();
20631.51Skamil			if (tracer != 0)
20641.51Skamil				_exit(exitval_tracer);
20651.51Skamil		}
20661.51Skamil
20671.67Skamil		if (stopped) {
20681.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
20691.67Skamil			await_stopped(tracee);
20701.67Skamil		}
20711.67Skamil
20721.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
20731.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
20741.1Skamil
20751.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
20761.1Skamil		FORKEE_REQUIRE_SUCCESS(
20771.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20781.1Skamil
20791.1Skamil		forkee_status_stopped(status, SIGSTOP);
20801.1Skamil
20811.1Skamil		/* Resume tracee with PT_CONTINUE */
20821.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20831.1Skamil
20841.1Skamil		/* Inform parent that tracer has attached to tracee */
20851.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20861.1Skamil
20871.1Skamil		/* Wait for parent to tell use that tracee should have exited */
20881.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20891.1Skamil
20901.1Skamil		/* Wait for tracee and assert that it exited */
20911.1Skamil		FORKEE_REQUIRE_SUCCESS(
20921.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20931.1Skamil
20941.1Skamil		forkee_status_exited(status, exitval_tracee);
20951.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
20961.1Skamil
20971.13Schristos		DPRINTF("Before exiting of the tracer process\n");
20981.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
20991.51Skamil	}
21001.51Skamil
21011.51Skamil	if (unrelated) {
21021.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
21031.51Skamil		    "calling %s()\n", TWAIT_FNAME);
21041.51Skamil		TWAIT_REQUIRE_SUCCESS(
21051.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21061.51Skamil
21071.51Skamil		validate_status_exited(status, exitval_tracer);
21081.51Skamil
21091.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
21101.51Skamil		    TWAIT_FNAME);
21111.51Skamil		TWAIT_REQUIRE_SUCCESS(
21121.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
21131.1Skamil	}
21141.1Skamil
21151.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
21161.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
21171.1Skamil
21181.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
21191.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
21201.1Skamil
21211.13Schristos	DPRINTF("Detect that tracee is zombie\n");
21221.51Skamil	if (notimeout)
21231.26Skamil		await_zombie_raw(tracee, 0);
21241.26Skamil	else
21251.26Skamil		await_zombie(tracee);
21261.1Skamil
21271.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
21281.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
21291.1Skamil	    TWAIT_FNAME);
21301.1Skamil	TWAIT_REQUIRE_SUCCESS(
21311.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
21321.1Skamil
21331.51Skamil	if (unrelated) {
21341.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
21351.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
21361.51Skamil	} else {
21371.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
21381.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
21391.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
21401.59Skamil			"%s()\n", TWAIT_FNAME);
21411.51Skamil
21421.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
21431.59Skamil			"tracee\n");
21441.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
21451.51Skamil		    tracer);
21461.1Skamil
21471.51Skamil		validate_status_exited(status, exitval_tracer);
21481.51Skamil	}
21491.1Skamil
21501.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
21511.1Skamil	    TWAIT_FNAME);
21521.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21531.1Skamil
21541.1Skamil	validate_status_exited(status, exitval_tracee);
21551.1Skamil
21561.1Skamil	msg_close(&parent_tracer);
21571.1Skamil	msg_close(&parent_tracee);
21581.1Skamil}
21591.26Skamil
21601.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
21611.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
21621.51Skamil{
21631.51Skamil	atf_tc_set_md_var(tc, "descr",
21641.51Skamil	    "Assert that tracer sees process termination before the parent");
21651.51Skamil}
21661.51Skamil
21671.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
21681.26Skamil{
21691.26Skamil
21701.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
21711.26Skamil}
21721.26Skamil
21731.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
21741.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
21751.1Skamil{
21761.1Skamil	atf_tc_set_md_var(tc, "descr",
21771.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
21781.51Skamil	    "process and no other error is reported");
21791.1Skamil}
21801.1Skamil
21811.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
21821.1Skamil{
21831.51Skamil	time_t start, end;
21841.51Skamil	double diff;
21851.51Skamil	unsigned long N = 0;
21861.1Skamil
21871.51Skamil	/*
21881.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
21891.51Skamil	 * This test body isn't specific to this race, however it's just good
21901.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
21911.51Skamil	 */
21921.1Skamil
21931.51Skamil	start = time(NULL);
21941.51Skamil	while (true) {
21951.51Skamil		DPRINTF("Step: %lu\n", N);
21961.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
21971.67Skamil		                                             false);
21981.51Skamil		end = time(NULL);
21991.51Skamil		diff = difftime(end, start);
22001.51Skamil		if (diff >= 5.0)
22011.51Skamil			break;
22021.51Skamil		++N;
22031.1Skamil	}
22041.51Skamil	DPRINTF("Iterations: %lu\n", N);
22051.51Skamil}
22061.1Skamil
22071.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
22081.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
22091.51Skamil{
22101.51Skamil	atf_tc_set_md_var(tc, "descr",
22111.51Skamil	    "Assert that tracer sees process termination before the parent");
22121.51Skamil}
22131.1Skamil
22141.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
22151.51Skamil{
22161.1Skamil
22171.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
22181.67Skamil}
22191.67Skamil
22201.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
22211.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
22221.67Skamil{
22231.67Skamil	atf_tc_set_md_var(tc, "descr",
22241.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
22251.67Skamil}
22261.67Skamil
22271.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
22281.67Skamil{
22291.67Skamil
22301.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
22311.1Skamil}
22321.1Skamil#endif
22331.1Skamil
22341.51Skamil/// ----------------------------------------------------------------------------
22351.51Skamil
22361.66Skamilstatic void
22371.66Skamilparent_attach_to_its_child(bool stopped)
22381.1Skamil{
22391.1Skamil	struct msg_fds parent_tracee;
22401.1Skamil	const int exitval_tracee = 5;
22411.1Skamil	pid_t tracee, wpid;
22421.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
22431.1Skamil#if defined(TWAIT_HAVE_STATUS)
22441.1Skamil	int status;
22451.1Skamil#endif
22461.1Skamil
22471.13Schristos	DPRINTF("Spawn tracee\n");
22481.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
22491.1Skamil	tracee = atf_utils_fork();
22501.1Skamil	if (tracee == 0) {
22511.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
22521.13Schristos		DPRINTF("Parent should now attach to tracee\n");
22531.1Skamil
22541.66Skamil		if (stopped) {
22551.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
22561.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
22571.66Skamil		}
22581.66Skamil
22591.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
22601.1Skamil		/* Wait for message from the parent */
22611.1Skamil		_exit(exitval_tracee);
22621.1Skamil	}
22631.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
22641.57Skamil
22651.66Skamil	if (stopped) {
22661.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
22671.66Skamil		await_stopped(tracee);
22681.66Skamil	}
22691.66Skamil
22701.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
22711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
22721.1Skamil
22731.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
22741.1Skamil	    TWAIT_FNAME);
22751.1Skamil	TWAIT_REQUIRE_SUCCESS(
22761.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22771.1Skamil
22781.1Skamil	validate_status_stopped(status, SIGSTOP);
22791.1Skamil
22801.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
22811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
22821.1Skamil
22831.13Schristos	DPRINTF("Let the tracee exit now\n");
22841.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
22851.1Skamil
22861.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
22871.1Skamil	TWAIT_REQUIRE_SUCCESS(
22881.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
22891.1Skamil
22901.1Skamil	validate_status_exited(status, exitval_tracee);
22911.1Skamil
22921.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
22931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
22941.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
22951.1Skamil
22961.1Skamil	msg_close(&parent_tracee);
22971.1Skamil}
22981.1Skamil
22991.66SkamilATF_TC(parent_attach_to_its_child);
23001.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
23011.66Skamil{
23021.66Skamil	atf_tc_set_md_var(tc, "descr",
23031.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
23041.66Skamil}
23051.66Skamil
23061.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
23071.66Skamil{
23081.66Skamil
23091.66Skamil	parent_attach_to_its_child(false);
23101.66Skamil}
23111.66Skamil
23121.66SkamilATF_TC(parent_attach_to_its_stopped_child);
23131.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
23141.66Skamil{
23151.66Skamil	atf_tc_set_md_var(tc, "descr",
23161.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
23171.66Skamil}
23181.66Skamil
23191.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
23201.66Skamil{
23211.66Skamil
23221.66Skamil	parent_attach_to_its_child(true);
23231.66Skamil}
23241.66Skamil
23251.51Skamil/// ----------------------------------------------------------------------------
23261.51Skamil
23271.65Skamilstatic void
23281.65Skamilchild_attach_to_its_parent(bool stopped)
23291.1Skamil{
23301.1Skamil	struct msg_fds parent_tracee;
23311.1Skamil	const int exitval_tracer = 5;
23321.1Skamil	pid_t tracer, wpid;
23331.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
23341.1Skamil#if defined(TWAIT_HAVE_STATUS)
23351.1Skamil	int status;
23361.1Skamil#endif
23371.1Skamil
23381.13Schristos	DPRINTF("Spawn tracer\n");
23391.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
23401.1Skamil	tracer = atf_utils_fork();
23411.1Skamil	if (tracer == 0) {
23421.1Skamil		/* Wait for message from the parent */
23431.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
23441.1Skamil
23451.65Skamil		if (stopped) {
23461.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
23471.65Skamil			        getppid());
23481.65Skamil			await_stopped(getppid());
23491.65Skamil		}
23501.65Skamil
23511.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
23521.1Skamil		    getppid());
23531.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
23541.1Skamil
23551.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
23561.1Skamil		    TWAIT_FNAME);
23571.1Skamil		FORKEE_REQUIRE_SUCCESS(
23581.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
23591.1Skamil
23601.1Skamil		forkee_status_stopped(status, SIGSTOP);
23611.1Skamil
23621.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
23631.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
23641.1Skamil		    != -1);
23651.1Skamil
23661.1Skamil		/* Tell parent we are ready */
23671.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
23681.1Skamil
23691.1Skamil		_exit(exitval_tracer);
23701.1Skamil	}
23711.1Skamil
23721.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
23731.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
23741.65Skamil
23751.65Skamil	if (stopped) {
23761.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
23771.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
23781.65Skamil	}
23791.65Skamil
23801.13Schristos	DPRINTF("Allow the tracer to exit now\n");
23811.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
23821.1Skamil
23831.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
23841.1Skamil	TWAIT_REQUIRE_SUCCESS(
23851.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23861.1Skamil
23871.1Skamil	validate_status_exited(status, exitval_tracer);
23881.1Skamil
23891.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
23901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
23911.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
23921.1Skamil
23931.1Skamil	msg_close(&parent_tracee);
23941.1Skamil}
23951.1Skamil
23961.65SkamilATF_TC(child_attach_to_its_parent);
23971.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
23981.65Skamil{
23991.65Skamil	atf_tc_set_md_var(tc, "descr",
24001.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
24011.65Skamil}
24021.65Skamil
24031.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
24041.65Skamil{
24051.65Skamil
24061.65Skamil	child_attach_to_its_parent(false);
24071.65Skamil}
24081.65Skamil
24091.65SkamilATF_TC(child_attach_to_its_stopped_parent);
24101.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
24111.65Skamil{
24121.65Skamil	atf_tc_set_md_var(tc, "descr",
24131.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
24141.65Skamil}
24151.65Skamil
24161.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
24171.65Skamil{
24181.65Skamil	/*
24191.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
24201.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
24211.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
24221.65Skamil	 *
24231.65Skamil	 * As a workaround spawn this test as a subprocess.
24241.65Skamil	 */
24251.65Skamil
24261.65Skamil	const int exitval = 15;
24271.65Skamil	pid_t child, wpid;
24281.65Skamil#if defined(TWAIT_HAVE_STATUS)
24291.65Skamil	int status;
24301.65Skamil#endif
24311.65Skamil
24321.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
24331.65Skamil	if (child == 0) {
24341.65Skamil		child_attach_to_its_parent(true);
24351.65Skamil		_exit(exitval);
24361.65Skamil	} else {
24371.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24381.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24391.65Skamil
24401.65Skamil		validate_status_exited(status, exitval);
24411.65Skamil
24421.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
24431.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24441.65Skamil	}
24451.65Skamil}
24461.65Skamil
24471.51Skamil/// ----------------------------------------------------------------------------
24481.51Skamil
24491.1Skamil#if defined(TWAIT_HAVE_PID)
24501.1Skamil
24511.51Skamilenum tracee_sees_its_original_parent_type {
24521.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
24531.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
24541.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
24551.51Skamil};
24561.51Skamil
24571.51Skamilstatic void
24581.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
24591.1Skamil{
24601.1Skamil	struct msg_fds parent_tracer, parent_tracee;
24611.1Skamil	const int exitval_tracee = 5;
24621.1Skamil	const int exitval_tracer = 10;
24631.1Skamil	pid_t parent, tracee, tracer, wpid;
24641.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
24651.1Skamil#if defined(TWAIT_HAVE_STATUS)
24661.1Skamil	int status;
24671.1Skamil#endif
24681.51Skamil	/* sysctl(3) - kinfo_proc2 */
24691.51Skamil	int name[CTL_MAXNAME];
24701.51Skamil	struct kinfo_proc2 kp;
24711.51Skamil	size_t len = sizeof(kp);
24721.51Skamil	unsigned int namelen;
24731.51Skamil
24741.51Skamil	/* procfs - status  */
24751.51Skamil	FILE *fp;
24761.51Skamil	struct stat st;
24771.51Skamil	const char *fname = "/proc/curproc/status";
24781.51Skamil	char s_executable[MAXPATHLEN];
24791.51Skamil	int s_pid, s_ppid;
24801.51Skamil	int rv;
24811.51Skamil
24821.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
24831.61Skre		SYSCALL_REQUIRE(
24841.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
24851.61Skre		if (rv != 0)
24861.51Skamil			atf_tc_skip("/proc/curproc/status not found");
24871.51Skamil	}
24881.1Skamil
24891.13Schristos	DPRINTF("Spawn tracee\n");
24901.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
24911.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
24921.1Skamil	tracee = atf_utils_fork();
24931.1Skamil	if (tracee == 0) {
24941.1Skamil		parent = getppid();
24951.1Skamil
24961.1Skamil		/* Emit message to the parent */
24971.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
24981.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
24991.1Skamil
25001.51Skamil		switch (type) {
25011.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
25021.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
25031.51Skamil			break;
25041.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
25051.51Skamil			namelen = 0;
25061.51Skamil			name[namelen++] = CTL_KERN;
25071.51Skamil			name[namelen++] = KERN_PROC2;
25081.51Skamil			name[namelen++] = KERN_PROC_PID;
25091.51Skamil			name[namelen++] = getpid();
25101.51Skamil			name[namelen++] = len;
25111.51Skamil			name[namelen++] = 1;
25121.51Skamil
25131.61Skre			FORKEE_ASSERT_EQ(
25141.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
25151.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
25161.51Skamil			break;
25171.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
25181.51Skamil			/*
25191.51Skamil			 * Format:
25201.51Skamil			 *  EXECUTABLE PID PPID ...
25211.51Skamil			 */
25221.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
25231.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
25241.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
25251.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
25261.51Skamil			break;
25271.51Skamil		}
25281.1Skamil
25291.1Skamil		_exit(exitval_tracee);
25301.1Skamil	}
25311.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
25321.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
25331.1Skamil
25341.13Schristos	DPRINTF("Spawn debugger\n");
25351.1Skamil	tracer = atf_utils_fork();
25361.1Skamil	if (tracer == 0) {
25371.1Skamil		/* No IPC to communicate with the child */
25381.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
25391.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25401.1Skamil
25411.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
25421.1Skamil		FORKEE_REQUIRE_SUCCESS(
25431.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25441.1Skamil
25451.1Skamil		forkee_status_stopped(status, SIGSTOP);
25461.1Skamil
25471.1Skamil		/* Resume tracee with PT_CONTINUE */
25481.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25491.1Skamil
25501.1Skamil		/* Inform parent that tracer has attached to tracee */
25511.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
25521.1Skamil
25531.1Skamil		/* Wait for parent to tell use that tracee should have exited */
25541.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
25551.1Skamil
25561.1Skamil		/* Wait for tracee and assert that it exited */
25571.1Skamil		FORKEE_REQUIRE_SUCCESS(
25581.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25591.1Skamil
25601.1Skamil		forkee_status_exited(status, exitval_tracee);
25611.1Skamil
25621.13Schristos		DPRINTF("Before exiting of the tracer process\n");
25631.1Skamil		_exit(exitval_tracer);
25641.1Skamil	}
25651.1Skamil
25661.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
25671.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
25681.1Skamil
25691.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
25701.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
25711.1Skamil
25721.13Schristos	DPRINTF("Detect that tracee is zombie\n");
25731.1Skamil	await_zombie(tracee);
25741.1Skamil
25751.13Schristos	DPRINTF("Assert that there is no status about tracee - "
25761.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
25771.1Skamil	TWAIT_REQUIRE_SUCCESS(
25781.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
25791.1Skamil
25801.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
25811.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
25821.1Skamil
25831.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
25841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
25851.1Skamil	    tracer);
25861.1Skamil
25871.1Skamil	validate_status_exited(status, exitval_tracer);
25881.1Skamil
25891.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
25901.1Skamil	    TWAIT_FNAME);
25911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
25921.1Skamil	    tracee);
25931.1Skamil
25941.1Skamil	validate_status_exited(status, exitval_tracee);
25951.1Skamil
25961.1Skamil	msg_close(&parent_tracer);
25971.1Skamil	msg_close(&parent_tracee);
25981.1Skamil}
25991.1Skamil
26001.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
26011.61SkreATF_TC(test);								\
26021.61SkreATF_TC_HEAD(test, tc)							\
26031.61Skre{									\
26041.61Skre	atf_tc_set_md_var(tc, "descr",					\
26051.61Skre	    "Assert that tracee sees its original parent when being traced " \
26061.61Skre	    "(check " descr ")");					\
26071.61Skre}									\
26081.61Skre									\
26091.61SkreATF_TC_BODY(test, tc)							\
26101.61Skre{									\
26111.61Skre									\
26121.61Skre	tracee_sees_its_original_parent(type);				\
26131.1Skamil}
26141.1Skamil
26151.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
26161.51Skamil	tracee_sees_its_original_parent_getppid,
26171.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
26181.51Skamil	"getppid(2)");
26191.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
26201.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
26211.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
26221.51Skamil	"sysctl(3) and kinfo_proc2");
26231.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
26241.51Skamil	tracee_sees_its_original_parent_procfs_status,
26251.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
26261.51Skamil	"the status file in procfs");
26271.1Skamil#endif
26281.1Skamil
26291.51Skamil/// ----------------------------------------------------------------------------
26301.1Skamil
26311.53Skamilstatic void
26321.53Skamileventmask_preserved(int event)
26331.1Skamil{
26341.1Skamil	const int exitval = 5;
26351.1Skamil	const int sigval = SIGSTOP;
26361.1Skamil	pid_t child, wpid;
26371.1Skamil#if defined(TWAIT_HAVE_STATUS)
26381.1Skamil	int status;
26391.1Skamil#endif
26401.1Skamil	ptrace_event_t set_event, get_event;
26411.1Skamil	const int len = sizeof(ptrace_event_t);
26421.1Skamil
26431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26451.1Skamil	if (child == 0) {
26461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26481.1Skamil
26491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26511.1Skamil
26521.13Schristos		DPRINTF("Before exiting of the child process\n");
26531.1Skamil		_exit(exitval);
26541.1Skamil	}
26551.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26561.1Skamil
26571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26591.1Skamil
26601.1Skamil	validate_status_stopped(status, sigval);
26611.1Skamil
26621.53Skamil	set_event.pe_set_event = event;
26631.61Skre	SYSCALL_REQUIRE(
26641.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
26651.61Skre	SYSCALL_REQUIRE(
26661.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
26671.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
26681.1Skamil
26691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26701.1Skamil	    "without signal to be sent\n");
26711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26721.1Skamil
26731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26751.1Skamil
26761.1Skamil	validate_status_exited(status, exitval);
26771.1Skamil
26781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26801.1Skamil}
26811.1Skamil
26821.61Skre#define EVENTMASK_PRESERVED(test, event)				\
26831.61SkreATF_TC(test);								\
26841.61SkreATF_TC_HEAD(test, tc)							\
26851.61Skre{									\
26861.61Skre	atf_tc_set_md_var(tc, "descr",					\
26871.61Skre	    "Verify that eventmask " #event " is preserved");		\
26881.61Skre}									\
26891.61Skre									\
26901.61SkreATF_TC_BODY(test, tc)							\
26911.61Skre{									\
26921.61Skre									\
26931.61Skre	eventmask_preserved(event);					\
26941.1Skamil}
26951.1Skamil
26961.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
26971.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
26981.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
26991.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
27001.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
27011.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
27021.1Skamil
27031.53Skamil/// ----------------------------------------------------------------------------
27041.1Skamil
27051.28Skamilstatic void
27061.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
27071.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
27081.1Skamil{
27091.1Skamil	const int exitval = 5;
27101.1Skamil	const int exitval2 = 15;
27111.1Skamil	const int sigval = SIGSTOP;
27121.31Skamil	pid_t child, child2 = 0, wpid;
27131.1Skamil#if defined(TWAIT_HAVE_STATUS)
27141.1Skamil	int status;
27151.1Skamil#endif
27161.1Skamil	ptrace_state_t state;
27171.1Skamil	const int slen = sizeof(state);
27181.1Skamil	ptrace_event_t event;
27191.1Skamil	const int elen = sizeof(event);
27201.1Skamil
27211.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27221.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27231.1Skamil	if (child == 0) {
27241.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27251.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27261.1Skamil
27271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27291.1Skamil
27301.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
27311.1Skamil
27321.1Skamil		if (child2 == 0)
27331.1Skamil			_exit(exitval2);
27341.1Skamil
27351.1Skamil		FORKEE_REQUIRE_SUCCESS
27361.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
27371.1Skamil
27381.1Skamil		forkee_status_exited(status, exitval2);
27391.1Skamil
27401.13Schristos		DPRINTF("Before exiting of the child process\n");
27411.1Skamil		_exit(exitval);
27421.1Skamil	}
27431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27441.1Skamil
27451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27471.1Skamil
27481.1Skamil	validate_status_stopped(status, sigval);
27491.1Skamil
27501.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
27511.61Skre	    trackfork ? "|PTRACE_FORK" : "",
27521.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
27531.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
27541.30Skamil	event.pe_set_event = 0;
27551.30Skamil	if (trackfork)
27561.30Skamil		event.pe_set_event |= PTRACE_FORK;
27571.30Skamil	if (trackvfork)
27581.30Skamil		event.pe_set_event |= PTRACE_VFORK;
27591.30Skamil	if (trackvforkdone)
27601.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
27611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
27621.1Skamil
27631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27641.1Skamil	    "without signal to be sent\n");
27651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27661.1Skamil
27671.29Skamil#if defined(TWAIT_HAVE_PID)
27681.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
27691.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
27701.61Skre		    child);
27711.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
27721.61Skre		    child);
27731.1Skamil
27741.29Skamil		validate_status_stopped(status, SIGTRAP);
27751.1Skamil
27761.61Skre		SYSCALL_REQUIRE(
27771.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
27781.31Skamil		if (trackfork && fn == fork) {
27791.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
27801.30Skamil			       PTRACE_FORK);
27811.30Skamil		}
27821.31Skamil		if (trackvfork && fn == vfork) {
27831.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
27841.30Skamil			       PTRACE_VFORK);
27851.30Skamil		}
27861.29Skamil
27871.29Skamil		child2 = state.pe_other_pid;
27881.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
27891.29Skamil
27901.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
27911.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
27921.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
27931.29Skamil		    child2);
27941.1Skamil
27951.29Skamil		validate_status_stopped(status, SIGTRAP);
27961.1Skamil
27971.61Skre		SYSCALL_REQUIRE(
27981.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
27991.31Skamil		if (trackfork && fn == fork) {
28001.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
28011.30Skamil			       PTRACE_FORK);
28021.30Skamil		}
28031.31Skamil		if (trackvfork && fn == vfork) {
28041.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
28051.30Skamil			       PTRACE_VFORK);
28061.30Skamil		}
28071.30Skamil
28081.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
28091.29Skamil
28101.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
28111.29Skamil		    "and without signal to be sent\n");
28121.61Skre		SYSCALL_REQUIRE(
28131.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
28141.29Skamil
28151.29Skamil		DPRINTF("Before resuming the child process where it left off "
28161.61Skre		    "and without signal to be sent\n");
28171.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28181.30Skamil	}
28191.30Skamil#endif
28201.30Skamil
28211.31Skamil	if (trackvforkdone && fn == vfork) {
28221.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
28231.61Skre		    child);
28241.61Skre		TWAIT_REQUIRE_SUCCESS(
28251.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
28261.30Skamil
28271.30Skamil		validate_status_stopped(status, SIGTRAP);
28281.30Skamil
28291.61Skre		SYSCALL_REQUIRE(
28301.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
28311.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
28321.30Skamil
28331.30Skamil		child2 = state.pe_other_pid;
28341.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
28351.61Skre		    child2);
28361.30Skamil
28371.30Skamil		DPRINTF("Before resuming the child process where it left off "
28381.61Skre		    "and without signal to be sent\n");
28391.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28401.30Skamil	}
28411.29Skamil
28421.30Skamil#if defined(TWAIT_HAVE_PID)
28431.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
28441.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
28451.61Skre		    "\n", TWAIT_FNAME);
28461.61Skre		TWAIT_REQUIRE_SUCCESS(
28471.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
28481.29Skamil
28491.29Skamil		validate_status_exited(status, exitval2);
28501.29Skamil
28511.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
28521.61Skre		    "process\n", TWAIT_FNAME);
28531.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
28541.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
28551.29Skamil	}
28561.29Skamil#endif
28571.1Skamil
28581.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
28591.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
28601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28611.1Skamil
28621.1Skamil	validate_status_stopped(status, SIGCHLD);
28631.1Skamil
28641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28651.1Skamil	    "without signal to be sent\n");
28661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28671.1Skamil
28681.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
28691.1Skamil	    TWAIT_FNAME);
28701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28711.1Skamil
28721.1Skamil	validate_status_exited(status, exitval);
28731.1Skamil
28741.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
28751.1Skamil	    TWAIT_FNAME);
28761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28771.1Skamil}
28781.28Skamil
28791.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
28801.61SkreATF_TC(name);								\
28811.61SkreATF_TC_HEAD(name, tc)							\
28821.61Skre{									\
28831.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
28841.61Skre}									\
28851.61Skre									\
28861.61SkreATF_TC_BODY(name, tc)							\
28871.61Skre{									\
28881.61Skre									\
28891.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
28901.32Skamil}
28911.32Skamil
28921.32Skamil#define F false
28931.32Skamil#define T true
28941.32Skamil
28951.32Skamil#define F_IF__0(x)
28961.32Skamil#define F_IF__1(x) x
28971.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
28981.32Skamil#define F_IF_(x,y) F_IF__(x,y)
28991.32Skamil#define F_IF(x,y) F_IF_(x,y)
29001.32Skamil
29011.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
29021.61Skre	"Verify " #function "(2) called with 0"				\
29031.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
29041.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
29051.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
29061.61Skre	" in EVENT_MASK."						\
29071.61Skre	F_IF(dchildbit," Detach child in this test.")			\
29081.61Skre	F_IF(dparentbit," Detach parent in this test.")
29091.1Skamil
29101.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
29111.31Skamil#if defined(TWAIT_HAVE_PID)
29121.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
29131.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
29141.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
29151.31Skamil#endif
29161.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
29171.31Skamil#if defined(TWAIT_HAVE_PID)
29181.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
29191.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
29201.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
29211.31Skamil#endif
29221.1Skamil
29231.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
29241.31Skamil#if defined(TWAIT_HAVE_PID)
29251.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
29261.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
29271.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
29281.31Skamil#endif
29291.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
29301.31Skamil#if defined(TWAIT_HAVE_PID)
29311.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
29321.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
29331.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
29341.31Skamil#endif
29351.31Skamil
29361.54Skamil/// ----------------------------------------------------------------------------
29371.31Skamil
29381.54Skamilenum bytes_transfer_type {
29391.54Skamil	BYTES_TRANSFER_DATA,
29401.54Skamil	BYTES_TRANSFER_DATAIO,
29411.54Skamil	BYTES_TRANSFER_TEXT,
29421.54Skamil	BYTES_TRANSFER_TEXTIO,
29431.54Skamil	BYTES_TRANSFER_AUXV
29441.54Skamil};
29451.31Skamil
29461.54Skamilstatic int __used
29471.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
29481.54Skamil{
29491.54Skamil	int e, f, g, h;
29501.1Skamil
29511.54Skamil	a *= 4;
29521.54Skamil	b += 3;
29531.54Skamil	c -= 2;
29541.54Skamil	d /= 1;
29551.1Skamil
29561.54Skamil	e = strtol("10", NULL, 10);
29571.54Skamil	f = strtol("20", NULL, 10);
29581.54Skamil	g = strtol("30", NULL, 10);
29591.54Skamil	h = strtol("40", NULL, 10);
29601.1Skamil
29611.54Skamil	return (a + b * c - d) + (e * f - g / h);
29621.1Skamil}
29631.1Skamil
29641.54Skamilstatic void
29651.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
29661.1Skamil{
29671.1Skamil	const int exitval = 5;
29681.1Skamil	const int sigval = SIGSTOP;
29691.1Skamil	pid_t child, wpid;
29701.54Skamil	bool skip = false;
29711.1Skamil
29721.54Skamil	int lookup_me = 0;
29731.54Skamil	uint8_t lookup_me8 = 0;
29741.54Skamil	uint16_t lookup_me16 = 0;
29751.54Skamil	uint32_t lookup_me32 = 0;
29761.54Skamil	uint64_t lookup_me64 = 0;
29771.1Skamil
29781.54Skamil	int magic = 0x13579246;
29791.54Skamil	uint8_t magic8 = 0xab;
29801.54Skamil	uint16_t magic16 = 0x1234;
29811.54Skamil	uint32_t magic32 = 0x98765432;
29821.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
29831.1Skamil
29841.54Skamil	struct ptrace_io_desc io;
29851.1Skamil#if defined(TWAIT_HAVE_STATUS)
29861.1Skamil	int status;
29871.1Skamil#endif
29881.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
29891.60Skre	AuxInfo ai[513], *aip;
29901.55Schristos
29911.55Schristos	ATF_REQUIRE(size < sizeof(ai));
29921.1Skamil
29931.54Skamil	/* Prepare variables for .TEXT transfers */
29941.54Skamil	switch (type) {
29951.54Skamil	case BYTES_TRANSFER_TEXT:
29961.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
29971.54Skamil		break;
29981.54Skamil	case BYTES_TRANSFER_TEXTIO:
29991.54Skamil		switch (size) {
30001.54Skamil		case 8:
30011.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
30021.54Skamil			break;
30031.54Skamil		case 16:
30041.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
30051.54Skamil			break;
30061.54Skamil		case 32:
30071.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
30081.54Skamil			break;
30091.54Skamil		case 64:
30101.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
30111.54Skamil			break;
30121.54Skamil		}
30131.54Skamil		break;
30141.54Skamil	default:
30151.54Skamil		break;
30161.54Skamil	}
30171.1Skamil
30181.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
30191.54Skamil	switch (type) {
30201.54Skamil	case BYTES_TRANSFER_TEXTIO:
30211.54Skamil	case BYTES_TRANSFER_DATAIO:
30221.54Skamil		io.piod_op = operation;
30231.54Skamil		switch (size) {
30241.54Skamil		case 8:
30251.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
30261.54Skamil			               (void *)bytes_transfer_dummy :
30271.54Skamil			               &lookup_me8;
30281.54Skamil			io.piod_addr = &lookup_me8;
30291.54Skamil			io.piod_len = sizeof(lookup_me8);
30301.54Skamil			break;
30311.54Skamil		case 16:
30321.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
30331.54Skamil			               (void *)bytes_transfer_dummy :
30341.54Skamil			               &lookup_me16;
30351.54Skamil			io.piod_addr = &lookup_me16;
30361.54Skamil			io.piod_len = sizeof(lookup_me16);
30371.54Skamil			break;
30381.54Skamil		case 32:
30391.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
30401.54Skamil			               (void *)bytes_transfer_dummy :
30411.54Skamil			               &lookup_me32;
30421.54Skamil			io.piod_addr = &lookup_me32;
30431.54Skamil			io.piod_len = sizeof(lookup_me32);
30441.54Skamil			break;
30451.54Skamil		case 64:
30461.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
30471.54Skamil			               (void *)bytes_transfer_dummy :
30481.54Skamil			               &lookup_me64;
30491.54Skamil			io.piod_addr = &lookup_me64;
30501.54Skamil			io.piod_len = sizeof(lookup_me64);
30511.54Skamil			break;
30521.54Skamil		default:
30531.54Skamil			break;
30541.54Skamil		}
30551.54Skamil		break;
30561.54Skamil	case BYTES_TRANSFER_AUXV:
30571.54Skamil		io.piod_op = operation;
30581.54Skamil		io.piod_offs = 0;
30591.54Skamil		io.piod_addr = ai;
30601.54Skamil		io.piod_len = size;
30611.54Skamil		break;
30621.54Skamil	default:
30631.54Skamil		break;
30641.1Skamil	}
30651.1Skamil
30661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30681.1Skamil	if (child == 0) {
30691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30711.1Skamil
30721.54Skamil		switch (type) {
30731.54Skamil		case BYTES_TRANSFER_DATA:
30741.54Skamil			switch (operation) {
30751.54Skamil			case PT_READ_D:
30761.54Skamil			case PT_READ_I:
30771.54Skamil				lookup_me = magic;
30781.54Skamil				break;
30791.54Skamil			default:
30801.54Skamil				break;
30811.54Skamil			}
30821.54Skamil			break;
30831.54Skamil		case BYTES_TRANSFER_DATAIO:
30841.54Skamil			switch (operation) {
30851.54Skamil			case PIOD_READ_D:
30861.54Skamil			case PIOD_READ_I:
30871.54Skamil				switch (size) {
30881.54Skamil				case 8:
30891.54Skamil					lookup_me8 = magic8;
30901.54Skamil					break;
30911.54Skamil				case 16:
30921.54Skamil					lookup_me16 = magic16;
30931.54Skamil					break;
30941.54Skamil				case 32:
30951.54Skamil					lookup_me32 = magic32;
30961.54Skamil					break;
30971.54Skamil				case 64:
30981.54Skamil					lookup_me64 = magic64;
30991.54Skamil					break;
31001.54Skamil				default:
31011.54Skamil					break;
31021.54Skamil				}
31031.54Skamil				break;
31041.54Skamil			default:
31051.54Skamil				break;
31061.54Skamil			}
31071.54Skamil		default:
31081.54Skamil			break;
31091.54Skamil		}
31101.54Skamil
31111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31131.1Skamil
31141.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
31151.54Skamil		switch (type) {
31161.54Skamil		case BYTES_TRANSFER_DATA:
31171.54Skamil			switch (operation) {
31181.54Skamil			case PT_WRITE_D:
31191.54Skamil			case PT_WRITE_I:
31201.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
31211.54Skamil				break;
31221.54Skamil			default:
31231.54Skamil				break;
31241.54Skamil			}
31251.54Skamil			break;
31261.54Skamil		case BYTES_TRANSFER_DATAIO:
31271.54Skamil			switch (operation) {
31281.54Skamil			case PIOD_WRITE_D:
31291.54Skamil			case PIOD_WRITE_I:
31301.54Skamil				switch (size) {
31311.54Skamil				case 8:
31321.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
31331.54Skamil					break;
31341.54Skamil				case 16:
31351.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
31361.54Skamil					break;
31371.54Skamil				case 32:
31381.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
31391.54Skamil					break;
31401.54Skamil				case 64:
31411.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
31421.54Skamil					break;
31431.54Skamil				default:
31441.54Skamil					break;
31451.54Skamil				}
31461.54Skamil				break;
31471.54Skamil			default:
31481.54Skamil				break;
31491.54Skamil			}
31501.54Skamil			break;
31511.54Skamil		case BYTES_TRANSFER_TEXT:
31521.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
31531.54Skamil			                     sizeof(magic)) == 0);
31541.54Skamil			break;
31551.54Skamil		case BYTES_TRANSFER_TEXTIO:
31561.54Skamil			switch (size) {
31571.54Skamil			case 8:
31581.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
31591.54Skamil				                     bytes_transfer_dummy,
31601.54Skamil				                     sizeof(magic8)) == 0);
31611.54Skamil				break;
31621.54Skamil			case 16:
31631.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
31641.54Skamil				                     bytes_transfer_dummy,
31651.54Skamil				                     sizeof(magic16)) == 0);
31661.54Skamil				break;
31671.54Skamil			case 32:
31681.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
31691.54Skamil				                     bytes_transfer_dummy,
31701.54Skamil				                     sizeof(magic32)) == 0);
31711.54Skamil				break;
31721.54Skamil			case 64:
31731.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
31741.54Skamil				                     bytes_transfer_dummy,
31751.54Skamil				                     sizeof(magic64)) == 0);
31761.54Skamil				break;
31771.54Skamil			}
31781.54Skamil			break;
31791.54Skamil		default:
31801.54Skamil			break;
31811.54Skamil		}
31821.54Skamil
31831.13Schristos		DPRINTF("Before exiting of the child process\n");
31841.1Skamil		_exit(exitval);
31851.1Skamil	}
31861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31871.1Skamil
31881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31901.1Skamil
31911.1Skamil	validate_status_stopped(status, sigval);
31921.1Skamil
31931.54Skamil	/* Check PaX MPROTECT */
31941.54Skamil	if (!can_we_write_to_text(child)) {
31951.54Skamil		switch (type) {
31961.54Skamil		case BYTES_TRANSFER_TEXTIO:
31971.54Skamil			switch (operation) {
31981.54Skamil			case PIOD_WRITE_D:
31991.54Skamil			case PIOD_WRITE_I:
32001.54Skamil				skip = true;
32011.54Skamil				break;
32021.54Skamil			default:
32031.54Skamil				break;
32041.54Skamil			}
32051.54Skamil			break;
32061.54Skamil		case BYTES_TRANSFER_TEXT:
32071.54Skamil			switch (operation) {
32081.54Skamil			case PT_WRITE_D:
32091.54Skamil			case PT_WRITE_I:
32101.54Skamil				skip = true;
32111.54Skamil				break;
32121.54Skamil			default:
32131.54Skamil				break;
32141.54Skamil			}
32151.54Skamil			break;
32161.54Skamil		default:
32171.54Skamil			break;
32181.54Skamil		}
32191.54Skamil	}
32201.1Skamil
32211.54Skamil	/* Bailout cleanly killing the child process */
32221.54Skamil	if (skip) {
32231.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
32241.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32251.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
32261.54Skamil		                      child);
32271.1Skamil
32281.54Skamil		validate_status_signaled(status, SIGKILL, 0);
32291.1Skamil
32301.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
32311.54Skamil	}
32321.1Skamil
32331.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
32341.54Skamil	       "parent=%d\n", child, getpid());
32351.1Skamil
32361.54Skamil	switch (type) {
32371.54Skamil	case BYTES_TRANSFER_TEXTIO:
32381.54Skamil	case BYTES_TRANSFER_DATAIO:
32391.54Skamil	case BYTES_TRANSFER_AUXV:
32401.54Skamil		switch (operation) {
32411.54Skamil		case PIOD_WRITE_D:
32421.54Skamil		case PIOD_WRITE_I:
32431.54Skamil			switch (size) {
32441.54Skamil			case 8:
32451.54Skamil				lookup_me8 = magic8;
32461.54Skamil				break;
32471.54Skamil			case 16:
32481.54Skamil				lookup_me16 = magic16;
32491.54Skamil				break;
32501.54Skamil			case 32:
32511.54Skamil				lookup_me32 = magic32;
32521.54Skamil				break;
32531.54Skamil			case 64:
32541.54Skamil				lookup_me64 = magic64;
32551.54Skamil				break;
32561.54Skamil			default:
32571.54Skamil				break;
32581.54Skamil			}
32591.54Skamil			break;
32601.54Skamil		default:
32611.54Skamil			break;
32621.54Skamil		}
32631.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
32641.54Skamil		switch (operation) {
32651.54Skamil		case PIOD_READ_D:
32661.54Skamil		case PIOD_READ_I:
32671.54Skamil			switch (size) {
32681.54Skamil			case 8:
32691.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
32701.54Skamil				break;
32711.54Skamil			case 16:
32721.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
32731.54Skamil				break;
32741.54Skamil			case 32:
32751.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
32761.54Skamil				break;
32771.54Skamil			case 64:
32781.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
32791.54Skamil				break;
32801.54Skamil			default:
32811.54Skamil				break;
32821.54Skamil			}
32831.54Skamil			break;
32841.54Skamil		case PIOD_READ_AUXV:
32851.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
32861.54Skamil			        io.piod_len);
32871.54Skamil			ATF_REQUIRE(io.piod_len > 0);
32881.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
32891.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
32901.54Skamil				    (long long int)aip->a_type,
32911.54Skamil				    (long long int)aip->a_v);
32921.54Skamil			break;
32931.54Skamil		default:
32941.54Skamil			break;
32951.54Skamil		}
32961.54Skamil		break;
32971.54Skamil	case BYTES_TRANSFER_TEXT:
32981.54Skamil		switch (operation) {
32991.54Skamil		case PT_READ_D:
33001.54Skamil		case PT_READ_I:
33011.54Skamil			errno = 0;
33021.54Skamil			lookup_me = ptrace(operation, child,
33031.54Skamil			                   bytes_transfer_dummy, 0);
33041.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
33051.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
33061.54Skamil			break;
33071.54Skamil		case PT_WRITE_D:
33081.54Skamil		case PT_WRITE_I:
33091.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
33101.54Skamil			                       bytes_transfer_dummy, magic)
33111.54Skamil			                != -1);
33121.54Skamil			break;
33131.54Skamil		default:
33141.54Skamil			break;
33151.54Skamil		}
33161.54Skamil		break;
33171.54Skamil	case BYTES_TRANSFER_DATA:
33181.54Skamil		switch (operation) {
33191.54Skamil		case PT_READ_D:
33201.54Skamil		case PT_READ_I:
33211.54Skamil			errno = 0;
33221.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
33231.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
33241.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
33251.54Skamil			break;
33261.54Skamil		case PT_WRITE_D:
33271.54Skamil		case PT_WRITE_I:
33281.54Skamil			lookup_me = magic;
33291.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
33301.54Skamil			                       magic) != -1);
33311.54Skamil			break;
33321.54Skamil		default:
33331.54Skamil			break;
33341.54Skamil		}
33351.54Skamil		break;
33361.54Skamil	default:
33371.54Skamil		break;
33381.54Skamil	}
33391.1Skamil
33401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33411.1Skamil	    "without signal to be sent\n");
33421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33431.1Skamil
33441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33461.1Skamil
33471.1Skamil	validate_status_exited(status, exitval);
33481.1Skamil
33491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33511.1Skamil}
33521.1Skamil
33531.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
33541.61SkreATF_TC(test);								\
33551.61SkreATF_TC_HEAD(test, tc)							\
33561.61Skre{									\
33571.61Skre	atf_tc_set_md_var(tc, "descr",					\
33581.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
33591.61Skre	    " of type " #type);						\
33601.61Skre}									\
33611.61Skre									\
33621.61SkreATF_TC_BODY(test, tc)							\
33631.61Skre{									\
33641.61Skre									\
33651.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
33661.1Skamil}
33671.1Skamil
33681.54Skamil// DATA
33691.1Skamil
33701.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
33711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
33721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
33731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
33741.54Skamil
33751.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
33761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
33771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
33781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
33791.54Skamil
33801.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
33811.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
33821.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
33831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
33841.54Skamil
33851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
33861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
33871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
33881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
33891.54Skamil
33901.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
33911.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
33921.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
33931.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
33941.54Skamil
33951.54Skamil// TEXT
33961.54Skamil
33971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
33981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
33991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
34001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
34011.54Skamil
34021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
34031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
34041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
34051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
34061.54Skamil
34071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
34081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
34091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
34101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
34111.54Skamil
34121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
34131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
34141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
34151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
34161.54Skamil
34171.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
34181.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
34191.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
34201.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
34211.1Skamil
34221.54Skamil// AUXV
34231.1Skamil
34241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
34251.1Skamil
34261.54Skamil/// ----------------------------------------------------------------------------
34271.1Skamil
34281.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
34291.72Skamilstatic void
34301.72Skamilaccess_regs(const char *regset, const char *aux)
34311.1Skamil{
34321.1Skamil	const int exitval = 5;
34331.1Skamil	const int sigval = SIGSTOP;
34341.1Skamil	pid_t child, wpid;
34351.1Skamil#if defined(TWAIT_HAVE_STATUS)
34361.1Skamil	int status;
34371.1Skamil#endif
34381.72Skamil#if defined(HAVE_GPREGS)
34391.72Skamil	struct reg gpr;
34401.76Sscole	register_t rgstr;
34411.1Skamil#endif
34421.72Skamil#if defined(HAVE_FPREGS)
34431.72Skamil	struct fpreg fpr;
34441.1Skamil#endif
34451.76Sscole
34461.72Skamil#if !defined(HAVE_GPREGS)
34471.72Skamil	if (strcmp(regset, "regs") == 0)
34481.72Skamil		atf_tc_fail("Impossible test scenario!");
34491.1Skamil#endif
34501.1Skamil
34511.72Skamil#if !defined(HAVE_FPREGS)
34521.72Skamil	if (strcmp(regset, "fpregs") == 0)
34531.72Skamil		atf_tc_fail("Impossible test scenario!");
34541.1Skamil#endif
34551.1Skamil
34561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34581.1Skamil	if (child == 0) {
34591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34611.1Skamil
34621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34641.1Skamil
34651.13Schristos		DPRINTF("Before exiting of the child process\n");
34661.1Skamil		_exit(exitval);
34671.1Skamil	}
34681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34691.1Skamil
34701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34721.1Skamil
34731.1Skamil	validate_status_stopped(status, sigval);
34741.1Skamil
34751.1Skamil#if defined(HAVE_GPREGS)
34761.72Skamil	if (strcmp(regset, "regs") == 0) {
34771.72Skamil		DPRINTF("Call GETREGS for the child process\n");
34781.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
34791.72Skamil
34801.72Skamil		if (strcmp(aux, "none") == 0) {
34811.72Skamil			DPRINTF("Retrieved registers\n");
34821.72Skamil		} else if (strcmp(aux, "pc") == 0) {
34831.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
34841.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
34851.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
34861.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
34871.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
34881.72Skamil		} else if (strcmp(aux, "sp") == 0) {
34891.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
34901.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
34911.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
34921.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
34931.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
34941.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
34951.72Skamil			DPRINTF("Call SETREGS for the child process\n");
34961.72Skamil			SYSCALL_REQUIRE(
34971.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
34981.72Skamil		}
34991.72Skamil	}
35001.1Skamil#endif
35011.1Skamil
35021.72Skamil#if defined(HAVE_FPREGS)
35031.72Skamil	if (strcmp(regset, "fpregs") == 0) {
35041.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
35051.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
35061.72Skamil
35071.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
35081.72Skamil			DPRINTF("Retrieved FP registers\n");
35091.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
35101.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
35111.72Skamil			SYSCALL_REQUIRE(
35121.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
35131.72Skamil		}
35141.1Skamil	}
35151.1Skamil#endif
35161.1Skamil
35171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35181.1Skamil	    "without signal to be sent\n");
35191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35201.1Skamil
35211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35231.1Skamil
35241.1Skamil	validate_status_exited(status, exitval);
35251.1Skamil
35261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35271.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35281.1Skamil}
35291.1Skamil
35301.72Skamil#define ACCESS_REGS(test, regset, aux)					\
35311.72SkamilATF_TC(test);								\
35321.72SkamilATF_TC_HEAD(test, tc)							\
35331.72Skamil{									\
35341.72Skamil        atf_tc_set_md_var(tc, "descr",					\
35351.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
35361.72Skamil}									\
35371.72Skamil									\
35381.72SkamilATF_TC_BODY(test, tc)							\
35391.72Skamil{									\
35401.72Skamil									\
35411.72Skamil        access_regs(regset, aux);					\
35421.1Skamil}
35431.1Skamil#endif
35441.1Skamil
35451.72Skamil#if defined(HAVE_GPREGS)
35461.72SkamilACCESS_REGS(access_regs1, "regs", "none")
35471.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
35481.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
35491.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
35501.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
35511.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
35521.1Skamil#endif
35531.1Skamil#if defined(HAVE_FPREGS)
35541.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
35551.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
35561.1Skamil#endif
35571.1Skamil
35581.72Skamil/// ----------------------------------------------------------------------------
35591.1Skamil
35601.1Skamil#if defined(PT_STEP)
35611.1Skamilstatic void
35621.2Skamilptrace_step(int N, int setstep)
35631.1Skamil{
35641.1Skamil	const int exitval = 5;
35651.1Skamil	const int sigval = SIGSTOP;
35661.1Skamil	pid_t child, wpid;
35671.1Skamil#if defined(TWAIT_HAVE_STATUS)
35681.1Skamil	int status;
35691.1Skamil#endif
35701.1Skamil	int happy;
35711.81Skamil	struct ptrace_siginfo info;
35721.1Skamil
35731.1Skamil#if defined(__arm__)
35741.1Skamil	/* PT_STEP not supported on arm 32-bit */
35751.1Skamil	atf_tc_expect_fail("PR kern/52119");
35761.1Skamil#endif
35771.1Skamil
35781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35801.1Skamil	if (child == 0) {
35811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35831.1Skamil
35841.1Skamil		happy = check_happy(999);
35851.1Skamil
35861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35881.1Skamil
35891.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
35901.1Skamil
35911.13Schristos		DPRINTF("Before exiting of the child process\n");
35921.1Skamil		_exit(exitval);
35931.1Skamil	}
35941.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35951.1Skamil
35961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35981.1Skamil
35991.1Skamil	validate_status_stopped(status, sigval);
36001.1Skamil
36011.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36021.81Skamil	SYSCALL_REQUIRE(
36031.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36041.81Skamil
36051.81Skamil	DPRINTF("Before checking siginfo_t\n");
36061.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
36071.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
36081.81Skamil
36091.1Skamil	while (N --> 0) {
36101.2Skamil		if (setstep) {
36111.13Schristos			DPRINTF("Before resuming the child process where it "
36121.2Skamil			    "left off and without signal to be sent (use "
36131.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
36141.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
36151.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
36161.2Skamil			    != -1);
36171.2Skamil		} else {
36181.13Schristos			DPRINTF("Before resuming the child process where it "
36191.2Skamil			    "left off and without signal to be sent (use "
36201.2Skamil			    "PT_STEP)\n");
36211.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
36221.2Skamil			    != -1);
36231.2Skamil		}
36241.1Skamil
36251.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36261.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
36271.1Skamil		    child);
36281.1Skamil
36291.1Skamil		validate_status_stopped(status, SIGTRAP);
36301.2Skamil
36311.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36321.81Skamil		SYSCALL_REQUIRE(
36331.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36341.81Skamil
36351.81Skamil		DPRINTF("Before checking siginfo_t\n");
36361.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
36371.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
36381.81Skamil
36391.2Skamil		if (setstep) {
36401.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
36411.2Skamil		}
36421.1Skamil	}
36431.1Skamil
36441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36451.1Skamil	    "without signal to be sent\n");
36461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36471.1Skamil
36481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36501.1Skamil
36511.1Skamil	validate_status_exited(status, exitval);
36521.1Skamil
36531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36551.1Skamil}
36561.1Skamil
36571.73Skamil#define PTRACE_STEP(test, N, setstep)					\
36581.73SkamilATF_TC(test);								\
36591.73SkamilATF_TC_HEAD(test, tc)							\
36601.73Skamil{									\
36611.73Skamil        atf_tc_set_md_var(tc, "descr",					\
36621.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
36631.73Skamil}									\
36641.73Skamil									\
36651.73SkamilATF_TC_BODY(test, tc)							\
36661.73Skamil{									\
36671.73Skamil									\
36681.73Skamil        ptrace_step(N, setstep);					\
36691.1Skamil}
36701.1Skamil
36711.73SkamilPTRACE_STEP(step1, 1, 0)
36721.73SkamilPTRACE_STEP(step2, 2, 0)
36731.73SkamilPTRACE_STEP(step3, 3, 0)
36741.73SkamilPTRACE_STEP(step4, 4, 0)
36751.73SkamilPTRACE_STEP(setstep1, 1, 1)
36761.73SkamilPTRACE_STEP(setstep2, 2, 1)
36771.73SkamilPTRACE_STEP(setstep3, 3, 1)
36781.73SkamilPTRACE_STEP(setstep4, 4, 1)
36791.1Skamil#endif
36801.1Skamil
36811.73Skamil/// ----------------------------------------------------------------------------
36821.1Skamil
36831.75Skamilstatic void
36841.75Skamilptrace_kill(const char *type)
36851.1Skamil{
36861.75Skamil	const int sigval = SIGSTOP;
36871.1Skamil	pid_t child, wpid;
36881.1Skamil#if defined(TWAIT_HAVE_STATUS)
36891.1Skamil	int status;
36901.1Skamil#endif
36911.1Skamil
36921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36941.1Skamil	if (child == 0) {
36951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36971.1Skamil
36981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37001.1Skamil
37011.1Skamil		/* NOTREACHED */
37021.1Skamil		FORKEE_ASSERTX(0 &&
37031.1Skamil		    "Child should be terminated by a signal from its parent");
37041.1Skamil	}
37051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37061.1Skamil
37071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37091.1Skamil
37101.1Skamil	validate_status_stopped(status, sigval);
37111.1Skamil
37121.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
37131.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
37141.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
37151.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
37161.75Skamil		kill(child, SIGKILL);
37171.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
37181.75Skamil		setpgid(child, 0);
37191.75Skamil		killpg(getpgid(child), SIGKILL);
37201.75Skamil	}
37211.1Skamil
37221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37241.1Skamil
37251.75Skamil	validate_status_signaled(status, SIGKILL, 0);
37261.1Skamil
37271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37291.1Skamil}
37301.1Skamil
37311.75Skamil#define PTRACE_KILL(test, type)						\
37321.75SkamilATF_TC(test);								\
37331.75SkamilATF_TC_HEAD(test, tc)							\
37341.75Skamil{									\
37351.75Skamil        atf_tc_set_md_var(tc, "descr",					\
37361.75Skamil            "Verify killing the child with " type);			\
37371.75Skamil}									\
37381.75Skamil									\
37391.75SkamilATF_TC_BODY(test, tc)							\
37401.75Skamil{									\
37411.75Skamil									\
37421.75Skamil        ptrace_kill(type);						\
37431.1Skamil}
37441.1Skamil
37451.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
37461.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
37471.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
37481.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
37491.1Skamil
37501.75Skamil/// ----------------------------------------------------------------------------
37511.1Skamil
37521.77Skamilstatic void
37531.77Skamiltraceme_lwpinfo(const int threads)
37541.1Skamil{
37551.1Skamil	const int sigval = SIGSTOP;
37561.77Skamil	const int sigval2 = SIGINT;
37571.1Skamil	pid_t child, wpid;
37581.1Skamil#if defined(TWAIT_HAVE_STATUS)
37591.1Skamil	int status;
37601.1Skamil#endif
37611.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
37621.77Skamil	struct ptrace_siginfo info;
37631.77Skamil
37641.77Skamil	/* Maximum number of supported threads in this test */
37651.77Skamil	pthread_t t[3];
37661.77Skamil	int n, rv;
37671.77Skamil
37681.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
37691.1Skamil
37701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37721.1Skamil	if (child == 0) {
37731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37751.1Skamil
37761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37781.1Skamil
37791.77Skamil		for (n = 0; n < threads; n++) {
37801.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
37811.77Skamil			FORKEE_ASSERT(rv == 0);
37821.77Skamil		}
37831.77Skamil
37841.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
37851.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
37861.77Skamil
37871.77Skamil		/* NOTREACHED */
37881.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
37891.1Skamil	}
37901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37911.1Skamil
37921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37941.1Skamil
37951.1Skamil	validate_status_stopped(status, sigval);
37961.1Skamil
37971.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
37981.77Skamil	SYSCALL_REQUIRE(
37991.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38001.77Skamil
38011.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
38021.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
38031.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
38041.77Skamil	    info.psi_siginfo.si_errno);
38051.77Skamil
38061.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
38071.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
38081.77Skamil
38091.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
38101.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
38111.1Skamil
38121.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
38131.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
38141.1Skamil
38151.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
38161.77Skamil	    lwp.pl_lwpid);
38171.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
38181.1Skamil
38191.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
38201.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
38211.1Skamil
38221.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
38231.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
38241.1Skamil
38251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38261.1Skamil	    "without signal to be sent\n");
38271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38281.1Skamil
38291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38311.1Skamil
38321.77Skamil	validate_status_stopped(status, sigval2);
38331.77Skamil
38341.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
38351.77Skamil	SYSCALL_REQUIRE(
38361.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38371.77Skamil
38381.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
38391.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
38401.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
38411.77Skamil	    info.psi_siginfo.si_errno);
38421.77Skamil
38431.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
38441.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
38451.77Skamil
38461.77Skamil	memset(&lwp, 0, sizeof(lwp));
38471.77Skamil
38481.77Skamil	for (n = 0; n <= threads; n++) {
38491.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
38501.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
38511.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
38521.77Skamil
38531.77Skamil		DPRINTF("Assert that the thread exists\n");
38541.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
38551.77Skamil
38561.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
38571.77Skamil		    lwp.pl_lwpid);
38581.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
38591.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
38601.77Skamil	}
38611.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
38621.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
38631.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
38641.77Skamil
38651.77Skamil	DPRINTF("Assert that there are no more threads\n");
38661.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
38671.77Skamil
38681.77Skamil	DPRINTF("Before resuming the child process where it left off and "
38691.77Skamil	    "without signal to be sent\n");
38701.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
38711.77Skamil
38721.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38731.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38741.77Skamil
38751.77Skamil	validate_status_signaled(status, SIGKILL, 0);
38761.1Skamil
38771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38791.1Skamil}
38801.1Skamil
38811.77Skamil#define TRACEME_LWPINFO(test, threads)					\
38821.77SkamilATF_TC(test);								\
38831.77SkamilATF_TC_HEAD(test, tc)							\
38841.77Skamil{									\
38851.77Skamil	atf_tc_set_md_var(tc, "descr",					\
38861.77Skamil	    "Verify LWPINFO with the child with " #threads		\
38871.77Skamil	    " spawned extra threads");					\
38881.77Skamil}									\
38891.77Skamil									\
38901.77SkamilATF_TC_BODY(test, tc)							\
38911.77Skamil{									\
38921.77Skamil									\
38931.77Skamil	traceme_lwpinfo(threads);					\
38941.1Skamil}
38951.1Skamil
38961.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
38971.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
38981.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
38991.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
39001.77Skamil
39011.77Skamil/// ----------------------------------------------------------------------------
39021.77Skamil
39031.77Skamil#if defined(TWAIT_HAVE_PID)
39041.77Skamilstatic void
39051.77Skamilattach_lwpinfo(const int threads)
39061.1Skamil{
39071.77Skamil	const int sigval = SIGINT;
39081.1Skamil	struct msg_fds parent_tracee, parent_tracer;
39091.1Skamil	const int exitval_tracer = 10;
39101.1Skamil	pid_t tracee, tracer, wpid;
39111.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
39121.1Skamil#if defined(TWAIT_HAVE_STATUS)
39131.1Skamil	int status;
39141.1Skamil#endif
39151.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
39161.77Skamil	struct ptrace_siginfo info;
39171.77Skamil
39181.77Skamil	/* Maximum number of supported threads in this test */
39191.77Skamil	pthread_t t[3];
39201.77Skamil	int n, rv;
39211.1Skamil
39221.13Schristos	DPRINTF("Spawn tracee\n");
39231.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
39241.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
39251.1Skamil	tracee = atf_utils_fork();
39261.1Skamil	if (tracee == 0) {
39271.1Skamil		/* Wait for message from the parent */
39281.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
39291.1Skamil
39301.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
39311.77Skamil
39321.77Skamil		for (n = 0; n < threads; n++) {
39331.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
39341.77Skamil			FORKEE_ASSERT(rv == 0);
39351.77Skamil		}
39361.77Skamil
39371.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
39381.77Skamil
39391.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39401.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39411.77Skamil
39421.77Skamil		/* NOTREACHED */
39431.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
39441.1Skamil	}
39451.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
39461.1Skamil
39471.13Schristos	DPRINTF("Spawn debugger\n");
39481.1Skamil	tracer = atf_utils_fork();
39491.1Skamil	if (tracer == 0) {
39501.1Skamil		/* No IPC to communicate with the child */
39511.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
39521.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
39531.1Skamil
39541.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
39551.1Skamil		FORKEE_REQUIRE_SUCCESS(
39561.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
39571.1Skamil
39581.1Skamil		forkee_status_stopped(status, SIGSTOP);
39591.1Skamil
39601.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
39611.77Skamil		    "tracee");
39621.77Skamil		FORKEE_ASSERT(
39631.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
39641.77Skamil
39651.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
39661.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
39671.77Skamil		    "si_errno=%#x\n",
39681.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
39691.77Skamil		    info.psi_siginfo.si_errno);
39701.77Skamil
39711.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
39721.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
39731.77Skamil
39741.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
39751.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
39761.1Skamil		    != -1);
39771.1Skamil
39781.13Schristos		DPRINTF("Assert that there exists a thread\n");
39791.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
39801.1Skamil
39811.13Schristos		DPRINTF("Assert that lwp thread %d received event "
39821.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
39831.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
39841.1Skamil
39851.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
39861.77Skamil		    "tracee\n");
39871.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
39881.1Skamil		    != -1);
39891.1Skamil
39901.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
39911.77Skamil		    "tracee\n");
39921.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
39931.1Skamil
39941.1Skamil		/* Resume tracee with PT_CONTINUE */
39951.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
39961.1Skamil
39971.1Skamil		/* Inform parent that tracer has attached to tracee */
39981.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
39991.77Skamil
40001.1Skamil		/* Wait for parent */
40011.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
40021.1Skamil
40031.77Skamil		/* Wait for tracee and assert that it raised a signal */
40041.77Skamil		FORKEE_REQUIRE_SUCCESS(
40051.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
40061.77Skamil
40071.77Skamil		forkee_status_stopped(status, SIGINT);
40081.77Skamil
40091.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
40101.77Skamil		    "child");
40111.77Skamil		FORKEE_ASSERT(
40121.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
40131.77Skamil
40141.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
40151.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
40161.77Skamil		    "si_errno=%#x\n",
40171.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
40181.77Skamil		    info.psi_siginfo.si_errno);
40191.77Skamil
40201.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
40211.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
40221.77Skamil
40231.77Skamil		memset(&lwp, 0, sizeof(lwp));
40241.77Skamil
40251.77Skamil		for (n = 0; n <= threads; n++) {
40261.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
40271.77Skamil			    "child\n");
40281.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
40291.77Skamil			    sizeof(lwp)) != -1);
40301.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
40311.77Skamil
40321.77Skamil			DPRINTF("Assert that the thread exists\n");
40331.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
40341.77Skamil
40351.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
40361.77Skamil			    "event\n", lwp.pl_lwpid);
40371.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
40381.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
40391.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
40401.77Skamil		}
40411.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
40421.77Skamil		    "tracee\n");
40431.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
40441.77Skamil		    != -1);
40451.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
40461.77Skamil
40471.77Skamil		DPRINTF("Assert that there are no more threads\n");
40481.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
40491.77Skamil
40501.77Skamil		DPRINTF("Before resuming the child process where it left off "
40511.77Skamil		    "and without signal to be sent\n");
40521.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
40531.77Skamil		    != -1);
40541.77Skamil
40551.1Skamil		/* Wait for tracee and assert that it exited */
40561.1Skamil		FORKEE_REQUIRE_SUCCESS(
40571.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
40581.1Skamil
40591.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
40601.1Skamil
40611.13Schristos		DPRINTF("Before exiting of the tracer process\n");
40621.1Skamil		_exit(exitval_tracer);
40631.1Skamil	}
40641.1Skamil
40651.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
40661.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
40671.1Skamil
40681.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
40691.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
40701.77Skamil
40711.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
40721.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
40731.1Skamil
40741.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
40751.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
40761.1Skamil
40771.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
40781.1Skamil	    TWAIT_FNAME);
40791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
40801.1Skamil	    tracer);
40811.1Skamil
40821.1Skamil	validate_status_exited(status, exitval_tracer);
40831.1Skamil
40841.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
40851.1Skamil	    TWAIT_FNAME);
40861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
40871.1Skamil	    tracee);
40881.1Skamil
40891.77Skamil	validate_status_signaled(status, SIGKILL, 0);
40901.1Skamil
40911.1Skamil	msg_close(&parent_tracer);
40921.1Skamil	msg_close(&parent_tracee);
40931.1Skamil}
40941.77Skamil
40951.77Skamil#define ATTACH_LWPINFO(test, threads)					\
40961.77SkamilATF_TC(test);								\
40971.77SkamilATF_TC_HEAD(test, tc)							\
40981.77Skamil{									\
40991.77Skamil	atf_tc_set_md_var(tc, "descr",					\
41001.77Skamil	    "Verify LWPINFO with the child with " #threads		\
41011.77Skamil	    " spawned extra threads (tracer is not the original "	\
41021.77Skamil	    "parent)");							\
41031.77Skamil}									\
41041.77Skamil									\
41051.77SkamilATF_TC_BODY(test, tc)							\
41061.77Skamil{									\
41071.77Skamil									\
41081.77Skamil	attach_lwpinfo(threads);					\
41091.77Skamil}
41101.77Skamil
41111.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
41121.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
41131.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
41141.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
41151.1Skamil#endif
41161.1Skamil
41171.77Skamil/// ----------------------------------------------------------------------------
41181.77Skamil
41191.1Skamilstatic void
41201.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
41211.1Skamil{
41221.1Skamil	const int exitval = 5;
41231.1Skamil	const int sigval = SIGINT;
41241.1Skamil	const int sigfaked = SIGTRAP;
41251.1Skamil	const int sicodefaked = TRAP_BRKPT;
41261.1Skamil	pid_t child, wpid;
41271.1Skamil	struct sigaction sa;
41281.1Skamil#if defined(TWAIT_HAVE_STATUS)
41291.1Skamil	int status;
41301.1Skamil#endif
41311.1Skamil	struct ptrace_siginfo info;
41321.1Skamil	memset(&info, 0, sizeof(info));
41331.1Skamil
41341.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41351.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41361.1Skamil	if (child == 0) {
41371.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41381.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41391.1Skamil
41401.79Skamil		sa.sa_sigaction = sah;
41411.1Skamil		sa.sa_flags = SA_SIGINFO;
41421.1Skamil		sigemptyset(&sa.sa_mask);
41431.1Skamil
41441.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
41451.79Skamil		    != -1);
41461.1Skamil
41471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41491.1Skamil
41501.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
41511.1Skamil
41521.13Schristos		DPRINTF("Before exiting of the child process\n");
41531.1Skamil		_exit(exitval);
41541.1Skamil	}
41551.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41561.1Skamil
41571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41591.1Skamil
41601.1Skamil	validate_status_stopped(status, sigval);
41611.1Skamil
41621.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
41631.61Skre	SYSCALL_REQUIRE(
41641.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41651.1Skamil
41661.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
41671.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
41681.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41691.1Skamil	    info.psi_siginfo.si_errno);
41701.1Skamil
41711.79Skamil	if (faked) {
41721.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
41731.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
41741.79Skamil		info.psi_siginfo.si_signo = sigfaked;
41751.79Skamil		info.psi_siginfo.si_code = sicodefaked;
41761.79Skamil	}
41771.1Skamil
41781.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
41791.61Skre	SYSCALL_REQUIRE(
41801.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
41811.1Skamil
41821.79Skamil	if (faked) {
41831.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
41841.79Skamil		    "child\n");
41851.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
41861.79Skamil		    sizeof(info)) != -1);
41871.1Skamil
41881.79Skamil		DPRINTF("Before checking siginfo_t\n");
41891.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
41901.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
41911.79Skamil	}
41921.1Skamil
41931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41941.1Skamil	    "without signal to be sent\n");
41951.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
41961.79Skamil	    faked ? sigfaked : sigval) != -1);
41971.1Skamil
41981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42001.1Skamil
42011.1Skamil	validate_status_exited(status, exitval);
42021.1Skamil
42031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42041.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42051.1Skamil}
42061.1Skamil
42071.79Skamil#define PTRACE_SIGINFO(test, faked)					\
42081.79SkamilATF_TC(test);								\
42091.79SkamilATF_TC_HEAD(test, tc)							\
42101.79Skamil{									\
42111.79Skamil	atf_tc_set_md_var(tc, "descr",					\
42121.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
42131.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
42141.79Skamil}									\
42151.79Skamil									\
42161.79Skamilstatic int test##_caught = 0;						\
42171.79Skamil									\
42181.79Skamilstatic void								\
42191.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
42201.79Skamil{									\
42211.79Skamil	if (faked) {							\
42221.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
42231.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
42241.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
42251.79Skamil	} else {							\
42261.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
42271.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
42281.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
42291.79Skamil	}								\
42301.79Skamil									\
42311.79Skamil	++ test##_caught;						\
42321.79Skamil}									\
42331.79Skamil									\
42341.79SkamilATF_TC_BODY(test, tc)							\
42351.79Skamil{									\
42361.79Skamil									\
42371.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
42381.79Skamil}
42391.79Skamil
42401.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
42411.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
42421.79Skamil
42431.79Skamil/// ----------------------------------------------------------------------------
42441.79Skamil
42451.82SkamilATF_TC(traceme_exec);
42461.82SkamilATF_TC_HEAD(traceme_exec, tc)
42471.1Skamil{
42481.1Skamil	atf_tc_set_md_var(tc, "descr",
42491.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
42501.1Skamil}
42511.1Skamil
42521.82SkamilATF_TC_BODY(traceme_exec, tc)
42531.1Skamil{
42541.1Skamil	const int sigval = SIGTRAP;
42551.1Skamil	pid_t child, wpid;
42561.1Skamil#if defined(TWAIT_HAVE_STATUS)
42571.1Skamil	int status;
42581.1Skamil#endif
42591.1Skamil
42601.1Skamil	struct ptrace_siginfo info;
42611.1Skamil	memset(&info, 0, sizeof(info));
42621.1Skamil
42631.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42641.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42651.1Skamil	if (child == 0) {
42661.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42671.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42681.1Skamil
42691.13Schristos		DPRINTF("Before calling execve(2) from child\n");
42701.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
42711.1Skamil
42721.1Skamil		FORKEE_ASSERT(0 && "Not reached");
42731.1Skamil	}
42741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42751.1Skamil
42761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42781.1Skamil
42791.1Skamil	validate_status_stopped(status, sigval);
42801.1Skamil
42811.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
42821.61Skre	SYSCALL_REQUIRE(
42831.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
42841.1Skamil
42851.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
42861.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
42871.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
42881.1Skamil	    info.psi_siginfo.si_errno);
42891.1Skamil
42901.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
42911.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
42921.1Skamil
42931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42941.1Skamil	    "without signal to be sent\n");
42951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42961.1Skamil
42971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
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.82Skamil/// ----------------------------------------------------------------------------
43051.82Skamil
43061.83Skamilstatic volatile int done;
43071.1Skamil
43081.83Skamilstatic void *
43091.83Skamiltrace_threads_cb(void *arg __unused)
43101.1Skamil{
43111.1Skamil
43121.83Skamil	done++;
43131.83Skamil
43141.83Skamil	while (done < 3)
43151.83Skamil		continue;
43161.83Skamil
43171.83Skamil	return NULL;
43181.1Skamil}
43191.1Skamil
43201.83Skamilstatic void
43211.83Skamiltrace_threads(bool trace_create, bool trace_exit)
43221.1Skamil{
43231.1Skamil	const int sigval = SIGSTOP;
43241.1Skamil	pid_t child, wpid;
43251.1Skamil#if defined(TWAIT_HAVE_STATUS)
43261.1Skamil	int status;
43271.1Skamil#endif
43281.1Skamil	ptrace_state_t state;
43291.1Skamil	const int slen = sizeof(state);
43301.1Skamil	ptrace_event_t event;
43311.1Skamil	const int elen = sizeof(event);
43321.83Skamil	struct ptrace_siginfo info;
43331.83Skamil
43341.83Skamil	pthread_t t[3];
43351.83Skamil	int rv;
43361.83Skamil	size_t n;
43371.1Skamil	lwpid_t lid;
43381.83Skamil
43391.83Skamil	/* Track created and exited threads */
43401.83Skamil	bool traced_lwps[__arraycount(t)];
43411.83Skamil
43421.83Skamil	atf_tc_skip("PR kern/51995");
43431.1Skamil
43441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43461.1Skamil	if (child == 0) {
43471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43491.1Skamil
43501.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43511.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43521.1Skamil
43531.83Skamil		for (n = 0; n < __arraycount(t); n++) {
43541.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
43551.83Skamil			    NULL);
43561.83Skamil			FORKEE_ASSERT(rv == 0);
43571.83Skamil		}
43581.1Skamil
43591.83Skamil		for (n = 0; n < __arraycount(t); n++) {
43601.83Skamil			rv = pthread_join(t[n], NULL);
43611.83Skamil			FORKEE_ASSERT(rv == 0);
43621.83Skamil		}
43631.1Skamil
43641.83Skamil		/*
43651.83Skamil		 * There is race between _exit() and pthread_join() detaching
43661.83Skamil		 * a thread. For simplicity kill the process after detecting
43671.83Skamil		 * LWP events.
43681.83Skamil		 */
43691.83Skamil		while (true)
43701.83Skamil			continue;
43711.1Skamil
43721.83Skamil		FORKEE_ASSERT(0 && "Not reached");
43731.1Skamil	}
43741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43751.1Skamil
43761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43781.1Skamil
43791.1Skamil	validate_status_stopped(status, sigval);
43801.1Skamil
43811.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
43821.83Skamil	SYSCALL_REQUIRE(
43831.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
43841.1Skamil
43851.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
43861.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
43871.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
43881.83Skamil	    info.psi_siginfo.si_errno);
43891.1Skamil
43901.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
43911.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
43921.1Skamil
43931.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
43941.83Skamil	memset(&event, 0, sizeof(event));
43951.83Skamil	if (trace_create)
43961.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
43971.83Skamil	if (trace_exit)
43981.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
43991.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
44001.1Skamil
44011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44021.1Skamil	    "without signal to be sent\n");
44031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44041.1Skamil
44051.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
44061.1Skamil
44071.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
44081.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
44091.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
44101.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
44111.83Skamil		    child);
44121.1Skamil
44131.83Skamil		validate_status_stopped(status, SIGTRAP);
44141.1Skamil
44151.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
44161.83Skamil		    "child\n");
44171.83Skamil		SYSCALL_REQUIRE(
44181.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
44191.1Skamil
44201.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
44211.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
44221.83Skamil		    "si_errno=%#x\n",
44231.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
44241.83Skamil		    info.psi_siginfo.si_errno);
44251.1Skamil
44261.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
44271.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
44281.1Skamil
44291.83Skamil		SYSCALL_REQUIRE(
44301.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
44311.1Skamil
44321.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
44331.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
44341.1Skamil
44351.83Skamil		lid = state.pe_lwp;
44361.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
44371.1Skamil
44381.83Skamil		traced_lwps[lid - 1] = true;
44391.1Skamil
44401.83Skamil		DPRINTF("Before resuming the child process where it left off "
44411.83Skamil		    "and without signal to be sent\n");
44421.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44431.83Skamil	}
44441.1Skamil
44451.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
44461.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
44471.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
44481.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
44491.83Skamil		    child);
44501.1Skamil
44511.83Skamil		validate_status_stopped(status, SIGTRAP);
44521.1Skamil
44531.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
44541.83Skamil		    "child\n");
44551.83Skamil		SYSCALL_REQUIRE(
44561.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
44571.1Skamil
44581.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
44591.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
44601.83Skamil		    "si_errno=%#x\n",
44611.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
44621.83Skamil		    info.psi_siginfo.si_errno);
44631.1Skamil
44641.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
44651.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
44661.1Skamil
44671.83Skamil		SYSCALL_REQUIRE(
44681.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
44691.1Skamil
44701.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
44711.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
44721.1Skamil
44731.83Skamil		lid = state.pe_lwp;
44741.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
44751.1Skamil
44761.83Skamil		if (trace_create) {
44771.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
44781.83Skamil			traced_lwps[lid - 1] = false;
44791.83Skamil		}
44801.1Skamil
44811.83Skamil		DPRINTF("Before resuming the child process where it left off "
44821.83Skamil		    "and without signal to be sent\n");
44831.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44841.83Skamil	}
44851.1Skamil
44861.83Skamil	kill(child, SIGKILL);
44871.1Skamil
44881.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
44891.1Skamil	    TWAIT_FNAME);
44901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44911.1Skamil
44921.83Skamil	validate_status_signaled(status, SIGKILL, 0);
44931.1Skamil
44941.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
44951.1Skamil	    TWAIT_FNAME);
44961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44971.1Skamil}
44981.1Skamil
44991.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
45001.83SkamilATF_TC(test);								\
45011.83SkamilATF_TC_HEAD(test, tc)							\
45021.83Skamil{									\
45031.83Skamil        atf_tc_set_md_var(tc, "descr",					\
45041.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
45051.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
45061.83Skamil	    trace_exit ? "" : "out");					\
45071.83Skamil}									\
45081.83Skamil									\
45091.83SkamilATF_TC_BODY(test, tc)							\
45101.83Skamil{									\
45111.83Skamil									\
45121.83Skamil        trace_threads(trace_create, trace_exit);			\
45131.83Skamil}
45141.83Skamil
45151.83SkamilTRACE_THREADS(trace_thread1, false, false)
45161.83SkamilTRACE_THREADS(trace_thread2, false, true)
45171.83SkamilTRACE_THREADS(trace_thread3, true, false)
45181.83SkamilTRACE_THREADS(trace_thread4, true, true)
45191.83Skamil
45201.83Skamil/// ----------------------------------------------------------------------------
45211.83Skamil
45221.84SkamilATF_TC(signal_mask_unrelated);
45231.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
45241.1Skamil{
45251.1Skamil	atf_tc_set_md_var(tc, "descr",
45261.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
45271.1Skamil	    "from catching other signals");
45281.1Skamil}
45291.1Skamil
45301.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
45311.1Skamil{
45321.1Skamil	const int exitval = 5;
45331.1Skamil	const int sigval = SIGSTOP;
45341.1Skamil	const int sigmasked = SIGTRAP;
45351.1Skamil	const int signotmasked = SIGINT;
45361.1Skamil	pid_t child, wpid;
45371.1Skamil#if defined(TWAIT_HAVE_STATUS)
45381.1Skamil	int status;
45391.1Skamil#endif
45401.1Skamil	sigset_t intmask;
45411.1Skamil
45421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45441.1Skamil	if (child == 0) {
45451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45471.1Skamil
45481.1Skamil		sigemptyset(&intmask);
45491.1Skamil		sigaddset(&intmask, sigmasked);
45501.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45511.1Skamil
45521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45541.1Skamil
45551.13Schristos		DPRINTF("Before raising %s from child\n",
45561.1Skamil		    strsignal(signotmasked));
45571.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
45581.1Skamil
45591.13Schristos		DPRINTF("Before exiting of the child process\n");
45601.1Skamil		_exit(exitval);
45611.1Skamil	}
45621.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45631.1Skamil
45641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45661.1Skamil
45671.1Skamil	validate_status_stopped(status, sigval);
45681.1Skamil
45691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45701.1Skamil	    "without signal to be sent\n");
45711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45721.1Skamil
45731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45751.1Skamil
45761.1Skamil	validate_status_stopped(status, signotmasked);
45771.1Skamil
45781.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45791.1Skamil	    "without signal to be sent\n");
45801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45811.1Skamil
45821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45841.1Skamil
45851.1Skamil	validate_status_exited(status, exitval);
45861.1Skamil
45871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45881.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45891.1Skamil}
45901.1Skamil
45911.84Skamil/// ----------------------------------------------------------------------------
45921.84Skamil
45931.1Skamil#if defined(PT_STEP)
45941.1SkamilATF_TC(signal4);
45951.1SkamilATF_TC_HEAD(signal4, tc)
45961.1Skamil{
45971.1Skamil	atf_tc_set_md_var(tc, "descr",
45981.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45991.1Skamil	    "catching single step trap");
46001.1Skamil}
46011.1Skamil
46021.1SkamilATF_TC_BODY(signal4, tc)
46031.1Skamil{
46041.1Skamil	const int exitval = 5;
46051.1Skamil	const int sigval = SIGSTOP;
46061.1Skamil	const int sigmasked = SIGTRAP;
46071.1Skamil	pid_t child, wpid;
46081.1Skamil#if defined(TWAIT_HAVE_STATUS)
46091.1Skamil	int status;
46101.1Skamil#endif
46111.1Skamil	sigset_t intmask;
46121.1Skamil	int happy;
46131.1Skamil
46141.1Skamil#if defined(__arm__)
46151.5Skamil	/* PT_STEP not supported on arm 32-bit */
46161.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
46171.1Skamil#endif
46181.1Skamil
46191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46211.1Skamil	if (child == 0) {
46221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46241.1Skamil
46251.1Skamil		happy = check_happy(100);
46261.1Skamil
46271.1Skamil		sigemptyset(&intmask);
46281.1Skamil		sigaddset(&intmask, sigmasked);
46291.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46301.1Skamil
46311.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46321.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46331.1Skamil
46341.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
46351.1Skamil
46361.13Schristos		DPRINTF("Before exiting of the child process\n");
46371.1Skamil		_exit(exitval);
46381.1Skamil	}
46391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46401.1Skamil
46411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46431.1Skamil
46441.1Skamil	validate_status_stopped(status, sigval);
46451.1Skamil
46461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46471.1Skamil	    "without signal to be sent\n");
46481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
46491.1Skamil
46501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46521.1Skamil
46531.1Skamil	validate_status_stopped(status, sigmasked);
46541.1Skamil
46551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46561.1Skamil	    "without signal to be sent\n");
46571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46581.1Skamil
46591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46611.1Skamil
46621.1Skamil	validate_status_exited(status, exitval);
46631.1Skamil
46641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46661.1Skamil}
46671.1Skamil#endif
46681.1Skamil
46691.1SkamilATF_TC(signal5);
46701.1SkamilATF_TC_HEAD(signal5, tc)
46711.1Skamil{
46721.1Skamil	atf_tc_set_md_var(tc, "descr",
46731.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
46741.1Skamil	    "catching exec() breakpoint");
46751.1Skamil}
46761.1Skamil
46771.1SkamilATF_TC_BODY(signal5, tc)
46781.1Skamil{
46791.1Skamil	const int sigval = SIGSTOP;
46801.1Skamil	const int sigmasked = SIGTRAP;
46811.1Skamil	pid_t child, wpid;
46821.1Skamil#if defined(TWAIT_HAVE_STATUS)
46831.1Skamil	int status;
46841.1Skamil#endif
46851.58Skamil	struct ptrace_siginfo info;
46861.1Skamil	sigset_t intmask;
46871.1Skamil
46881.58Skamil	memset(&info, 0, sizeof(info));
46891.14Schristos
46901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46921.1Skamil	if (child == 0) {
46931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46951.1Skamil
46961.1Skamil		sigemptyset(&intmask);
46971.1Skamil		sigaddset(&intmask, sigmasked);
46981.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46991.1Skamil
47001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47021.1Skamil
47031.13Schristos		DPRINTF("Before calling execve(2) from child\n");
47041.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
47051.1Skamil
47061.58Skamil		/* NOTREACHED */
47071.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
47081.1Skamil	}
47091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47101.1Skamil
47111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47131.1Skamil
47141.1Skamil	validate_status_stopped(status, sigval);
47151.1Skamil
47161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47171.1Skamil	    "without signal to be sent\n");
47181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47191.1Skamil
47201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47221.1Skamil
47231.1Skamil	validate_status_stopped(status, sigmasked);
47241.1Skamil
47251.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
47261.61Skre	SYSCALL_REQUIRE(
47271.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
47281.58Skamil
47291.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47301.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
47311.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47321.58Skamil	    info.psi_siginfo.si_errno);
47331.58Skamil
47341.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
47351.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
47361.58Skamil
47371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47381.1Skamil	    "without signal to be sent\n");
47391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47401.1Skamil
47411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47431.1Skamil
47441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47461.1Skamil}
47471.1Skamil
47481.1Skamil#if defined(TWAIT_HAVE_PID)
47491.1SkamilATF_TC(signal6);
47501.1SkamilATF_TC_HEAD(signal6, tc)
47511.1Skamil{
47521.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
47531.1Skamil	atf_tc_set_md_var(tc, "descr",
47541.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
47551.1Skamil	    "catching PTRACE_FORK breakpoint");
47561.1Skamil}
47571.1Skamil
47581.1SkamilATF_TC_BODY(signal6, tc)
47591.1Skamil{
47601.1Skamil	const int exitval = 5;
47611.1Skamil	const int exitval2 = 15;
47621.1Skamil	const int sigval = SIGSTOP;
47631.1Skamil	const int sigmasked = SIGTRAP;
47641.1Skamil	pid_t child, child2, wpid;
47651.1Skamil#if defined(TWAIT_HAVE_STATUS)
47661.1Skamil	int status;
47671.1Skamil#endif
47681.1Skamil	sigset_t intmask;
47691.1Skamil	ptrace_state_t state;
47701.1Skamil	const int slen = sizeof(state);
47711.1Skamil	ptrace_event_t event;
47721.1Skamil	const int elen = sizeof(event);
47731.1Skamil
47741.38Skamil	atf_tc_expect_fail("PR kern/51918");
47751.14Schristos
47761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47781.1Skamil	if (child == 0) {
47791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47811.1Skamil
47821.1Skamil		sigemptyset(&intmask);
47831.1Skamil		sigaddset(&intmask, sigmasked);
47841.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
47851.1Skamil
47861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47881.1Skamil
47891.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
47901.1Skamil
47911.1Skamil		if (child2 == 0)
47921.1Skamil			_exit(exitval2);
47931.1Skamil
47941.1Skamil		FORKEE_REQUIRE_SUCCESS
47951.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
47961.1Skamil
47971.1Skamil		forkee_status_exited(status, exitval2);
47981.1Skamil
47991.13Schristos		DPRINTF("Before exiting of the child process\n");
48001.1Skamil		_exit(exitval);
48011.1Skamil	}
48021.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48031.1Skamil
48041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48061.1Skamil
48071.1Skamil	validate_status_stopped(status, sigval);
48081.1Skamil
48091.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
48101.1Skamil	event.pe_set_event = PTRACE_FORK;
48111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
48121.1Skamil
48131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48141.1Skamil	    "without signal to be sent\n");
48151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48161.1Skamil
48171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48191.1Skamil
48201.1Skamil	validate_status_stopped(status, sigmasked);
48211.1Skamil
48221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
48231.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
48241.1Skamil
48251.1Skamil	child2 = state.pe_other_pid;
48261.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
48271.1Skamil
48281.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
48291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
48301.1Skamil	    child2);
48311.1Skamil
48321.1Skamil	validate_status_stopped(status, SIGTRAP);
48331.1Skamil
48341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
48351.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
48361.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
48371.1Skamil
48381.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
48391.1Skamil	    "without signal to be sent\n");
48401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
48411.1Skamil
48421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48431.1Skamil	    "without signal to be sent\n");
48441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48451.1Skamil
48461.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
48471.1Skamil	    TWAIT_FNAME);
48481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
48491.57Skamil	    child2);
48501.1Skamil
48511.1Skamil	validate_status_exited(status, exitval2);
48521.1Skamil
48531.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
48541.1Skamil	    TWAIT_FNAME);
48551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
48561.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
48571.1Skamil
48581.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48591.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
48601.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48611.1Skamil
48621.1Skamil	validate_status_stopped(status, SIGCHLD);
48631.1Skamil
48641.57Skamil	DPRINTF("Before resuming the child process where it left off and "
48651.1Skamil	    "without signal to be sent\n");
48661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48671.1Skamil
48681.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48691.1Skamil	    TWAIT_FNAME);
48701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48711.1Skamil
48721.1Skamil	validate_status_exited(status, exitval);
48731.1Skamil
48741.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48751.57Skamil	    TWAIT_FNAME);
48761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48771.1Skamil}
48781.1Skamil#endif
48791.1Skamil
48801.1Skamil#if defined(TWAIT_HAVE_PID)
48811.1SkamilATF_TC(signal7);
48821.1SkamilATF_TC_HEAD(signal7, tc)
48831.1Skamil{
48841.1Skamil	atf_tc_set_md_var(tc, "descr",
48851.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
48861.1Skamil	    "catching PTRACE_VFORK breakpoint");
48871.1Skamil}
48881.1Skamil
48891.1SkamilATF_TC_BODY(signal7, tc)
48901.1Skamil{
48911.1Skamil	const int exitval = 5;
48921.1Skamil	const int exitval2 = 15;
48931.1Skamil	const int sigval = SIGSTOP;
48941.1Skamil	const int sigmasked = SIGTRAP;
48951.1Skamil	pid_t child, child2, wpid;
48961.1Skamil#if defined(TWAIT_HAVE_STATUS)
48971.1Skamil	int status;
48981.1Skamil#endif
48991.1Skamil	sigset_t intmask;
49001.1Skamil	ptrace_state_t state;
49011.1Skamil	const int slen = sizeof(state);
49021.1Skamil	ptrace_event_t event;
49031.1Skamil	const int elen = sizeof(event);
49041.1Skamil
49051.38Skamil	atf_tc_expect_fail("PR kern/51918");
49061.14Schristos
49071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49091.1Skamil	if (child == 0) {
49101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49121.1Skamil
49131.1Skamil		sigemptyset(&intmask);
49141.1Skamil		sigaddset(&intmask, sigmasked);
49151.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
49161.1Skamil
49171.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49181.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49191.1Skamil
49201.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
49211.1Skamil
49221.1Skamil		if (child2 == 0)
49231.1Skamil			_exit(exitval2);
49241.1Skamil
49251.1Skamil		FORKEE_REQUIRE_SUCCESS
49261.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
49271.1Skamil
49281.1Skamil		forkee_status_exited(status, exitval2);
49291.1Skamil
49301.13Schristos		DPRINTF("Before exiting of the child process\n");
49311.1Skamil		_exit(exitval);
49321.1Skamil	}
49331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49341.1Skamil
49351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49371.1Skamil
49381.1Skamil	validate_status_stopped(status, sigval);
49391.1Skamil
49401.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
49411.1Skamil	event.pe_set_event = PTRACE_VFORK;
49421.61Skre	SYSCALL_REQUIRE(
49431.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
49441.61Skre	    errno == ENOTSUP);
49451.1Skamil
49461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49471.1Skamil	    "without signal to be sent\n");
49481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49491.1Skamil
49501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49521.1Skamil
49531.1Skamil	validate_status_stopped(status, sigmasked);
49541.1Skamil
49551.61Skre	SYSCALL_REQUIRE(
49561.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
49571.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
49581.1Skamil
49591.1Skamil	child2 = state.pe_other_pid;
49601.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
49611.1Skamil
49621.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
49631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
49641.1Skamil	    child2);
49651.1Skamil
49661.1Skamil	validate_status_stopped(status, SIGTRAP);
49671.1Skamil
49681.61Skre	SYSCALL_REQUIRE(
49691.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
49701.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
49711.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
49721.1Skamil
49731.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
49741.1Skamil	    "without signal to be sent\n");
49751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
49761.1Skamil
49771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49781.1Skamil	    "without signal to be sent\n");
49791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49801.1Skamil
49811.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
49821.1Skamil	    TWAIT_FNAME);
49831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
49841.57Skamil	    child2);
49851.1Skamil
49861.1Skamil	validate_status_exited(status, exitval2);
49871.1Skamil
49881.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
49891.1Skamil	    TWAIT_FNAME);
49901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
49911.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
49921.1Skamil
49931.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49941.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
49951.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49961.1Skamil
49971.1Skamil	validate_status_stopped(status, SIGCHLD);
49981.1Skamil
49991.57Skamil	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.57Skamil	    TWAIT_FNAME);
50111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50121.1Skamil}
50131.1Skamil#endif
50141.1Skamil
50151.1SkamilATF_TC(signal8);
50161.1SkamilATF_TC_HEAD(signal8, tc)
50171.1Skamil{
50181.1Skamil	atf_tc_set_md_var(tc, "descr",
50191.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
50201.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
50211.1Skamil}
50221.1Skamil
50231.1SkamilATF_TC_BODY(signal8, tc)
50241.1Skamil{
50251.1Skamil	const int exitval = 5;
50261.1Skamil	const int exitval2 = 15;
50271.1Skamil	const int sigval = SIGSTOP;
50281.1Skamil	const int sigmasked = SIGTRAP;
50291.1Skamil	pid_t child, child2, wpid;
50301.1Skamil#if defined(TWAIT_HAVE_STATUS)
50311.1Skamil	int status;
50321.1Skamil#endif
50331.1Skamil	sigset_t intmask;
50341.1Skamil	ptrace_state_t state;
50351.1Skamil	const int slen = sizeof(state);
50361.1Skamil	ptrace_event_t event;
50371.1Skamil	const int elen = sizeof(event);
50381.1Skamil
50391.14Schristos	atf_tc_expect_fail("PR kern/51918");
50401.14Schristos
50411.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50421.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50431.1Skamil	if (child == 0) {
50441.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50451.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50461.1Skamil
50471.1Skamil		sigemptyset(&intmask);
50481.1Skamil		sigaddset(&intmask, sigmasked);
50491.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
50501.1Skamil
50511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50531.1Skamil
50541.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
50551.1Skamil
50561.1Skamil		if (child2 == 0)
50571.1Skamil			_exit(exitval2);
50581.1Skamil
50591.1Skamil		FORKEE_REQUIRE_SUCCESS
50601.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
50611.1Skamil
50621.1Skamil		forkee_status_exited(status, exitval2);
50631.1Skamil
50641.13Schristos		DPRINTF("Before exiting of the child process\n");
50651.1Skamil		_exit(exitval);
50661.1Skamil	}
50671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50681.1Skamil
50691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50711.1Skamil
50721.1Skamil	validate_status_stopped(status, sigval);
50731.1Skamil
50741.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
50751.1Skamil	    child);
50761.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
50771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50781.1Skamil
50791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50801.1Skamil	    "without signal to be sent\n");
50811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50821.1Skamil
50831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50851.1Skamil
50861.1Skamil	validate_status_stopped(status, sigmasked);
50871.1Skamil
50881.61Skre	SYSCALL_REQUIRE(
50891.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50901.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
50911.1Skamil
50921.1Skamil	child2 = state.pe_other_pid;
50931.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
50941.1Skamil
50951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50961.1Skamil	    "without signal to be sent\n");
50971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50981.1Skamil
50991.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
51001.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
51011.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51021.1Skamil
51031.1Skamil	validate_status_stopped(status, SIGCHLD);
51041.1Skamil
51051.57Skamil	DPRINTF("Before resuming the child process where it left off and "
51061.1Skamil	    "without signal to be sent\n");
51071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51081.1Skamil
51091.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51101.1Skamil	    TWAIT_FNAME);
51111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51121.1Skamil
51131.1Skamil	validate_status_exited(status, exitval);
51141.1Skamil
51151.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51161.57Skamil	    TWAIT_FNAME);
51171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51181.1Skamil}
51191.1Skamil
51201.83Skamilvolatile lwpid_t the_lwp_id = 0;
51211.83Skamil
51221.83Skamilstatic void
51231.83Skamillwp_main_func(void *arg)
51241.83Skamil{
51251.83Skamil	the_lwp_id = _lwp_self();
51261.83Skamil	_lwp_exit();
51271.83Skamil}
51281.83Skamil
51291.1SkamilATF_TC(signal9);
51301.1SkamilATF_TC_HEAD(signal9, tc)
51311.1Skamil{
51321.1Skamil	atf_tc_set_md_var(tc, "descr",
51331.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
51341.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
51351.1Skamil}
51361.1Skamil
51371.1SkamilATF_TC_BODY(signal9, tc)
51381.1Skamil{
51391.1Skamil	const int exitval = 5;
51401.1Skamil	const int sigval = SIGSTOP;
51411.1Skamil	const int sigmasked = SIGTRAP;
51421.1Skamil	pid_t child, wpid;
51431.1Skamil#if defined(TWAIT_HAVE_STATUS)
51441.1Skamil	int status;
51451.1Skamil#endif
51461.1Skamil	sigset_t intmask;
51471.1Skamil	ptrace_state_t state;
51481.1Skamil	const int slen = sizeof(state);
51491.1Skamil	ptrace_event_t event;
51501.1Skamil	const int elen = sizeof(event);
51511.1Skamil	ucontext_t uc;
51521.1Skamil	lwpid_t lid;
51531.1Skamil	static const size_t ssize = 16*1024;
51541.1Skamil	void *stack;
51551.1Skamil
51561.14Schristos	atf_tc_expect_fail("PR kern/51918");
51571.14Schristos
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.1Skamil		sigemptyset(&intmask);
51651.1Skamil		sigaddset(&intmask, sigmasked);
51661.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
51671.1Skamil
51681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51701.1Skamil
51711.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
51721.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
51731.1Skamil
51741.13Schristos		DPRINTF("Before making context for new lwp in child\n");
51751.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
51761.1Skamil
51771.13Schristos		DPRINTF("Before creating new in child\n");
51781.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
51791.1Skamil
51801.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
51811.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
51821.1Skamil
51831.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
51841.1Skamil		    "are the same\n", lid, the_lwp_id);
51851.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
51861.1Skamil
51871.13Schristos		DPRINTF("Before exiting of the child process\n");
51881.1Skamil		_exit(exitval);
51891.1Skamil	}
51901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51911.1Skamil
51921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51941.1Skamil
51951.1Skamil	validate_status_stopped(status, sigval);
51961.1Skamil
51971.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
51981.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
51991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
52001.1Skamil
52011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52021.1Skamil	    "without signal to be sent\n");
52031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52041.1Skamil
52051.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52061.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
52071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52081.1Skamil
52091.1Skamil	validate_status_stopped(status, sigmasked);
52101.1Skamil
52111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
52121.1Skamil
52131.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
52141.1Skamil
52151.1Skamil	lid = state.pe_lwp;
52161.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
52171.1Skamil
52181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52191.1Skamil	    "without signal to be sent\n");
52201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52211.1Skamil
52221.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52231.1Skamil	    TWAIT_FNAME);
52241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52251.1Skamil
52261.1Skamil	validate_status_exited(status, exitval);
52271.1Skamil
52281.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52291.1Skamil	    TWAIT_FNAME);
52301.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52311.1Skamil}
52321.1Skamil
52331.1SkamilATF_TC(signal10);
52341.1SkamilATF_TC_HEAD(signal10, tc)
52351.1Skamil{
52361.1Skamil	atf_tc_set_md_var(tc, "descr",
52371.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
52381.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
52391.1Skamil}
52401.1Skamil
52411.1SkamilATF_TC_BODY(signal10, tc)
52421.1Skamil{
52431.1Skamil	const int exitval = 5;
52441.1Skamil	const int sigval = SIGSTOP;
52451.1Skamil	const int sigmasked = SIGTRAP;
52461.1Skamil	pid_t child, wpid;
52471.1Skamil#if defined(TWAIT_HAVE_STATUS)
52481.1Skamil	int status;
52491.1Skamil#endif
52501.1Skamil	sigset_t intmask;
52511.1Skamil	ptrace_state_t state;
52521.1Skamil	const int slen = sizeof(state);
52531.1Skamil	ptrace_event_t event;
52541.1Skamil	const int elen = sizeof(event);
52551.1Skamil	ucontext_t uc;
52561.1Skamil	lwpid_t lid;
52571.1Skamil	static const size_t ssize = 16*1024;
52581.1Skamil	void *stack;
52591.1Skamil
52601.14Schristos	atf_tc_expect_fail("PR kern/51918");
52611.14Schristos
52621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52641.1Skamil	if (child == 0) {
52651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52671.1Skamil
52681.1Skamil		sigemptyset(&intmask);
52691.1Skamil		sigaddset(&intmask, sigmasked);
52701.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
52711.1Skamil
52721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52741.1Skamil
52751.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
52761.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
52771.1Skamil
52781.13Schristos		DPRINTF("Before making context for new lwp in child\n");
52791.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
52801.1Skamil
52811.13Schristos		DPRINTF("Before creating new in child\n");
52821.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
52831.1Skamil
52841.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
52851.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
52861.1Skamil
52871.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
52881.1Skamil		    "are the same\n", lid, the_lwp_id);
52891.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
52901.1Skamil
52911.13Schristos		DPRINTF("Before exiting of the child process\n");
52921.1Skamil		_exit(exitval);
52931.1Skamil	}
52941.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52951.1Skamil
52961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52981.1Skamil
52991.1Skamil	validate_status_stopped(status, sigval);
53001.1Skamil
53011.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
53021.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
53031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
53041.1Skamil
53051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53061.1Skamil	    "without signal to be sent\n");
53071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53081.1Skamil
53091.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
53101.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
53111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53121.1Skamil
53131.1Skamil	validate_status_stopped(status, sigmasked);
53141.1Skamil
53151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
53161.1Skamil
53171.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
53181.1Skamil
53191.1Skamil	lid = state.pe_lwp;
53201.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
53211.1Skamil
53221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53231.1Skamil	    "without signal to be sent\n");
53241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53251.1Skamil
53261.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53271.1Skamil	    TWAIT_FNAME);
53281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53291.1Skamil
53301.1Skamil	validate_status_exited(status, exitval);
53311.1Skamil
53321.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53331.1Skamil	    TWAIT_FNAME);
53341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53351.1Skamil}
53361.1Skamil
53371.1Skamilstatic void
53381.1Skamillwp_main_stop(void *arg)
53391.1Skamil{
53401.1Skamil	the_lwp_id = _lwp_self();
53411.1Skamil
53421.1Skamil	raise(SIGTRAP);
53431.1Skamil
53441.1Skamil	_lwp_exit();
53451.1Skamil}
53461.1Skamil
53471.1SkamilATF_TC(suspend1);
53481.1SkamilATF_TC_HEAD(suspend1, tc)
53491.1Skamil{
53501.1Skamil	atf_tc_set_md_var(tc, "descr",
53511.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
53521.1Skamil	    "resumed by a tracee");
53531.1Skamil}
53541.1Skamil
53551.1SkamilATF_TC_BODY(suspend1, tc)
53561.1Skamil{
53571.1Skamil	const int exitval = 5;
53581.1Skamil	const int sigval = SIGSTOP;
53591.1Skamil	pid_t child, wpid;
53601.1Skamil#if defined(TWAIT_HAVE_STATUS)
53611.1Skamil	int status;
53621.1Skamil#endif
53631.1Skamil	ucontext_t uc;
53641.1Skamil	lwpid_t lid;
53651.1Skamil	static const size_t ssize = 16*1024;
53661.1Skamil	void *stack;
53671.1Skamil	struct ptrace_lwpinfo pl;
53681.1Skamil	struct ptrace_siginfo psi;
53691.1Skamil	volatile int go = 0;
53701.1Skamil
53711.17Skamil	// Feature pending for refactoring
53721.17Skamil	atf_tc_expect_fail("PR kern/51995");
53731.17Skamil
53741.16Skamil	// Hangs with qemu
53751.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
53761.16Skamil
53771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53791.1Skamil	if (child == 0) {
53801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53821.1Skamil
53831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53851.1Skamil
53861.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
53871.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53881.1Skamil
53891.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53901.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
53911.1Skamil
53921.13Schristos		DPRINTF("Before creating new in child\n");
53931.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
53941.1Skamil
53951.1Skamil		while (go == 0)
53961.1Skamil			continue;
53971.1Skamil
53981.1Skamil		raise(SIGINT);
53991.1Skamil
54001.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
54011.1Skamil
54021.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54031.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54041.1Skamil
54051.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54061.1Skamil		    "are the same\n", lid, the_lwp_id);
54071.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54081.1Skamil
54091.13Schristos		DPRINTF("Before exiting of the child process\n");
54101.1Skamil		_exit(exitval);
54111.1Skamil	}
54121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54131.1Skamil
54141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54161.1Skamil
54171.1Skamil	validate_status_stopped(status, sigval);
54181.1Skamil
54191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54201.1Skamil	    "without signal to be sent\n");
54211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54221.1Skamil
54231.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54241.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54261.1Skamil
54271.1Skamil	validate_status_stopped(status, SIGTRAP);
54281.1Skamil
54291.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
54301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
54311.1Skamil
54321.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
54331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
54341.1Skamil
54351.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
54361.1Skamil	    child, getpid());
54371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
54381.1Skamil
54391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54401.1Skamil	    "without signal to be sent\n");
54411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54421.1Skamil
54431.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54441.1Skamil	    "SIGINT\n", TWAIT_FNAME);
54451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54461.1Skamil
54471.1Skamil	validate_status_stopped(status, SIGINT);
54481.1Skamil
54491.1Skamil	pl.pl_lwpid = 0;
54501.1Skamil
54511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54521.1Skamil	while (pl.pl_lwpid != 0) {
54531.1Skamil
54541.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54551.1Skamil		switch (pl.pl_lwpid) {
54561.1Skamil		case 1:
54571.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
54581.1Skamil			break;
54591.1Skamil		case 2:
54601.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
54611.1Skamil			break;
54621.1Skamil		}
54631.1Skamil	}
54641.1Skamil
54651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54661.1Skamil	    "without signal to be sent\n");
54671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54681.1Skamil
54691.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54701.1Skamil	    TWAIT_FNAME);
54711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54721.1Skamil
54731.1Skamil	validate_status_exited(status, exitval);
54741.1Skamil
54751.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54761.1Skamil	    TWAIT_FNAME);
54771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54781.1Skamil}
54791.1Skamil
54801.1SkamilATF_TC(suspend2);
54811.1SkamilATF_TC_HEAD(suspend2, tc)
54821.1Skamil{
54831.1Skamil	atf_tc_set_md_var(tc, "descr",
54841.1Skamil	    "Verify that the while the only thread within a process is "
54851.1Skamil	    "suspended, the whole process cannot be unstopped");
54861.1Skamil}
54871.1Skamil
54881.1SkamilATF_TC_BODY(suspend2, tc)
54891.1Skamil{
54901.1Skamil	const int exitval = 5;
54911.1Skamil	const int sigval = SIGSTOP;
54921.1Skamil	pid_t child, wpid;
54931.1Skamil#if defined(TWAIT_HAVE_STATUS)
54941.1Skamil	int status;
54951.1Skamil#endif
54961.1Skamil	struct ptrace_siginfo psi;
54971.1Skamil
54981.17Skamil	// Feature pending for refactoring
54991.17Skamil	atf_tc_expect_fail("PR kern/51995");
55001.17Skamil
55011.16Skamil	// Hangs with qemu
55021.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
55031.16Skamil
55041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55061.1Skamil	if (child == 0) {
55071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55091.1Skamil
55101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55121.1Skamil
55131.13Schristos		DPRINTF("Before exiting of the child process\n");
55141.1Skamil		_exit(exitval);
55151.1Skamil	}
55161.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55171.1Skamil
55181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55201.1Skamil
55211.1Skamil	validate_status_stopped(status, sigval);
55221.1Skamil
55231.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
55241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
55251.1Skamil
55261.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
55271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
55281.1Skamil
55291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55301.1Skamil	    "without signal to be sent\n");
55311.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
55321.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
55331.1Skamil
55341.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
55351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
55361.1Skamil
55371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55381.1Skamil	    "without signal to be sent\n");
55391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55401.1Skamil
55411.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55421.1Skamil	    TWAIT_FNAME);
55431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55441.1Skamil
55451.1Skamil	validate_status_exited(status, exitval);
55461.1Skamil
55471.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55481.1Skamil	    TWAIT_FNAME);
55491.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55501.1Skamil}
55511.1Skamil
55521.1SkamilATF_TC(resume1);
55531.1SkamilATF_TC_HEAD(resume1, tc)
55541.1Skamil{
55551.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
55561.1Skamil	atf_tc_set_md_var(tc, "descr",
55571.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
55581.1Skamil	    "resumed by the debugger");
55591.1Skamil}
55601.1Skamil
55611.1SkamilATF_TC_BODY(resume1, tc)
55621.1Skamil{
55631.1Skamil	struct msg_fds fds;
55641.1Skamil	const int exitval = 5;
55651.1Skamil	const int sigval = SIGSTOP;
55661.1Skamil	pid_t child, wpid;
55671.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
55681.1Skamil#if defined(TWAIT_HAVE_STATUS)
55691.1Skamil	int status;
55701.1Skamil#endif
55711.1Skamil	ucontext_t uc;
55721.1Skamil	lwpid_t lid;
55731.1Skamil	static const size_t ssize = 16*1024;
55741.1Skamil	void *stack;
55751.1Skamil	struct ptrace_lwpinfo pl;
55761.1Skamil	struct ptrace_siginfo psi;
55771.1Skamil
55781.17Skamil	// Feature pending for refactoring
55791.17Skamil	atf_tc_expect_fail("PR kern/51995");
55801.17Skamil
55811.15Schristos	// Hangs with qemu
55821.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
55831.1Skamil
55841.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
55851.1Skamil
55861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55881.1Skamil	if (child == 0) {
55891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55911.1Skamil
55921.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55931.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55941.1Skamil
55951.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
55961.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
55971.1Skamil
55981.13Schristos		DPRINTF("Before making context for new lwp in child\n");
55991.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
56001.1Skamil
56011.13Schristos		DPRINTF("Before creating new in child\n");
56021.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
56031.1Skamil
56041.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
56051.1Skamil
56061.1Skamil		raise(SIGINT);
56071.1Skamil
56081.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
56091.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
56101.1Skamil
56111.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
56121.1Skamil		    "are the same\n", lid, the_lwp_id);
56131.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
56141.1Skamil
56151.13Schristos		DPRINTF("Before exiting of the child process\n");
56161.1Skamil		_exit(exitval);
56171.1Skamil	}
56181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56191.1Skamil
56201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56221.1Skamil
56231.1Skamil	validate_status_stopped(status, sigval);
56241.1Skamil
56251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56261.1Skamil	    "without signal to be sent\n");
56271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56281.1Skamil
56291.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
56301.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
56311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56321.1Skamil
56331.1Skamil	validate_status_stopped(status, SIGTRAP);
56341.1Skamil
56351.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
56361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
56371.1Skamil
56381.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
56391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
56401.1Skamil
56411.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
56421.1Skamil
56431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56441.1Skamil	    "without signal to be sent\n");
56451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56461.1Skamil
56471.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
56481.1Skamil	    "SIGINT\n", TWAIT_FNAME);
56491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56501.1Skamil
56511.1Skamil	validate_status_stopped(status, SIGINT);
56521.1Skamil
56531.1Skamil	pl.pl_lwpid = 0;
56541.1Skamil
56551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
56561.1Skamil	while (pl.pl_lwpid != 0) {
56571.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
56581.1Skamil		switch (pl.pl_lwpid) {
56591.1Skamil		case 1:
56601.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
56611.1Skamil			break;
56621.1Skamil		case 2:
56631.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
56641.1Skamil			break;
56651.1Skamil		}
56661.1Skamil	}
56671.1Skamil
56681.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
56691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
56701.1Skamil
56711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56721.1Skamil	    "without signal to be sent\n");
56731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56741.1Skamil
56751.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
56761.1Skamil	    TWAIT_FNAME);
56771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56781.1Skamil
56791.1Skamil	validate_status_exited(status, exitval);
56801.1Skamil
56811.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
56821.1Skamil	    TWAIT_FNAME);
56831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56841.1Skamil
56851.1Skamil	msg_close(&fds);
56861.1Skamil
56871.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
56881.1Skamil	sleep(10);
56891.1Skamil}
56901.1Skamil
56911.1SkamilATF_TC(syscall1);
56921.1SkamilATF_TC_HEAD(syscall1, tc)
56931.1Skamil{
56941.1Skamil	atf_tc_set_md_var(tc, "descr",
56951.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
56961.1Skamil}
56971.1Skamil
56981.1SkamilATF_TC_BODY(syscall1, tc)
56991.1Skamil{
57001.1Skamil	const int exitval = 5;
57011.1Skamil	const int sigval = SIGSTOP;
57021.1Skamil	pid_t child, wpid;
57031.1Skamil#if defined(TWAIT_HAVE_STATUS)
57041.1Skamil	int status;
57051.1Skamil#endif
57061.1Skamil	struct ptrace_siginfo info;
57071.1Skamil	memset(&info, 0, sizeof(info));
57081.1Skamil
57091.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57101.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57111.1Skamil	if (child == 0) {
57121.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57131.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57141.1Skamil
57151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57171.1Skamil
57181.1Skamil		syscall(SYS_getpid);
57191.1Skamil
57201.13Schristos		DPRINTF("Before exiting of the child process\n");
57211.1Skamil		_exit(exitval);
57221.1Skamil	}
57231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57241.1Skamil
57251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57271.1Skamil
57281.1Skamil	validate_status_stopped(status, sigval);
57291.1Skamil
57301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57311.1Skamil	    "without signal to be sent\n");
57321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
57331.1Skamil
57341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57361.1Skamil
57371.1Skamil	validate_status_stopped(status, SIGTRAP);
57381.1Skamil
57391.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
57401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
57411.1Skamil
57421.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
57431.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
57441.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
57451.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
57461.1Skamil
57471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57481.1Skamil	    "without signal to be sent\n");
57491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
57501.1Skamil
57511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57531.1Skamil
57541.1Skamil	validate_status_stopped(status, SIGTRAP);
57551.1Skamil
57561.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
57571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
57581.1Skamil
57591.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
57601.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
57611.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
57621.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
57631.1Skamil
57641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57651.1Skamil	    "without signal to be sent\n");
57661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57671.1Skamil
57681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57701.1Skamil
57711.1Skamil	validate_status_exited(status, exitval);
57721.1Skamil
57731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57751.1Skamil}
57761.1Skamil
57771.1SkamilATF_TC(syscallemu1);
57781.1SkamilATF_TC_HEAD(syscallemu1, tc)
57791.1Skamil{
57801.1Skamil	atf_tc_set_md_var(tc, "descr",
57811.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
57821.1Skamil}
57831.1Skamil
57841.1SkamilATF_TC_BODY(syscallemu1, tc)
57851.1Skamil{
57861.1Skamil	const int exitval = 5;
57871.1Skamil	const int sigval = SIGSTOP;
57881.1Skamil	pid_t child, wpid;
57891.1Skamil#if defined(TWAIT_HAVE_STATUS)
57901.1Skamil	int status;
57911.1Skamil#endif
57921.1Skamil
57931.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
57941.6Skamil	/* syscallemu does not work on sparc (32-bit) */
57951.6Skamil	atf_tc_expect_fail("PR kern/52166");
57961.6Skamil#endif
57971.6Skamil
57981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58001.1Skamil	if (child == 0) {
58011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58031.1Skamil
58041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58061.1Skamil
58071.1Skamil		syscall(SYS_exit, 100);
58081.1Skamil
58091.13Schristos		DPRINTF("Before exiting of the child process\n");
58101.1Skamil		_exit(exitval);
58111.1Skamil	}
58121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58131.1Skamil
58141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58161.1Skamil
58171.1Skamil	validate_status_stopped(status, sigval);
58181.1Skamil
58191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58201.1Skamil	    "without signal to be sent\n");
58211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
58221.1Skamil
58231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58251.1Skamil
58261.1Skamil	validate_status_stopped(status, SIGTRAP);
58271.1Skamil
58281.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
58291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
58301.1Skamil
58311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58321.1Skamil	    "without signal to be sent\n");
58331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
58341.1Skamil
58351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58371.1Skamil
58381.1Skamil	validate_status_stopped(status, SIGTRAP);
58391.1Skamil
58401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58411.1Skamil	    "without signal to be sent\n");
58421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58431.1Skamil
58441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58461.1Skamil
58471.1Skamil	validate_status_exited(status, exitval);
58481.1Skamil
58491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58511.1Skamil}
58521.1Skamil
58531.1Skamil#include "t_ptrace_amd64_wait.h"
58541.1Skamil#include "t_ptrace_i386_wait.h"
58551.1Skamil#include "t_ptrace_x86_wait.h"
58561.1Skamil
58571.1SkamilATF_TP_ADD_TCS(tp)
58581.1Skamil{
58591.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
58601.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
58611.33Skamil
58621.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
58631.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
58641.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
58651.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
58661.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
58671.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
58681.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
58691.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
58701.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
58711.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
58721.33Skamil
58731.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
58741.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
58751.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
58761.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
58771.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
58781.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
58791.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
58801.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
58811.87Skamil
58821.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
58831.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
58841.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
58851.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
58861.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
58871.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
58881.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
58891.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
58901.86Skamil
58911.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
58921.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
58931.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
58941.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
58951.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
58961.59Skamil
58971.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
58981.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
58991.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
59001.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
59011.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
59021.88Skamil
59031.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
59041.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
59051.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
59061.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
59071.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
59081.88Skamil
59091.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
59101.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
59111.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
59121.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
59131.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
59141.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
59151.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
59161.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
59171.50Skamil
59181.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
59191.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
59201.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
59211.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
59221.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
59231.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
59241.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
59251.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
59261.50Skamil
59271.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
59281.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
59291.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
59301.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
59311.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
59321.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
59331.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
59341.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
59351.50Skamil
59361.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
59371.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
59381.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
59391.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
59401.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
59411.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
59421.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
59431.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
59441.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
59451.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
59461.1Skamil
59471.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
59481.37Skamil
59491.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
59501.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
59511.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
59521.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
59531.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
59541.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
59551.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
59561.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
59571.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
59581.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
59591.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
59601.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
59611.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
59621.40Skamil
59631.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
59641.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
59651.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
59661.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
59671.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
59681.41Skamil
59691.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
59701.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
59711.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
59721.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
59731.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
59741.92Skamil
59751.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
59761.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
59771.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
59781.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
59791.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
59801.92Skamil
59811.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
59821.43Skamil
59831.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
59841.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
59851.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
59861.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
59871.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
59881.59Skamil
59891.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
59901.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
59911.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
59921.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
59931.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
59941.51Skamil
59951.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
59961.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
59971.51Skamil
59981.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
59991.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
60001.51Skamil
60011.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
60021.51Skamil		tracee_sees_its_original_parent_getppid);
60031.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
60041.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
60051.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
60061.51Skamil		tracee_sees_its_original_parent_procfs_status);
60071.1Skamil
60081.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
60091.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
60101.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
60111.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
60121.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
60131.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
60141.1Skamil
60151.31Skamil	ATF_TP_ADD_TC(tp, fork1);
60161.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
60171.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
60181.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
60191.31Skamil	ATF_TP_ADD_TC(tp, fork5);
60201.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
60211.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
60221.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
60231.31Skamil
60241.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
60251.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
60261.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
60271.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
60281.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
60291.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
60301.64Smartin// thes tests hang on SMP machines, disable them for now
60311.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
60321.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
60331.1Skamil
60341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
60351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
60361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
60371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
60381.54Skamil
60391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
60401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
60411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
60421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
60431.54Skamil
60441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
60451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
60461.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
60471.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
60481.54Skamil
60491.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
60501.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
60511.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
60521.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
60531.54Skamil
60541.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
60551.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
60561.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
60571.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
60581.54Skamil
60591.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
60601.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
60611.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
60621.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
60631.54Skamil
60641.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
60651.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
60661.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
60671.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
60681.54Skamil
60691.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
60701.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
60711.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
60721.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
60731.54Skamil
60741.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
60751.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
60761.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
60771.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
60781.54Skamil
60791.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
60801.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
60811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
60821.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
60831.1Skamil
60841.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
60851.1Skamil
60861.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
60871.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
60881.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
60891.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
60901.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
60911.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
60921.1Skamil
60931.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
60941.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
60951.1Skamil
60961.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
60971.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
60981.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
60991.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
61001.1Skamil
61011.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
61021.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
61031.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
61041.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
61051.2Skamil
61061.1Skamil	ATF_TP_ADD_TC(tp, kill1);
61071.1Skamil	ATF_TP_ADD_TC(tp, kill2);
61081.75Skamil	ATF_TP_ADD_TC(tp, kill3);
61091.1Skamil
61101.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
61111.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
61121.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
61131.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
61141.77Skamil
61151.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
61161.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
61171.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
61181.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
61191.1Skamil
61201.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
61211.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
61221.79Skamil
61231.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
61241.1Skamil
61251.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
61261.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
61271.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
61281.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
61291.1Skamil
61301.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
61311.84Skamil
61321.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
61331.1Skamil	ATF_TP_ADD_TC(tp, signal5);
61341.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
61351.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
61361.1Skamil	ATF_TP_ADD_TC(tp, signal8);
61371.1Skamil	ATF_TP_ADD_TC(tp, signal9);
61381.1Skamil	ATF_TP_ADD_TC(tp, signal10);
61391.1Skamil
61401.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
61411.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
61421.1Skamil
61431.1Skamil	ATF_TP_ADD_TC(tp, resume1);
61441.1Skamil
61451.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
61461.1Skamil
61471.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
61481.1Skamil
61491.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
61501.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
61511.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
61521.1Skamil
61531.1Skamil	return atf_no_error();
61541.1Skamil}
6155