t_ptrace_wait.c revision 1.101
11.101Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.101 2019/03/28 08:13:40 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.101Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.101 2019/03/28 08:13:40 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.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5381.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5391.88Skamil	if (child == 0) {
5401.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5411.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5421.88Skamil
5431.88Skamil		sigemptyset(&intmask);
5441.88Skamil		sigaddset(&intmask, sig);
5451.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5461.88Skamil
5471.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5481.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5491.89Skamil
5501.88Skamil		DPRINTF("Before executing a trap\n");
5511.88Skamil		switch (sig) {
5521.88Skamil		case SIGTRAP:
5531.88Skamil			trigger_trap();
5541.88Skamil			break;
5551.88Skamil		case SIGSEGV:
5561.88Skamil			trigger_segv();
5571.88Skamil			break;
5581.88Skamil		case SIGILL:
5591.88Skamil			trigger_ill();
5601.88Skamil			break;
5611.88Skamil		case SIGFPE:
5621.88Skamil			trigger_fpe();
5631.88Skamil			break;
5641.88Skamil		case SIGBUS:
5651.88Skamil			trigger_bus();
5661.88Skamil			break;
5671.88Skamil		default:
5681.88Skamil			/* NOTREACHED */
5691.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5701.88Skamil		}
5711.88Skamil
5721.88Skamil		/* NOTREACHED */
5731.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5741.88Skamil	}
5751.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5761.88Skamil
5771.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5781.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5791.88Skamil
5801.89Skamil	validate_status_stopped(status, sigval);
5811.89Skamil
5821.89Skamil	name[0] = CTL_KERN,
5831.89Skamil	name[1] = KERN_PROC2,
5841.89Skamil	name[2] = KERN_PROC_PID;
5851.89Skamil	name[3] = child;
5861.89Skamil	name[4] = sizeof(kp);
5871.89Skamil	name[5] = 1;
5881.89Skamil
5891.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
5901.89Skamil
5911.89Skamil	kp_sigmask = kp.p_sigmask;
5921.89Skamil
5931.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5941.89Skamil	SYSCALL_REQUIRE(
5951.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5961.89Skamil
5971.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5981.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5991.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6001.89Skamil	    info.psi_siginfo.si_errno);
6011.89Skamil
6021.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6031.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6041.89Skamil
6051.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6061.89Skamil	    "without signal to be sent\n");
6071.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6081.89Skamil
6091.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6101.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6111.89Skamil
6121.88Skamil	validate_status_stopped(status, sig);
6131.88Skamil
6141.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6151.88Skamil	SYSCALL_REQUIRE(
6161.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6171.88Skamil
6181.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6191.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6201.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6211.88Skamil	    info.psi_siginfo.si_errno);
6221.88Skamil
6231.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6241.89Skamil
6251.89Skamil	DPRINTF("kp_sigmask="
6261.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6271.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6281.89Skamil	    kp_sigmask.__bits[3]);
6291.89Skamil
6301.89Skamil	DPRINTF("kp.p_sigmask="
6311.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6321.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6331.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6341.89Skamil
6351.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6361.89Skamil
6371.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6381.88Skamil	switch (sig) {
6391.88Skamil	case SIGTRAP:
6401.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6411.88Skamil		break;
6421.88Skamil	case SIGSEGV:
6431.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6441.88Skamil		break;
6451.88Skamil	case SIGILL:
6461.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
6471.88Skamil		break;
6481.88Skamil	case SIGFPE:
6491.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6501.88Skamil		break;
6511.88Skamil	case SIGBUS:
6521.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6531.88Skamil		break;
6541.88Skamil	}
6551.88Skamil
6561.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6571.88Skamil
6581.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6591.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6601.88Skamil
6611.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6621.88Skamil
6631.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6641.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6651.88Skamil}
6661.88Skamil
6671.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6681.88SkamilATF_TC(test);								\
6691.88SkamilATF_TC_HEAD(test, tc)							\
6701.88Skamil{									\
6711.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6721.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6731.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6741.88Skamil}									\
6751.88Skamil									\
6761.88SkamilATF_TC_BODY(test, tc)							\
6771.88Skamil{									\
6781.88Skamil									\
6791.88Skamil	traceme_signalmasked_crash(sig);				\
6801.88Skamil}
6811.88Skamil
6821.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
6831.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
6841.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
6851.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
6861.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
6871.88Skamil
6881.88Skamil/// ----------------------------------------------------------------------------
6891.88Skamil
6901.88Skamilstatic void
6911.88Skamiltraceme_signalignored_crash(int sig)
6921.88Skamil{
6931.90Skamil	const int sigval = SIGSTOP;
6941.88Skamil	pid_t child, wpid;
6951.88Skamil#if defined(TWAIT_HAVE_STATUS)
6961.88Skamil	int status;
6971.88Skamil#endif
6981.88Skamil	struct sigaction sa;
6991.88Skamil	struct ptrace_siginfo info;
7001.90Skamil	struct kinfo_proc2 kp;
7011.90Skamil	size_t len = sizeof(kp);
7021.90Skamil
7031.90Skamil	int name[6];
7041.90Skamil	const size_t namelen = __arraycount(name);
7051.90Skamil	ki_sigset_t kp_sigignore;
7061.88Skamil
7071.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7081.88Skamil	if (sig == SIGILL)
7091.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7101.88Skamil#endif
7111.88Skamil
7121.88Skamil	memset(&info, 0, sizeof(info));
7131.88Skamil
7141.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7151.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7161.88Skamil	if (child == 0) {
7171.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7181.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7191.88Skamil
7201.88Skamil		memset(&sa, 0, sizeof(sa));
7211.88Skamil		sa.sa_handler = SIG_IGN;
7221.88Skamil		sigemptyset(&sa.sa_mask);
7231.88Skamil
7241.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7251.88Skamil
7261.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7271.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7281.90Skamil
7291.88Skamil		DPRINTF("Before executing a trap\n");
7301.88Skamil		switch (sig) {
7311.88Skamil		case SIGTRAP:
7321.88Skamil			trigger_trap();
7331.88Skamil			break;
7341.88Skamil		case SIGSEGV:
7351.88Skamil			trigger_segv();
7361.88Skamil			break;
7371.88Skamil		case SIGILL:
7381.88Skamil			trigger_ill();
7391.88Skamil			break;
7401.88Skamil		case SIGFPE:
7411.88Skamil			trigger_fpe();
7421.88Skamil			break;
7431.88Skamil		case SIGBUS:
7441.88Skamil			trigger_bus();
7451.88Skamil			break;
7461.88Skamil		default:
7471.88Skamil			/* NOTREACHED */
7481.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7491.88Skamil		}
7501.88Skamil
7511.88Skamil		/* NOTREACHED */
7521.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7531.88Skamil	}
7541.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7551.88Skamil
7561.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7571.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7581.88Skamil
7591.90Skamil	validate_status_stopped(status, sigval);
7601.90Skamil
7611.90Skamil	name[0] = CTL_KERN,
7621.90Skamil	name[1] = KERN_PROC2,
7631.90Skamil	name[2] = KERN_PROC_PID;
7641.90Skamil	name[3] = child;
7651.90Skamil	name[4] = sizeof(kp);
7661.90Skamil	name[5] = 1;
7671.90Skamil
7681.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
7691.90Skamil
7701.90Skamil	kp_sigignore = kp.p_sigignore;
7711.90Skamil
7721.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7731.90Skamil	SYSCALL_REQUIRE(
7741.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7751.90Skamil
7761.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7771.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7781.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7791.90Skamil	    info.psi_siginfo.si_errno);
7801.90Skamil
7811.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
7821.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
7831.90Skamil
7841.90Skamil	DPRINTF("Before resuming the child process where it left off and "
7851.90Skamil	    "without signal to be sent\n");
7861.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
7871.90Skamil
7881.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7891.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7901.90Skamil
7911.88Skamil	validate_status_stopped(status, sig);
7921.88Skamil
7931.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
7941.88Skamil	SYSCALL_REQUIRE(
7951.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7961.88Skamil
7971.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7981.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7991.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8001.88Skamil	    info.psi_siginfo.si_errno);
8011.88Skamil
8021.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8031.90Skamil
8041.90Skamil	DPRINTF("kp_sigignore="
8051.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8061.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8071.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8081.90Skamil
8091.90Skamil	DPRINTF("kp.p_sigignore="
8101.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8111.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8121.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8131.90Skamil
8141.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8151.90Skamil
8161.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8171.88Skamil	switch (sig) {
8181.88Skamil	case SIGTRAP:
8191.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8201.88Skamil		break;
8211.88Skamil	case SIGSEGV:
8221.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8231.88Skamil		break;
8241.88Skamil	case SIGILL:
8251.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
8261.88Skamil		break;
8271.88Skamil	case SIGFPE:
8281.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8291.88Skamil		break;
8301.88Skamil	case SIGBUS:
8311.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8321.88Skamil		break;
8331.88Skamil	}
8341.88Skamil
8351.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8361.88Skamil
8371.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8381.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8391.88Skamil
8401.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8411.88Skamil
8421.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8431.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8441.88Skamil}
8451.88Skamil
8461.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8471.88SkamilATF_TC(test);								\
8481.88SkamilATF_TC_HEAD(test, tc)							\
8491.88Skamil{									\
8501.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8511.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8521.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8531.88Skamil}									\
8541.88Skamil									\
8551.88SkamilATF_TC_BODY(test, tc)							\
8561.88Skamil{									\
8571.88Skamil									\
8581.88Skamil	traceme_signalignored_crash(sig);				\
8591.88Skamil}
8601.88Skamil
8611.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8621.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8631.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8641.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8651.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8661.88Skamil
8671.88Skamil/// ----------------------------------------------------------------------------
8681.88Skamil
8691.88Skamilstatic void
8701.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
8711.1Skamil{
8721.1Skamil	const int exitval = 5;
8731.34Skamil	const int sigval = SIGSTOP;
8741.1Skamil	pid_t child, wpid;
8751.1Skamil	struct sigaction sa;
8761.1Skamil#if defined(TWAIT_HAVE_STATUS)
8771.1Skamil	int status;
8781.1Skamil#endif
8791.61Skre	struct ptrace_siginfo info;
8801.1Skamil
8811.45Skamil	memset(&info, 0, sizeof(info));
8821.45Skamil
8831.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
8841.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
8851.1Skamil	if (child == 0) {
8861.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8871.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8881.1Skamil
8891.34Skamil		sa.sa_handler = sah;
8901.1Skamil		sa.sa_flags = SA_SIGINFO;
8911.1Skamil		sigemptyset(&sa.sa_mask);
8921.1Skamil
8931.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
8941.1Skamil
8951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
8961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
8971.1Skamil
8981.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
8991.1Skamil
9001.13Schristos		DPRINTF("Before exiting of the child process\n");
9011.1Skamil		_exit(exitval);
9021.1Skamil	}
9031.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9041.1Skamil
9051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9071.1Skamil
9081.1Skamil	validate_status_stopped(status, sigval);
9091.1Skamil
9101.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9111.61Skre	SYSCALL_REQUIRE(
9121.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9131.45Skamil
9141.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9151.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9161.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9171.45Skamil	    info.psi_siginfo.si_errno);
9181.45Skamil
9191.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9201.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9211.45Skamil
9221.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9231.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9251.1Skamil
9261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9281.1Skamil
9291.1Skamil	validate_status_exited(status, exitval);
9301.1Skamil
9311.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9331.1Skamil}
9341.1Skamil
9351.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9361.61SkreATF_TC(test);								\
9371.61SkreATF_TC_HEAD(test, tc)							\
9381.61Skre{									\
9391.61Skre	atf_tc_set_md_var(tc, "descr",					\
9401.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9411.61Skre	    "handled correctly and caught by a signal handler");	\
9421.61Skre}									\
9431.61Skre									\
9441.61Skrestatic int test##_caught = 0;						\
9451.61Skre									\
9461.61Skrestatic void								\
9471.61Skretest##_sighandler(int arg)						\
9481.61Skre{									\
9491.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9501.61Skre									\
9511.61Skre	++ test##_caught;						\
9521.61Skre}									\
9531.61Skre									\
9541.61SkreATF_TC_BODY(test, tc)							\
9551.61Skre{									\
9561.61Skre									\
9571.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9581.34Skamil}
9591.34Skamil
9601.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9611.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9621.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9631.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9641.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9651.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9661.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9671.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
9681.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
9691.34Skamil
9701.34Skamil/// ----------------------------------------------------------------------------
9711.34Skamil
9721.35Skamilstatic void
9731.50Skamiltraceme_sendsignal_masked(int sigsent)
9741.50Skamil{
9751.50Skamil	const int exitval = 5;
9761.50Skamil	const int sigval = SIGSTOP;
9771.50Skamil	pid_t child, wpid;
9781.50Skamil	sigset_t set;
9791.50Skamil#if defined(TWAIT_HAVE_STATUS)
9801.50Skamil	int status;
9811.50Skamil#endif
9821.61Skre	struct ptrace_siginfo info;
9831.50Skamil
9841.50Skamil	memset(&info, 0, sizeof(info));
9851.50Skamil
9861.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9871.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
9881.50Skamil	if (child == 0) {
9891.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9901.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9911.50Skamil
9921.50Skamil		sigemptyset(&set);
9931.50Skamil		sigaddset(&set, sigsent);
9941.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
9951.50Skamil
9961.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9971.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9981.50Skamil
9991.50Skamil		_exit(exitval);
10001.50Skamil	}
10011.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10021.50Skamil
10031.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10041.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10051.50Skamil
10061.50Skamil	validate_status_stopped(status, sigval);
10071.50Skamil
10081.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10091.61Skre	SYSCALL_REQUIRE(
10101.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10111.50Skamil
10121.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10131.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10141.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10151.50Skamil	    info.psi_siginfo.si_errno);
10161.50Skamil
10171.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10181.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10191.50Skamil
10201.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10211.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10221.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10231.50Skamil
10241.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10251.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10261.50Skamil
10271.50Skamil	validate_status_exited(status, exitval);
10281.50Skamil
10291.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10301.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10311.50Skamil}
10321.50Skamil
10331.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10341.61SkreATF_TC(test);								\
10351.61SkreATF_TC_HEAD(test, tc)							\
10361.61Skre{									\
10371.61Skre	atf_tc_set_md_var(tc, "descr",					\
10381.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10391.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10401.61Skre}									\
10411.61Skre									\
10421.61SkreATF_TC_BODY(test, tc)							\
10431.61Skre{									\
10441.61Skre									\
10451.61Skre	traceme_sendsignal_masked(sig);					\
10461.50Skamil}
10471.50Skamil
10481.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10491.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10501.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10511.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10521.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10531.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10541.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10551.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10561.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10571.50Skamil
10581.50Skamil/// ----------------------------------------------------------------------------
10591.50Skamil
10601.50Skamilstatic void
10611.50Skamiltraceme_sendsignal_ignored(int sigsent)
10621.50Skamil{
10631.50Skamil	const int exitval = 5;
10641.50Skamil	const int sigval = SIGSTOP;
10651.50Skamil	pid_t child, wpid;
10661.50Skamil	struct sigaction sa;
10671.50Skamil#if defined(TWAIT_HAVE_STATUS)
10681.50Skamil	int status;
10691.50Skamil#endif
10701.61Skre	struct ptrace_siginfo info;
10711.50Skamil
10721.50Skamil	memset(&info, 0, sizeof(info));
10731.50Skamil
10741.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10751.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10761.50Skamil	if (child == 0) {
10771.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10781.61Skre
10791.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10801.50Skamil
10811.50Skamil		memset(&sa, 0, sizeof(sa));
10821.50Skamil		sa.sa_handler = SIG_IGN;
10831.50Skamil		sigemptyset(&sa.sa_mask);
10841.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
10851.50Skamil
10861.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10871.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10881.50Skamil
10891.50Skamil		_exit(exitval);
10901.50Skamil	}
10911.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10921.50Skamil
10931.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10941.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10951.50Skamil
10961.50Skamil	validate_status_stopped(status, sigval);
10971.50Skamil
10981.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10991.61Skre	SYSCALL_REQUIRE(
11001.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11011.50Skamil
11021.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11031.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11041.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11051.50Skamil	    info.psi_siginfo.si_errno);
11061.50Skamil
11071.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11081.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11091.50Skamil
11101.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11111.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11121.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11131.50Skamil
11141.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11151.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11161.50Skamil
11171.50Skamil	validate_status_exited(status, exitval);
11181.50Skamil
11191.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11201.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11211.50Skamil}
11221.50Skamil
11231.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11241.61SkreATF_TC(test);								\
11251.61SkreATF_TC_HEAD(test, tc)							\
11261.61Skre{									\
11271.61Skre	atf_tc_set_md_var(tc, "descr",					\
11281.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11291.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11301.61Skre}									\
11311.61Skre									\
11321.61SkreATF_TC_BODY(test, tc)							\
11331.61Skre{									\
11341.61Skre									\
11351.61Skre	traceme_sendsignal_ignored(sig);				\
11361.50Skamil}
11371.50Skamil
11381.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11391.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11401.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11411.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11421.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11431.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11441.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11451.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11461.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11471.50Skamil
11481.50Skamil/// ----------------------------------------------------------------------------
11491.50Skamil
11501.50Skamilstatic void
11511.50Skamiltraceme_sendsignal_simple(int sigsent)
11521.1Skamil{
11531.35Skamil	const int sigval = SIGSTOP;
11541.35Skamil	int exitval = 0;
11551.1Skamil	pid_t child, wpid;
11561.1Skamil#if defined(TWAIT_HAVE_STATUS)
11571.1Skamil	int status;
11581.85Skamil	int expect_core;
11591.85Skamil
11601.85Skamil	switch (sigsent) {
11611.85Skamil	case SIGABRT:
11621.85Skamil	case SIGTRAP:
11631.85Skamil	case SIGBUS:
11641.85Skamil	case SIGILL:
11651.85Skamil	case SIGFPE:
11661.85Skamil	case SIGSEGV:
11671.85Skamil		expect_core = 1;
11681.85Skamil		break;
11691.85Skamil	default:
11701.85Skamil		expect_core = 0;
11711.85Skamil		break;
11721.85Skamil	}
11731.1Skamil#endif
11741.61Skre	struct ptrace_siginfo info;
11751.1Skamil
11761.45Skamil	memset(&info, 0, sizeof(info));
11771.45Skamil
11781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
11791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
11801.1Skamil	if (child == 0) {
11811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11831.1Skamil
11841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11861.1Skamil
11871.35Skamil		switch (sigsent) {
11881.35Skamil		case SIGCONT:
11891.48Skamil		case SIGSTOP:
11901.35Skamil			_exit(exitval);
11911.35Skamil		default:
11921.35Skamil			/* NOTREACHED */
11931.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
11941.35Skamil		}
11951.1Skamil	}
11961.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11971.1Skamil
11981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12001.1Skamil
12011.1Skamil	validate_status_stopped(status, sigval);
12021.1Skamil
12031.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12041.61Skre	SYSCALL_REQUIRE(
12051.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12061.45Skamil
12071.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12081.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12091.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12101.45Skamil	    info.psi_siginfo.si_errno);
12111.45Skamil
12121.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12131.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12141.45Skamil
12151.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12161.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12181.1Skamil
12191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12211.1Skamil
12221.35Skamil	switch (sigsent) {
12231.48Skamil	case SIGSTOP:
12241.48Skamil		validate_status_stopped(status, sigsent);
12251.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12261.61Skre		    "child\n");
12271.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12281.61Skre		    sizeof(info)) != -1);
12291.48Skamil
12301.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12311.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12321.61Skre		    "si_errno=%#x\n",
12331.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12341.61Skre		    info.psi_siginfo.si_errno);
12351.48Skamil
12361.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12371.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12381.48Skamil
12391.48Skamil		DPRINTF("Before resuming the child process where it left off "
12401.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12411.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12421.48Skamil
12431.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12441.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12451.61Skre		    child);
12461.48Skamil		/* FALLTHROUGH */
12471.35Skamil	case SIGCONT:
12481.35Skamil		validate_status_exited(status, exitval);
12491.35Skamil		break;
12501.35Skamil	default:
12511.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12521.35Skamil		break;
12531.35Skamil	}
12541.1Skamil
12551.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12561.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12571.1Skamil}
12581.1Skamil
12591.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12601.61SkreATF_TC(test);								\
12611.61SkreATF_TC_HEAD(test, tc)							\
12621.61Skre{									\
12631.61Skre	atf_tc_set_md_var(tc, "descr",					\
12641.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12651.61Skre	    "handled correctly in a child without a signal handler");	\
12661.61Skre}									\
12671.61Skre									\
12681.61SkreATF_TC_BODY(test, tc)							\
12691.61Skre{									\
12701.61Skre									\
12711.61Skre	traceme_sendsignal_simple(sig);					\
12721.35Skamil}
12731.35Skamil
12741.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
12751.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
12761.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
12771.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
12781.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
12791.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
12801.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
12811.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
12821.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
12831.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
12841.35Skamil
12851.35Skamil/// ----------------------------------------------------------------------------
12861.35Skamil
12871.37SkamilATF_TC(traceme_pid1_parent);
12881.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
12891.37Skamil{
12901.37Skamil	atf_tc_set_md_var(tc, "descr",
12911.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
12921.37Skamil}
12931.37Skamil
12941.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
12951.37Skamil{
12961.37Skamil	struct msg_fds parent_child;
12971.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
12981.37Skamil	pid_t child1, child2, wpid;
12991.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13001.37Skamil#if defined(TWAIT_HAVE_STATUS)
13011.37Skamil	int status;
13021.37Skamil#endif
13031.37Skamil
13041.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13051.37Skamil
13061.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13071.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13081.37Skamil	if (child1 == 0) {
13091.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13101.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13111.37Skamil		if (child2 != 0) {
13121.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13131.61Skre			    getpid(), child2);
13141.37Skamil			_exit(exitval_child1);
13151.37Skamil		}
13161.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13171.37Skamil
13181.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13191.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13201.37Skamil
13211.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13221.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13231.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13241.37Skamil
13251.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13261.37Skamil
13271.37Skamil		_exit(exitval_child2);
13281.37Skamil	}
13291.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13301.37Skamil
13311.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13321.61Skre	TWAIT_REQUIRE_SUCCESS(
13331.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13341.37Skamil
13351.37Skamil	validate_status_exited(status, exitval_child1);
13361.37Skamil
13371.37Skamil	DPRINTF("Notify that child1 is dead\n");
13381.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13391.37Skamil
13401.37Skamil	DPRINTF("Wait for exiting of child2\n");
13411.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13421.37Skamil}
13431.37Skamil
13441.37Skamil/// ----------------------------------------------------------------------------
13451.37Skamil
13461.40Skamilstatic void
13471.40Skamiltraceme_vfork_raise(int sigval)
13481.40Skamil{
13491.46Skamil	const int exitval = 5, exitval_watcher = 10;
13501.46Skamil	pid_t child, parent, watcher, wpid;
13511.46Skamil	int rv;
13521.40Skamil#if defined(TWAIT_HAVE_STATUS)
13531.40Skamil	int status;
13541.85Skamil
13551.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13561.85Skamil	volatile int expect_core;
13571.85Skamil
13581.85Skamil	switch (sigval) {
13591.85Skamil	case SIGABRT:
13601.85Skamil	case SIGTRAP:
13611.85Skamil	case SIGBUS:
13621.85Skamil	case SIGILL:
13631.85Skamil	case SIGFPE:
13641.85Skamil	case SIGSEGV:
13651.85Skamil		expect_core = 1;
13661.85Skamil		break;
13671.85Skamil	default:
13681.85Skamil		expect_core = 0;
13691.85Skamil		break;
13701.85Skamil	}
13711.40Skamil#endif
13721.40Skamil
13731.46Skamil	/*
13741.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
13751.46Skamil	 * the SIGKILL signal to it.
13761.46Skamil	 *
13771.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
13781.46Skamil	 * simpler to reparent this process to initproc and forget about it.
13791.46Skamil	 */
13801.46Skamil	if (sigval == SIGSTOP) {
13811.46Skamil		parent = getpid();
13821.46Skamil
13831.46Skamil		watcher = fork();
13841.46Skamil		ATF_REQUIRE(watcher != 1);
13851.46Skamil		if (watcher == 0) {
13861.46Skamil			/* Double fork(2) trick to reparent to initproc */
13871.46Skamil			watcher = fork();
13881.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
13891.46Skamil			if (watcher != 0)
13901.46Skamil				_exit(exitval_watcher);
13911.46Skamil
13921.46Skamil			child = await_stopped_child(parent);
13931.46Skamil
13941.46Skamil			errno = 0;
13951.46Skamil			rv = kill(child, SIGKILL);
13961.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
13971.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
13981.46Skamil
13991.46Skamil			/* This exit value will be collected by initproc */
14001.46Skamil			_exit(0);
14011.46Skamil		}
14021.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14031.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14041.61Skre		    watcher);
14051.46Skamil
14061.46Skamil		validate_status_exited(status, exitval_watcher);
14071.46Skamil
14081.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14091.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14101.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14111.46Skamil	}
14121.46Skamil
14131.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14141.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14151.40Skamil	if (child == 0) {
14161.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14171.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14181.40Skamil
14191.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14201.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14211.40Skamil
14221.40Skamil		switch (sigval) {
14231.46Skamil		case SIGSTOP:
14241.40Skamil		case SIGKILL:
14251.40Skamil		case SIGABRT:
14261.40Skamil		case SIGHUP:
14271.85Skamil		case SIGTRAP:
14281.85Skamil		case SIGBUS:
14291.85Skamil		case SIGILL:
14301.85Skamil		case SIGFPE:
14311.85Skamil		case SIGSEGV:
14321.40Skamil			/* NOTREACHED */
14331.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14341.70Smrg			__unreachable();
14351.40Skamil		default:
14361.40Skamil			DPRINTF("Before exiting of the child process\n");
14371.40Skamil			_exit(exitval);
14381.40Skamil		}
14391.40Skamil	}
14401.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14411.40Skamil
14421.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14431.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14441.40Skamil
14451.40Skamil	switch (sigval) {
14461.40Skamil	case SIGKILL:
14471.40Skamil	case SIGABRT:
14481.40Skamil	case SIGHUP:
14491.85Skamil	case SIGTRAP:
14501.85Skamil	case SIGBUS:
14511.85Skamil	case SIGILL:
14521.85Skamil	case SIGFPE:
14531.85Skamil	case SIGSEGV:
14541.40Skamil		validate_status_signaled(status, sigval, expect_core);
14551.40Skamil		break;
14561.40Skamil	case SIGSTOP:
14571.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14581.46Skamil		break;
14591.40Skamil	case SIGCONT:
14601.47Skamil	case SIGTSTP:
14611.47Skamil	case SIGTTIN:
14621.47Skamil	case SIGTTOU:
14631.40Skamil		validate_status_exited(status, exitval);
14641.40Skamil		break;
14651.40Skamil	default:
14661.40Skamil		/* NOTREACHED */
14671.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
14681.40Skamil		break;
14691.40Skamil	}
14701.40Skamil
14711.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14721.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14731.40Skamil}
14741.40Skamil
14751.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
14761.61SkreATF_TC(test);								\
14771.61SkreATF_TC_HEAD(test, tc)							\
14781.61Skre{									\
14791.61Skre	atf_tc_set_md_var(tc, "descr",					\
14801.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
14811.61Skre	    "vfork(2)ed child");					\
14821.61Skre}									\
14831.61Skre									\
14841.61SkreATF_TC_BODY(test, tc)							\
14851.61Skre{									\
14861.61Skre									\
14871.61Skre	traceme_vfork_raise(sig);					\
14881.40Skamil}
14891.40Skamil
14901.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
14911.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
14921.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
14931.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
14941.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
14951.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
14961.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
14971.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
14981.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
14991.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15001.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15011.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15021.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15031.40Skamil
15041.40Skamil/// ----------------------------------------------------------------------------
15051.40Skamil
15061.52Skamilstatic void
15071.52Skamiltraceme_vfork_crash(int sig)
15081.41Skamil{
15091.41Skamil	pid_t child, wpid;
15101.41Skamil#if defined(TWAIT_HAVE_STATUS)
15111.41Skamil	int status;
15121.41Skamil#endif
15131.41Skamil
15141.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15151.71Skamil	if (sig == SIGILL)
15161.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15171.71Skamil#endif
15181.71Skamil
15191.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15201.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15211.41Skamil	if (child == 0) {
15221.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15231.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15241.41Skamil
15251.52Skamil		DPRINTF("Before executing a trap\n");
15261.52Skamil		switch (sig) {
15271.52Skamil		case SIGTRAP:
15281.52Skamil			trigger_trap();
15291.52Skamil			break;
15301.52Skamil		case SIGSEGV:
15311.52Skamil			trigger_segv();
15321.52Skamil			break;
15331.52Skamil		case SIGILL:
15341.52Skamil			trigger_ill();
15351.52Skamil			break;
15361.52Skamil		case SIGFPE:
15371.52Skamil			trigger_fpe();
15381.52Skamil			break;
15391.52Skamil		case SIGBUS:
15401.52Skamil			trigger_bus();
15411.52Skamil			break;
15421.52Skamil		default:
15431.52Skamil			/* NOTREACHED */
15441.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15451.52Skamil		}
15461.41Skamil
15471.41Skamil		/* NOTREACHED */
15481.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15491.41Skamil	}
15501.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15511.41Skamil
15521.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15531.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15541.41Skamil
15551.52Skamil	validate_status_signaled(status, sig, 1);
15561.41Skamil
15571.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15581.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15591.41Skamil}
15601.41Skamil
15611.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15621.61SkreATF_TC(test);								\
15631.61SkreATF_TC_HEAD(test, tc)							\
15641.61Skre{									\
15651.61Skre	atf_tc_set_md_var(tc, "descr",					\
15661.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
15671.61Skre	    "vfork(2)ed child");					\
15681.61Skre}									\
15691.61Skre									\
15701.61SkreATF_TC_BODY(test, tc)							\
15711.61Skre{									\
15721.61Skre									\
15731.61Skre	traceme_vfork_crash(sig);					\
15741.52Skamil}
15751.52Skamil
15761.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
15771.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
15781.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
15791.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
15801.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
15811.52Skamil
15821.41Skamil/// ----------------------------------------------------------------------------
15831.41Skamil
15841.92Skamilstatic void
15851.92Skamiltraceme_vfork_signalmasked_crash(int sig)
15861.92Skamil{
15871.92Skamil	pid_t child, wpid;
15881.92Skamil#if defined(TWAIT_HAVE_STATUS)
15891.92Skamil	int status;
15901.92Skamil#endif
15911.92Skamil	sigset_t intmask;
15921.92Skamil
15931.92Skamil#ifndef PTRACE_ILLEGAL_ASM
15941.92Skamil	if (sig == SIGILL)
15951.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15961.92Skamil#endif
15971.92Skamil
15981.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15991.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16001.92Skamil	if (child == 0) {
16011.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16021.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16031.92Skamil
16041.92Skamil		sigemptyset(&intmask);
16051.92Skamil		sigaddset(&intmask, sig);
16061.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16071.92Skamil
16081.92Skamil		DPRINTF("Before executing a trap\n");
16091.92Skamil		switch (sig) {
16101.92Skamil		case SIGTRAP:
16111.92Skamil			trigger_trap();
16121.92Skamil			break;
16131.92Skamil		case SIGSEGV:
16141.92Skamil			trigger_segv();
16151.92Skamil			break;
16161.92Skamil		case SIGILL:
16171.92Skamil			trigger_ill();
16181.92Skamil			break;
16191.92Skamil		case SIGFPE:
16201.92Skamil			trigger_fpe();
16211.92Skamil			break;
16221.92Skamil		case SIGBUS:
16231.92Skamil			trigger_bus();
16241.92Skamil			break;
16251.92Skamil		default:
16261.92Skamil			/* NOTREACHED */
16271.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16281.92Skamil		}
16291.92Skamil
16301.92Skamil		/* NOTREACHED */
16311.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16321.92Skamil	}
16331.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16341.92Skamil
16351.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16361.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16371.92Skamil
16381.92Skamil	validate_status_signaled(status, sig, 1);
16391.92Skamil
16401.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16411.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16421.92Skamil}
16431.92Skamil
16441.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16451.92SkamilATF_TC(test);								\
16461.92SkamilATF_TC_HEAD(test, tc)							\
16471.92Skamil{									\
16481.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16491.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16501.92Skamil	    "vfork(2)ed child with a masked signal");			\
16511.92Skamil}									\
16521.92Skamil									\
16531.92SkamilATF_TC_BODY(test, tc)							\
16541.92Skamil{									\
16551.92Skamil									\
16561.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16571.92Skamil}
16581.92Skamil
16591.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16601.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16611.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
16621.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
16631.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
16641.92Skamil
16651.92Skamil/// ----------------------------------------------------------------------------
16661.92Skamil
16671.92Skamilstatic void
16681.92Skamiltraceme_vfork_signalignored_crash(int sig)
16691.92Skamil{
16701.92Skamil	pid_t child, wpid;
16711.92Skamil#if defined(TWAIT_HAVE_STATUS)
16721.92Skamil	int status;
16731.92Skamil#endif
16741.92Skamil	struct sigaction sa;
16751.92Skamil
16761.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16771.92Skamil	if (sig == SIGILL)
16781.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16791.92Skamil#endif
16801.92Skamil
16811.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16821.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16831.92Skamil	if (child == 0) {
16841.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16851.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16861.92Skamil
16871.92Skamil		memset(&sa, 0, sizeof(sa));
16881.92Skamil		sa.sa_handler = SIG_IGN;
16891.92Skamil		sigemptyset(&sa.sa_mask);
16901.92Skamil
16911.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
16921.92Skamil
16931.92Skamil		DPRINTF("Before executing a trap\n");
16941.92Skamil		switch (sig) {
16951.92Skamil		case SIGTRAP:
16961.92Skamil			trigger_trap();
16971.92Skamil			break;
16981.92Skamil		case SIGSEGV:
16991.92Skamil			trigger_segv();
17001.92Skamil			break;
17011.92Skamil		case SIGILL:
17021.92Skamil			trigger_ill();
17031.92Skamil			break;
17041.92Skamil		case SIGFPE:
17051.92Skamil			trigger_fpe();
17061.92Skamil			break;
17071.92Skamil		case SIGBUS:
17081.92Skamil			trigger_bus();
17091.92Skamil			break;
17101.92Skamil		default:
17111.92Skamil			/* NOTREACHED */
17121.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17131.92Skamil		}
17141.92Skamil
17151.92Skamil		/* NOTREACHED */
17161.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17171.92Skamil	}
17181.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17191.92Skamil
17201.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17211.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17221.92Skamil
17231.92Skamil	validate_status_signaled(status, sig, 1);
17241.92Skamil
17251.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17261.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17271.92Skamil}
17281.92Skamil
17291.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17301.92SkamilATF_TC(test);								\
17311.92SkamilATF_TC_HEAD(test, tc)							\
17321.92Skamil{									\
17331.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17341.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17351.92Skamil	    "vfork(2)ed child with ignored signal");			\
17361.92Skamil}									\
17371.92Skamil									\
17381.92SkamilATF_TC_BODY(test, tc)							\
17391.92Skamil{									\
17401.92Skamil									\
17411.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17421.92Skamil}
17431.92Skamil
17441.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17451.92Skamil    SIGTRAP)
17461.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17471.92Skamil    SIGSEGV)
17481.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17491.92Skamil    SIGILL)
17501.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17511.92Skamil    SIGFPE)
17521.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17531.92Skamil    SIGBUS)
17541.92Skamil
17551.92Skamil/// ----------------------------------------------------------------------------
17561.92Skamil
17571.96Skamilstatic void
17581.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
17591.43Skamil{
17601.43Skamil	const int sigval = SIGTRAP;
17611.43Skamil	pid_t child, wpid;
17621.43Skamil#if defined(TWAIT_HAVE_STATUS)
17631.43Skamil	int status;
17641.43Skamil#endif
17651.96Skamil	struct sigaction sa;
17661.61Skre	struct ptrace_siginfo info;
17671.96Skamil	sigset_t intmask;
17681.96Skamil	struct kinfo_proc2 kp;
17691.96Skamil	size_t len = sizeof(kp);
17701.96Skamil
17711.96Skamil	int name[6];
17721.96Skamil	const size_t namelen = __arraycount(name);
17731.96Skamil	ki_sigset_t kp_sigmask;
17741.96Skamil	ki_sigset_t kp_sigignore;
17751.43Skamil
17761.43Skamil	memset(&info, 0, sizeof(info));
17771.43Skamil
17781.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17791.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17801.43Skamil	if (child == 0) {
17811.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17821.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17831.43Skamil
17841.96Skamil		if (masked) {
17851.96Skamil			sigemptyset(&intmask);
17861.96Skamil			sigaddset(&intmask, sigval);
17871.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
17881.96Skamil		}
17891.96Skamil
17901.96Skamil		if (ignored) {
17911.96Skamil			memset(&sa, 0, sizeof(sa));
17921.96Skamil			sa.sa_handler = SIG_IGN;
17931.96Skamil			sigemptyset(&sa.sa_mask);
17941.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
17951.96Skamil		}
17961.96Skamil
17971.43Skamil		DPRINTF("Before calling execve(2) from child\n");
17981.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
17991.43Skamil
18001.43Skamil		/* NOTREACHED */
18011.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18021.43Skamil	}
18031.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18041.43Skamil
18051.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18061.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18071.43Skamil
18081.43Skamil	validate_status_stopped(status, sigval);
18091.43Skamil
18101.96Skamil	name[0] = CTL_KERN,
18111.96Skamil	name[1] = KERN_PROC2,
18121.96Skamil	name[2] = KERN_PROC_PID;
18131.96Skamil	name[3] = getpid();
18141.96Skamil	name[4] = sizeof(kp);
18151.96Skamil	name[5] = 1;
18161.96Skamil
18171.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18181.96Skamil
18191.96Skamil	if (masked)
18201.96Skamil		kp_sigmask = kp.p_sigmask;
18211.96Skamil
18221.96Skamil	if (ignored)
18231.96Skamil		kp_sigignore = kp.p_sigignore;
18241.96Skamil
18251.96Skamil	name[3] = getpid();
18261.96Skamil
18271.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18281.96Skamil
18291.96Skamil	if (masked) {
18301.96Skamil		DPRINTF("kp_sigmask="
18311.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18321.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18331.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18341.96Skamil
18351.96Skamil	        DPRINTF("kp.p_sigmask="
18361.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18371.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18381.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18391.96Skamil
18401.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18411.96Skamil		    sizeof(kp_sigmask)));
18421.96Skamil	}
18431.96Skamil
18441.96Skamil	if (ignored) {
18451.96Skamil		DPRINTF("kp_sigignore="
18461.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18471.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18481.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18491.96Skamil
18501.96Skamil	        DPRINTF("kp.p_sigignore="
18511.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18521.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
18531.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
18541.96Skamil
18551.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
18561.96Skamil		    sizeof(kp_sigignore)));
18571.96Skamil	}
18581.96Skamil
18591.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
18601.61Skre	SYSCALL_REQUIRE(
18611.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
18621.43Skamil
18631.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
18641.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
18651.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
18661.43Skamil	    info.psi_siginfo.si_errno);
18671.43Skamil
18681.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
18691.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
18701.43Skamil
18711.43Skamil	DPRINTF("Before resuming the child process where it left off and "
18721.43Skamil	    "without signal to be sent\n");
18731.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18741.43Skamil
18751.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18761.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18771.43Skamil
18781.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18791.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18801.43Skamil}
18811.43Skamil
18821.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
18831.96SkamilATF_TC(test);								\
18841.96SkamilATF_TC_HEAD(test, tc)							\
18851.96Skamil{									\
18861.96Skamil	atf_tc_set_md_var(tc, "descr",					\
18871.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
18881.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
18891.96Skamil	    masked ? " with ignored signal" : "");			\
18901.96Skamil}									\
18911.96Skamil									\
18921.96SkamilATF_TC_BODY(test, tc)							\
18931.96Skamil{									\
18941.96Skamil									\
18951.96Skamil	traceme_vfork_exec(masked, ignored);				\
18961.96Skamil}
18971.96Skamil
18981.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
18991.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19001.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19011.96Skamil
19021.43Skamil/// ----------------------------------------------------------------------------
19031.43Skamil
19041.1Skamil#if defined(TWAIT_HAVE_PID)
19051.51Skamilstatic void
19061.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19071.59Skamil{
19081.94Skamil	const int sigval = SIGSTOP;
19091.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19101.59Skamil	const int exitval = 10;
19111.59Skamil	pid_t tracee, tracer, wpid;
19121.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19131.59Skamil#if defined(TWAIT_HAVE_STATUS)
19141.59Skamil	int status;
19151.59Skamil#endif
19161.94Skamil	struct sigaction sa;
19171.59Skamil	struct ptrace_siginfo info;
19181.94Skamil	sigset_t intmask;
19191.94Skamil	struct kinfo_proc2 kp;
19201.94Skamil	size_t len = sizeof(kp);
19211.94Skamil
19221.94Skamil	int name[6];
19231.94Skamil	const size_t namelen = __arraycount(name);
19241.94Skamil	ki_sigset_t kp_sigmask;
19251.94Skamil	ki_sigset_t kp_sigignore;
19261.61Skre
19271.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19281.71Skamil	if (sig == SIGILL)
19291.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19301.71Skamil#endif
19311.71Skamil
19321.59Skamil	memset(&info, 0, sizeof(info));
19331.59Skamil
19341.59Skamil	DPRINTF("Spawn tracee\n");
19351.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19361.59Skamil	tracee = atf_utils_fork();
19371.59Skamil	if (tracee == 0) {
19381.59Skamil		// Wait for parent to let us crash
19391.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19401.61Skre
19411.94Skamil		if (masked) {
19421.94Skamil			sigemptyset(&intmask);
19431.94Skamil			sigaddset(&intmask, sig);
19441.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19451.94Skamil		}
19461.94Skamil
19471.94Skamil		if (ignored) {
19481.94Skamil			memset(&sa, 0, sizeof(sa));
19491.94Skamil			sa.sa_handler = SIG_IGN;
19501.94Skamil			sigemptyset(&sa.sa_mask);
19511.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
19521.94Skamil		}
19531.94Skamil
19541.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19551.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19561.94Skamil
19571.59Skamil		DPRINTF("Before executing a trap\n");
19581.59Skamil		switch (sig) {
19591.59Skamil		case SIGTRAP:
19601.59Skamil			trigger_trap();
19611.59Skamil			break;
19621.59Skamil		case SIGSEGV:
19631.59Skamil			trigger_segv();
19641.59Skamil			break;
19651.59Skamil		case SIGILL:
19661.59Skamil			trigger_ill();
19671.59Skamil			break;
19681.59Skamil		case SIGFPE:
19691.59Skamil			trigger_fpe();
19701.59Skamil			break;
19711.59Skamil		case SIGBUS:
19721.59Skamil			trigger_bus();
19731.59Skamil			break;
19741.59Skamil		default:
19751.59Skamil			/* NOTREACHED */
19761.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
19771.59Skamil		}
19781.59Skamil
19791.59Skamil		/* NOTREACHED */
19801.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
19811.59Skamil	}
19821.59Skamil
19831.59Skamil	DPRINTF("Spawn debugger\n");
19841.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
19851.59Skamil	tracer = atf_utils_fork();
19861.59Skamil	if (tracer == 0) {
19871.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
19881.59Skamil		tracer = atf_utils_fork();
19891.59Skamil		if (tracer != 0)
19901.61Skre			_exit(exitval);
19911.59Skamil
19921.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
19931.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
19941.59Skamil
19951.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
19961.59Skamil		FORKEE_REQUIRE_SUCCESS(
19971.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
19981.59Skamil
19991.59Skamil		forkee_status_stopped(status, SIGSTOP);
20001.59Skamil
20011.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20021.94Skamil		    "traced process\n");
20031.94Skamil		SYSCALL_REQUIRE(
20041.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20051.94Skamil
20061.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20071.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20081.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20091.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20101.94Skamil
20111.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20121.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20131.94Skamil
20141.59Skamil		/* Resume tracee with PT_CONTINUE */
20151.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20161.59Skamil
20171.59Skamil		/* Inform parent that tracer has attached to tracee */
20181.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20191.59Skamil
20201.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20211.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20221.59Skamil
20231.59Skamil		/* Wait for tracee and assert that it exited */
20241.59Skamil		FORKEE_REQUIRE_SUCCESS(
20251.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20261.59Skamil
20271.94Skamil		forkee_status_stopped(status, sigval);
20281.94Skamil
20291.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20301.94Skamil		    "traced process\n");
20311.94Skamil		SYSCALL_REQUIRE(
20321.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20331.94Skamil
20341.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20351.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20361.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20371.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20381.94Skamil
20391.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20401.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20411.94Skamil
20421.94Skamil		name[0] = CTL_KERN,
20431.94Skamil		name[1] = KERN_PROC2,
20441.94Skamil		name[2] = KERN_PROC_PID;
20451.94Skamil		name[3] = tracee;
20461.94Skamil		name[4] = sizeof(kp);
20471.94Skamil		name[5] = 1;
20481.94Skamil
20491.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20501.94Skamil
20511.94Skamil		if (masked)
20521.94Skamil			kp_sigmask = kp.p_sigmask;
20531.94Skamil
20541.94Skamil		if (ignored)
20551.94Skamil			kp_sigignore = kp.p_sigignore;
20561.94Skamil
20571.94Skamil		/* Resume tracee with PT_CONTINUE */
20581.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20591.94Skamil
20601.94Skamil		/* Wait for tracee and assert that it exited */
20611.94Skamil		FORKEE_REQUIRE_SUCCESS(
20621.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20631.94Skamil
20641.93Skamil		forkee_status_stopped(status, sig);
20651.59Skamil
20661.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20671.61Skre		    "traced process\n");
20681.61Skre		SYSCALL_REQUIRE(
20691.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20701.59Skamil
20711.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20721.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20731.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20741.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20751.59Skamil
20761.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
20771.94Skamil
20781.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20791.94Skamil
20801.94Skamil		if (masked) {
20811.94Skamil			DPRINTF("kp_sigmask="
20821.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
20831.94Skamil			    PRIx32 "\n",
20841.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
20851.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
20861.94Skamil
20871.94Skamil			DPRINTF("kp.p_sigmask="
20881.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
20891.94Skamil			    PRIx32 "\n",
20901.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
20911.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
20921.94Skamil
20931.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
20941.94Skamil			    sizeof(kp_sigmask)));
20951.94Skamil		}
20961.94Skamil
20971.94Skamil		if (ignored) {
20981.94Skamil			DPRINTF("kp_sigignore="
20991.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21001.94Skamil			    PRIx32 "\n",
21011.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21021.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21031.94Skamil
21041.94Skamil			DPRINTF("kp.p_sigignore="
21051.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21061.94Skamil			    PRIx32 "\n",
21071.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21081.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21091.94Skamil
21101.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21111.94Skamil			    sizeof(kp_sigignore)));
21121.94Skamil		}
21131.94Skamil
21141.59Skamil		switch (sig) {
21151.59Skamil		case SIGTRAP:
21161.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21171.59Skamil			break;
21181.59Skamil		case SIGSEGV:
21191.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21201.59Skamil			break;
21211.71Skamil		case SIGILL:
21221.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
21231.71Skamil			break;
21241.59Skamil		case SIGFPE:
21251.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21261.59Skamil			break;
21271.59Skamil		case SIGBUS:
21281.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21291.59Skamil			break;
21301.59Skamil		}
21311.59Skamil
21321.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21331.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21341.93Skamil		FORKEE_REQUIRE_SUCCESS(
21351.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21361.59Skamil
21371.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21381.59Skamil
21391.71Skamil		/* Inform parent that tracer is exiting normally */
21401.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21411.71Skamil
21421.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21431.59Skamil		_exit(0 /* collect by initproc */);
21441.59Skamil	}
21451.59Skamil
21461.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21471.59Skamil	    "calling %s()\n", TWAIT_FNAME);
21481.59Skamil	TWAIT_REQUIRE_SUCCESS(
21491.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21501.59Skamil
21511.59Skamil	validate_status_exited(status, exitval);
21521.59Skamil
21531.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
21541.59Skamil	    TWAIT_FNAME);
21551.59Skamil	TWAIT_REQUIRE_SUCCESS(
21561.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
21571.59Skamil
21581.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
21591.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
21601.59Skamil
21611.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
21621.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
21631.59Skamil
21641.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
21651.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
21661.59Skamil
21671.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
21681.59Skamil	    TWAIT_FNAME);
21691.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21701.59Skamil
21711.59Skamil	validate_status_signaled(status, SIGKILL, 0);
21721.59Skamil
21731.71Skamil	DPRINTF("Await normal exit of tracer\n");
21741.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
21751.71Skamil
21761.59Skamil	msg_close(&parent_tracer);
21771.59Skamil	msg_close(&parent_tracee);
21781.59Skamil}
21791.59Skamil
21801.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
21811.61SkreATF_TC(test);								\
21821.61SkreATF_TC_HEAD(test, tc)							\
21831.61Skre{									\
21841.61Skre	atf_tc_set_md_var(tc, "descr",					\
21851.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
21861.94Skamil	    "the debuggee");						\
21871.61Skre}									\
21881.61Skre									\
21891.61SkreATF_TC_BODY(test, tc)							\
21901.61Skre{									\
21911.61Skre									\
21921.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
21931.59Skamil}
21941.59Skamil
21951.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
21961.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
21971.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
21981.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
21991.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22001.94Skamil
22011.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22021.94SkamilATF_TC(test);								\
22031.94SkamilATF_TC_HEAD(test, tc)							\
22041.94Skamil{									\
22051.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22061.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22071.94Skamil	    "the debuggee with masked signal");				\
22081.94Skamil}									\
22091.94Skamil									\
22101.94SkamilATF_TC_BODY(test, tc)							\
22111.94Skamil{									\
22121.94Skamil									\
22131.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22141.94Skamil}
22151.94Skamil
22161.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22171.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22181.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22191.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22201.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22211.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22221.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22231.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22241.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22251.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22261.94Skamil
22271.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22281.94SkamilATF_TC(test);								\
22291.94SkamilATF_TC_HEAD(test, tc)							\
22301.94Skamil{									\
22311.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22321.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22331.94Skamil	    "the debuggee with signal ignored");			\
22341.94Skamil}									\
22351.94Skamil									\
22361.94SkamilATF_TC_BODY(test, tc)							\
22371.94Skamil{									\
22381.94Skamil									\
22391.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22401.94Skamil}
22411.94Skamil
22421.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22431.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22441.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22451.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22461.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22471.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
22481.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22491.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
22501.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22511.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
22521.59Skamil#endif
22531.59Skamil
22541.59Skamil/// ----------------------------------------------------------------------------
22551.59Skamil
22561.59Skamil#if defined(TWAIT_HAVE_PID)
22571.59Skamilstatic void
22581.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
22591.67Skamil                                             bool stopped)
22601.1Skamil{
22611.51Skamil	/*
22621.51Skamil	 * notimeout - disable timeout in await zombie function
22631.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
22641.67Skamil	 * stopped - attach to a stopped process
22651.51Skamil	 */
22661.1Skamil
22671.1Skamil	struct msg_fds parent_tracee, parent_tracer;
22681.1Skamil	const int exitval_tracee = 5;
22691.1Skamil	const int exitval_tracer = 10;
22701.1Skamil	pid_t tracee, tracer, wpid;
22711.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
22721.1Skamil#if defined(TWAIT_HAVE_STATUS)
22731.1Skamil	int status;
22741.1Skamil#endif
22751.1Skamil
22761.67Skamil	/*
22771.67Skamil	 * Only a subset of options are supported.
22781.67Skamil	 */
22791.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
22801.67Skamil	            (!notimeout && unrelated && !stopped) ||
22811.67Skamil	            (notimeout && !unrelated && !stopped) ||
22821.67Skamil	            (!notimeout && unrelated && stopped));
22831.67Skamil
22841.13Schristos	DPRINTF("Spawn tracee\n");
22851.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
22861.1Skamil	tracee = atf_utils_fork();
22871.1Skamil	if (tracee == 0) {
22881.67Skamil		if (stopped) {
22891.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
22901.67Skamil			raise(SIGSTOP);
22911.67Skamil		}
22921.67Skamil
22931.1Skamil		// Wait for parent to let us exit
22941.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
22951.1Skamil		_exit(exitval_tracee);
22961.1Skamil	}
22971.1Skamil
22981.13Schristos	DPRINTF("Spawn debugger\n");
22991.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23001.1Skamil	tracer = atf_utils_fork();
23011.1Skamil	if (tracer == 0) {
23021.51Skamil		if(unrelated) {
23031.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23041.51Skamil			tracer = atf_utils_fork();
23051.51Skamil			if (tracer != 0)
23061.51Skamil				_exit(exitval_tracer);
23071.51Skamil		}
23081.51Skamil
23091.67Skamil		if (stopped) {
23101.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23111.67Skamil			await_stopped(tracee);
23121.67Skamil		}
23131.67Skamil
23141.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23151.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23161.1Skamil
23171.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23181.1Skamil		FORKEE_REQUIRE_SUCCESS(
23191.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23201.1Skamil
23211.1Skamil		forkee_status_stopped(status, SIGSTOP);
23221.1Skamil
23231.1Skamil		/* Resume tracee with PT_CONTINUE */
23241.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23251.1Skamil
23261.1Skamil		/* Inform parent that tracer has attached to tracee */
23271.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23281.1Skamil
23291.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23301.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23311.1Skamil
23321.1Skamil		/* Wait for tracee and assert that it exited */
23331.1Skamil		FORKEE_REQUIRE_SUCCESS(
23341.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23351.1Skamil
23361.1Skamil		forkee_status_exited(status, exitval_tracee);
23371.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23381.1Skamil
23391.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23401.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23411.51Skamil	}
23421.51Skamil
23431.51Skamil	if (unrelated) {
23441.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23451.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23461.51Skamil		TWAIT_REQUIRE_SUCCESS(
23471.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23481.51Skamil
23491.51Skamil		validate_status_exited(status, exitval_tracer);
23501.51Skamil
23511.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
23521.51Skamil		    TWAIT_FNAME);
23531.51Skamil		TWAIT_REQUIRE_SUCCESS(
23541.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
23551.1Skamil	}
23561.1Skamil
23571.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
23581.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
23591.1Skamil
23601.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
23611.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
23621.1Skamil
23631.13Schristos	DPRINTF("Detect that tracee is zombie\n");
23641.51Skamil	if (notimeout)
23651.26Skamil		await_zombie_raw(tracee, 0);
23661.26Skamil	else
23671.26Skamil		await_zombie(tracee);
23681.1Skamil
23691.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
23701.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
23711.1Skamil	    TWAIT_FNAME);
23721.1Skamil	TWAIT_REQUIRE_SUCCESS(
23731.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
23741.1Skamil
23751.51Skamil	if (unrelated) {
23761.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
23771.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
23781.51Skamil	} else {
23791.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
23801.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
23811.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
23821.59Skamil			"%s()\n", TWAIT_FNAME);
23831.51Skamil
23841.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
23851.59Skamil			"tracee\n");
23861.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
23871.51Skamil		    tracer);
23881.1Skamil
23891.51Skamil		validate_status_exited(status, exitval_tracer);
23901.51Skamil	}
23911.1Skamil
23921.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
23931.1Skamil	    TWAIT_FNAME);
23941.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23951.1Skamil
23961.1Skamil	validate_status_exited(status, exitval_tracee);
23971.1Skamil
23981.1Skamil	msg_close(&parent_tracer);
23991.1Skamil	msg_close(&parent_tracee);
24001.1Skamil}
24011.26Skamil
24021.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24031.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24041.51Skamil{
24051.51Skamil	atf_tc_set_md_var(tc, "descr",
24061.51Skamil	    "Assert that tracer sees process termination before the parent");
24071.51Skamil}
24081.51Skamil
24091.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24101.26Skamil{
24111.26Skamil
24121.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24131.26Skamil}
24141.26Skamil
24151.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24161.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24171.1Skamil{
24181.1Skamil	atf_tc_set_md_var(tc, "descr",
24191.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24201.51Skamil	    "process and no other error is reported");
24211.1Skamil}
24221.1Skamil
24231.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24241.1Skamil{
24251.51Skamil	time_t start, end;
24261.51Skamil	double diff;
24271.51Skamil	unsigned long N = 0;
24281.1Skamil
24291.51Skamil	/*
24301.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24311.51Skamil	 * This test body isn't specific to this race, however it's just good
24321.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24331.51Skamil	 */
24341.1Skamil
24351.51Skamil	start = time(NULL);
24361.51Skamil	while (true) {
24371.51Skamil		DPRINTF("Step: %lu\n", N);
24381.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24391.67Skamil		                                             false);
24401.51Skamil		end = time(NULL);
24411.51Skamil		diff = difftime(end, start);
24421.51Skamil		if (diff >= 5.0)
24431.51Skamil			break;
24441.51Skamil		++N;
24451.1Skamil	}
24461.51Skamil	DPRINTF("Iterations: %lu\n", N);
24471.51Skamil}
24481.1Skamil
24491.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
24501.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24511.51Skamil{
24521.51Skamil	atf_tc_set_md_var(tc, "descr",
24531.51Skamil	    "Assert that tracer sees process termination before the parent");
24541.51Skamil}
24551.1Skamil
24561.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24571.51Skamil{
24581.1Skamil
24591.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
24601.67Skamil}
24611.67Skamil
24621.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
24631.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
24641.67Skamil{
24651.67Skamil	atf_tc_set_md_var(tc, "descr",
24661.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
24671.67Skamil}
24681.67Skamil
24691.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
24701.67Skamil{
24711.67Skamil
24721.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
24731.1Skamil}
24741.1Skamil#endif
24751.1Skamil
24761.51Skamil/// ----------------------------------------------------------------------------
24771.51Skamil
24781.66Skamilstatic void
24791.66Skamilparent_attach_to_its_child(bool stopped)
24801.1Skamil{
24811.1Skamil	struct msg_fds parent_tracee;
24821.1Skamil	const int exitval_tracee = 5;
24831.1Skamil	pid_t tracee, wpid;
24841.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
24851.1Skamil#if defined(TWAIT_HAVE_STATUS)
24861.1Skamil	int status;
24871.1Skamil#endif
24881.1Skamil
24891.13Schristos	DPRINTF("Spawn tracee\n");
24901.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
24911.1Skamil	tracee = atf_utils_fork();
24921.1Skamil	if (tracee == 0) {
24931.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
24941.13Schristos		DPRINTF("Parent should now attach to tracee\n");
24951.1Skamil
24961.66Skamil		if (stopped) {
24971.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
24981.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
24991.66Skamil		}
25001.66Skamil
25011.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25021.1Skamil		/* Wait for message from the parent */
25031.1Skamil		_exit(exitval_tracee);
25041.1Skamil	}
25051.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25061.57Skamil
25071.66Skamil	if (stopped) {
25081.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25091.66Skamil		await_stopped(tracee);
25101.66Skamil	}
25111.66Skamil
25121.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25141.1Skamil
25151.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25161.1Skamil	    TWAIT_FNAME);
25171.1Skamil	TWAIT_REQUIRE_SUCCESS(
25181.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25191.1Skamil
25201.1Skamil	validate_status_stopped(status, SIGSTOP);
25211.1Skamil
25221.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25241.1Skamil
25251.13Schristos	DPRINTF("Let the tracee exit now\n");
25261.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25271.1Skamil
25281.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25291.1Skamil	TWAIT_REQUIRE_SUCCESS(
25301.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25311.1Skamil
25321.1Skamil	validate_status_exited(status, exitval_tracee);
25331.1Skamil
25341.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25361.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25371.1Skamil
25381.1Skamil	msg_close(&parent_tracee);
25391.1Skamil}
25401.1Skamil
25411.66SkamilATF_TC(parent_attach_to_its_child);
25421.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25431.66Skamil{
25441.66Skamil	atf_tc_set_md_var(tc, "descr",
25451.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25461.66Skamil}
25471.66Skamil
25481.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
25491.66Skamil{
25501.66Skamil
25511.66Skamil	parent_attach_to_its_child(false);
25521.66Skamil}
25531.66Skamil
25541.66SkamilATF_TC(parent_attach_to_its_stopped_child);
25551.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
25561.66Skamil{
25571.66Skamil	atf_tc_set_md_var(tc, "descr",
25581.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
25591.66Skamil}
25601.66Skamil
25611.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
25621.66Skamil{
25631.66Skamil
25641.66Skamil	parent_attach_to_its_child(true);
25651.66Skamil}
25661.66Skamil
25671.51Skamil/// ----------------------------------------------------------------------------
25681.51Skamil
25691.65Skamilstatic void
25701.65Skamilchild_attach_to_its_parent(bool stopped)
25711.1Skamil{
25721.1Skamil	struct msg_fds parent_tracee;
25731.1Skamil	const int exitval_tracer = 5;
25741.1Skamil	pid_t tracer, wpid;
25751.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25761.1Skamil#if defined(TWAIT_HAVE_STATUS)
25771.1Skamil	int status;
25781.1Skamil#endif
25791.1Skamil
25801.13Schristos	DPRINTF("Spawn tracer\n");
25811.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25821.1Skamil	tracer = atf_utils_fork();
25831.1Skamil	if (tracer == 0) {
25841.1Skamil		/* Wait for message from the parent */
25851.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25861.1Skamil
25871.65Skamil		if (stopped) {
25881.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
25891.65Skamil			        getppid());
25901.65Skamil			await_stopped(getppid());
25911.65Skamil		}
25921.65Skamil
25931.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
25941.1Skamil		    getppid());
25951.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
25961.1Skamil
25971.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
25981.1Skamil		    TWAIT_FNAME);
25991.1Skamil		FORKEE_REQUIRE_SUCCESS(
26001.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26011.1Skamil
26021.1Skamil		forkee_status_stopped(status, SIGSTOP);
26031.1Skamil
26041.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26051.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26061.1Skamil		    != -1);
26071.1Skamil
26081.1Skamil		/* Tell parent we are ready */
26091.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26101.1Skamil
26111.1Skamil		_exit(exitval_tracer);
26121.1Skamil	}
26131.1Skamil
26141.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26151.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26161.65Skamil
26171.65Skamil	if (stopped) {
26181.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26191.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26201.65Skamil	}
26211.65Skamil
26221.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26231.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26241.1Skamil
26251.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26261.1Skamil	TWAIT_REQUIRE_SUCCESS(
26271.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26281.1Skamil
26291.1Skamil	validate_status_exited(status, exitval_tracer);
26301.1Skamil
26311.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26331.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26341.1Skamil
26351.1Skamil	msg_close(&parent_tracee);
26361.1Skamil}
26371.1Skamil
26381.65SkamilATF_TC(child_attach_to_its_parent);
26391.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26401.65Skamil{
26411.65Skamil	atf_tc_set_md_var(tc, "descr",
26421.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26431.65Skamil}
26441.65Skamil
26451.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26461.65Skamil{
26471.65Skamil
26481.65Skamil	child_attach_to_its_parent(false);
26491.65Skamil}
26501.65Skamil
26511.65SkamilATF_TC(child_attach_to_its_stopped_parent);
26521.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
26531.65Skamil{
26541.65Skamil	atf_tc_set_md_var(tc, "descr",
26551.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
26561.65Skamil}
26571.65Skamil
26581.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
26591.65Skamil{
26601.65Skamil	/*
26611.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
26621.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
26631.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
26641.65Skamil	 *
26651.65Skamil	 * As a workaround spawn this test as a subprocess.
26661.65Skamil	 */
26671.65Skamil
26681.65Skamil	const int exitval = 15;
26691.65Skamil	pid_t child, wpid;
26701.65Skamil#if defined(TWAIT_HAVE_STATUS)
26711.65Skamil	int status;
26721.65Skamil#endif
26731.65Skamil
26741.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
26751.65Skamil	if (child == 0) {
26761.65Skamil		child_attach_to_its_parent(true);
26771.65Skamil		_exit(exitval);
26781.65Skamil	} else {
26791.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26801.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26811.65Skamil
26821.65Skamil		validate_status_exited(status, exitval);
26831.65Skamil
26841.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
26851.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26861.65Skamil	}
26871.65Skamil}
26881.65Skamil
26891.51Skamil/// ----------------------------------------------------------------------------
26901.51Skamil
26911.1Skamil#if defined(TWAIT_HAVE_PID)
26921.1Skamil
26931.51Skamilenum tracee_sees_its_original_parent_type {
26941.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
26951.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
26961.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
26971.51Skamil};
26981.51Skamil
26991.51Skamilstatic void
27001.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27011.1Skamil{
27021.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27031.1Skamil	const int exitval_tracee = 5;
27041.1Skamil	const int exitval_tracer = 10;
27051.1Skamil	pid_t parent, tracee, tracer, wpid;
27061.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27071.1Skamil#if defined(TWAIT_HAVE_STATUS)
27081.1Skamil	int status;
27091.1Skamil#endif
27101.51Skamil	/* sysctl(3) - kinfo_proc2 */
27111.51Skamil	int name[CTL_MAXNAME];
27121.51Skamil	struct kinfo_proc2 kp;
27131.51Skamil	size_t len = sizeof(kp);
27141.51Skamil	unsigned int namelen;
27151.51Skamil
27161.51Skamil	/* procfs - status  */
27171.51Skamil	FILE *fp;
27181.51Skamil	struct stat st;
27191.51Skamil	const char *fname = "/proc/curproc/status";
27201.51Skamil	char s_executable[MAXPATHLEN];
27211.51Skamil	int s_pid, s_ppid;
27221.51Skamil	int rv;
27231.51Skamil
27241.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27251.61Skre		SYSCALL_REQUIRE(
27261.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27271.61Skre		if (rv != 0)
27281.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27291.51Skamil	}
27301.1Skamil
27311.13Schristos	DPRINTF("Spawn tracee\n");
27321.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27331.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27341.1Skamil	tracee = atf_utils_fork();
27351.1Skamil	if (tracee == 0) {
27361.1Skamil		parent = getppid();
27371.1Skamil
27381.1Skamil		/* Emit message to the parent */
27391.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27401.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27411.1Skamil
27421.51Skamil		switch (type) {
27431.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27441.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27451.51Skamil			break;
27461.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27471.51Skamil			namelen = 0;
27481.51Skamil			name[namelen++] = CTL_KERN;
27491.51Skamil			name[namelen++] = KERN_PROC2;
27501.51Skamil			name[namelen++] = KERN_PROC_PID;
27511.51Skamil			name[namelen++] = getpid();
27521.51Skamil			name[namelen++] = len;
27531.51Skamil			name[namelen++] = 1;
27541.51Skamil
27551.61Skre			FORKEE_ASSERT_EQ(
27561.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
27571.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
27581.51Skamil			break;
27591.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
27601.51Skamil			/*
27611.51Skamil			 * Format:
27621.51Skamil			 *  EXECUTABLE PID PPID ...
27631.51Skamil			 */
27641.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
27651.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
27661.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
27671.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
27681.51Skamil			break;
27691.51Skamil		}
27701.1Skamil
27711.1Skamil		_exit(exitval_tracee);
27721.1Skamil	}
27731.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
27741.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
27751.1Skamil
27761.13Schristos	DPRINTF("Spawn debugger\n");
27771.1Skamil	tracer = atf_utils_fork();
27781.1Skamil	if (tracer == 0) {
27791.1Skamil		/* No IPC to communicate with the child */
27801.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
27811.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
27821.1Skamil
27831.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
27841.1Skamil		FORKEE_REQUIRE_SUCCESS(
27851.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
27861.1Skamil
27871.1Skamil		forkee_status_stopped(status, SIGSTOP);
27881.1Skamil
27891.1Skamil		/* Resume tracee with PT_CONTINUE */
27901.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
27911.1Skamil
27921.1Skamil		/* Inform parent that tracer has attached to tracee */
27931.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
27941.1Skamil
27951.1Skamil		/* Wait for parent to tell use that tracee should have exited */
27961.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
27971.1Skamil
27981.1Skamil		/* Wait for tracee and assert that it exited */
27991.1Skamil		FORKEE_REQUIRE_SUCCESS(
28001.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28011.1Skamil
28021.1Skamil		forkee_status_exited(status, exitval_tracee);
28031.1Skamil
28041.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28051.1Skamil		_exit(exitval_tracer);
28061.1Skamil	}
28071.1Skamil
28081.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28091.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28101.1Skamil
28111.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28121.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28131.1Skamil
28141.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28151.1Skamil	await_zombie(tracee);
28161.1Skamil
28171.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28181.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28191.1Skamil	TWAIT_REQUIRE_SUCCESS(
28201.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28211.1Skamil
28221.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28231.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28241.1Skamil
28251.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28271.1Skamil	    tracer);
28281.1Skamil
28291.1Skamil	validate_status_exited(status, exitval_tracer);
28301.1Skamil
28311.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28321.1Skamil	    TWAIT_FNAME);
28331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28341.1Skamil	    tracee);
28351.1Skamil
28361.1Skamil	validate_status_exited(status, exitval_tracee);
28371.1Skamil
28381.1Skamil	msg_close(&parent_tracer);
28391.1Skamil	msg_close(&parent_tracee);
28401.1Skamil}
28411.1Skamil
28421.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28431.61SkreATF_TC(test);								\
28441.61SkreATF_TC_HEAD(test, tc)							\
28451.61Skre{									\
28461.61Skre	atf_tc_set_md_var(tc, "descr",					\
28471.61Skre	    "Assert that tracee sees its original parent when being traced " \
28481.61Skre	    "(check " descr ")");					\
28491.61Skre}									\
28501.61Skre									\
28511.61SkreATF_TC_BODY(test, tc)							\
28521.61Skre{									\
28531.61Skre									\
28541.61Skre	tracee_sees_its_original_parent(type);				\
28551.1Skamil}
28561.1Skamil
28571.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28581.51Skamil	tracee_sees_its_original_parent_getppid,
28591.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
28601.51Skamil	"getppid(2)");
28611.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28621.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
28631.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
28641.51Skamil	"sysctl(3) and kinfo_proc2");
28651.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28661.51Skamil	tracee_sees_its_original_parent_procfs_status,
28671.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
28681.51Skamil	"the status file in procfs");
28691.1Skamil#endif
28701.1Skamil
28711.51Skamil/// ----------------------------------------------------------------------------
28721.1Skamil
28731.53Skamilstatic void
28741.53Skamileventmask_preserved(int event)
28751.1Skamil{
28761.1Skamil	const int exitval = 5;
28771.1Skamil	const int sigval = SIGSTOP;
28781.1Skamil	pid_t child, wpid;
28791.1Skamil#if defined(TWAIT_HAVE_STATUS)
28801.1Skamil	int status;
28811.1Skamil#endif
28821.1Skamil	ptrace_event_t set_event, get_event;
28831.1Skamil	const int len = sizeof(ptrace_event_t);
28841.1Skamil
28851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28871.1Skamil	if (child == 0) {
28881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28901.1Skamil
28911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28931.1Skamil
28941.13Schristos		DPRINTF("Before exiting of the child process\n");
28951.1Skamil		_exit(exitval);
28961.1Skamil	}
28971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28981.1Skamil
28991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29011.1Skamil
29021.1Skamil	validate_status_stopped(status, sigval);
29031.1Skamil
29041.53Skamil	set_event.pe_set_event = event;
29051.61Skre	SYSCALL_REQUIRE(
29061.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29071.61Skre	SYSCALL_REQUIRE(
29081.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29091.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29101.1Skamil
29111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29121.1Skamil	    "without signal to be sent\n");
29131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29141.1Skamil
29151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29171.1Skamil
29181.1Skamil	validate_status_exited(status, exitval);
29191.1Skamil
29201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29211.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29221.1Skamil}
29231.1Skamil
29241.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29251.61SkreATF_TC(test);								\
29261.61SkreATF_TC_HEAD(test, tc)							\
29271.61Skre{									\
29281.61Skre	atf_tc_set_md_var(tc, "descr",					\
29291.61Skre	    "Verify that eventmask " #event " is preserved");		\
29301.61Skre}									\
29311.61Skre									\
29321.61SkreATF_TC_BODY(test, tc)							\
29331.61Skre{									\
29341.61Skre									\
29351.61Skre	eventmask_preserved(event);					\
29361.1Skamil}
29371.1Skamil
29381.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29391.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29401.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29411.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29421.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29431.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29441.1Skamil
29451.53Skamil/// ----------------------------------------------------------------------------
29461.1Skamil
29471.28Skamilstatic void
29481.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
29491.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
29501.1Skamil{
29511.1Skamil	const int exitval = 5;
29521.1Skamil	const int exitval2 = 15;
29531.1Skamil	const int sigval = SIGSTOP;
29541.31Skamil	pid_t child, child2 = 0, wpid;
29551.1Skamil#if defined(TWAIT_HAVE_STATUS)
29561.1Skamil	int status;
29571.1Skamil#endif
29581.1Skamil	ptrace_state_t state;
29591.1Skamil	const int slen = sizeof(state);
29601.1Skamil	ptrace_event_t event;
29611.1Skamil	const int elen = sizeof(event);
29621.1Skamil
29631.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29641.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29651.1Skamil	if (child == 0) {
29661.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29671.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29681.1Skamil
29691.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29701.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29711.1Skamil
29721.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
29731.1Skamil
29741.1Skamil		if (child2 == 0)
29751.1Skamil			_exit(exitval2);
29761.1Skamil
29771.1Skamil		FORKEE_REQUIRE_SUCCESS
29781.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
29791.1Skamil
29801.1Skamil		forkee_status_exited(status, exitval2);
29811.1Skamil
29821.13Schristos		DPRINTF("Before exiting of the child process\n");
29831.1Skamil		_exit(exitval);
29841.1Skamil	}
29851.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29861.1Skamil
29871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29891.1Skamil
29901.1Skamil	validate_status_stopped(status, sigval);
29911.1Skamil
29921.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
29931.61Skre	    trackfork ? "|PTRACE_FORK" : "",
29941.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
29951.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
29961.30Skamil	event.pe_set_event = 0;
29971.30Skamil	if (trackfork)
29981.30Skamil		event.pe_set_event |= PTRACE_FORK;
29991.30Skamil	if (trackvfork)
30001.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30011.30Skamil	if (trackvforkdone)
30021.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30041.1Skamil
30051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30061.1Skamil	    "without signal to be sent\n");
30071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30081.1Skamil
30091.29Skamil#if defined(TWAIT_HAVE_PID)
30101.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30111.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30121.61Skre		    child);
30131.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30141.61Skre		    child);
30151.1Skamil
30161.29Skamil		validate_status_stopped(status, SIGTRAP);
30171.1Skamil
30181.61Skre		SYSCALL_REQUIRE(
30191.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30201.31Skamil		if (trackfork && fn == fork) {
30211.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30221.30Skamil			       PTRACE_FORK);
30231.30Skamil		}
30241.31Skamil		if (trackvfork && fn == vfork) {
30251.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30261.30Skamil			       PTRACE_VFORK);
30271.30Skamil		}
30281.29Skamil
30291.29Skamil		child2 = state.pe_other_pid;
30301.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
30311.29Skamil
30321.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
30331.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
30341.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
30351.29Skamil		    child2);
30361.1Skamil
30371.29Skamil		validate_status_stopped(status, SIGTRAP);
30381.1Skamil
30391.61Skre		SYSCALL_REQUIRE(
30401.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
30411.31Skamil		if (trackfork && fn == fork) {
30421.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30431.30Skamil			       PTRACE_FORK);
30441.30Skamil		}
30451.31Skamil		if (trackvfork && fn == vfork) {
30461.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30471.30Skamil			       PTRACE_VFORK);
30481.30Skamil		}
30491.30Skamil
30501.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
30511.29Skamil
30521.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
30531.29Skamil		    "and without signal to be sent\n");
30541.61Skre		SYSCALL_REQUIRE(
30551.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
30561.29Skamil
30571.29Skamil		DPRINTF("Before resuming the child process where it left off "
30581.61Skre		    "and without signal to be sent\n");
30591.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30601.30Skamil	}
30611.30Skamil#endif
30621.30Skamil
30631.31Skamil	if (trackvforkdone && fn == vfork) {
30641.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30651.61Skre		    child);
30661.61Skre		TWAIT_REQUIRE_SUCCESS(
30671.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
30681.30Skamil
30691.30Skamil		validate_status_stopped(status, SIGTRAP);
30701.30Skamil
30711.61Skre		SYSCALL_REQUIRE(
30721.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30731.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
30741.30Skamil
30751.30Skamil		child2 = state.pe_other_pid;
30761.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
30771.61Skre		    child2);
30781.30Skamil
30791.30Skamil		DPRINTF("Before resuming the child process where it left off "
30801.61Skre		    "and without signal to be sent\n");
30811.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30821.30Skamil	}
30831.29Skamil
30841.30Skamil#if defined(TWAIT_HAVE_PID)
30851.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30861.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
30871.61Skre		    "\n", TWAIT_FNAME);
30881.61Skre		TWAIT_REQUIRE_SUCCESS(
30891.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30901.29Skamil
30911.29Skamil		validate_status_exited(status, exitval2);
30921.29Skamil
30931.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
30941.61Skre		    "process\n", TWAIT_FNAME);
30951.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
30961.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
30971.29Skamil	}
30981.29Skamil#endif
30991.1Skamil
31001.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31011.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31031.1Skamil
31041.1Skamil	validate_status_stopped(status, SIGCHLD);
31051.1Skamil
31061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31071.1Skamil	    "without signal to be sent\n");
31081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31091.1Skamil
31101.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31111.1Skamil	    TWAIT_FNAME);
31121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31131.1Skamil
31141.1Skamil	validate_status_exited(status, exitval);
31151.1Skamil
31161.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31171.1Skamil	    TWAIT_FNAME);
31181.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31191.1Skamil}
31201.28Skamil
31211.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
31221.61SkreATF_TC(name);								\
31231.61SkreATF_TC_HEAD(name, tc)							\
31241.61Skre{									\
31251.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
31261.61Skre}									\
31271.61Skre									\
31281.61SkreATF_TC_BODY(name, tc)							\
31291.61Skre{									\
31301.61Skre									\
31311.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
31321.32Skamil}
31331.32Skamil
31341.32Skamil#define F false
31351.32Skamil#define T true
31361.32Skamil
31371.32Skamil#define F_IF__0(x)
31381.32Skamil#define F_IF__1(x) x
31391.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
31401.32Skamil#define F_IF_(x,y) F_IF__(x,y)
31411.32Skamil#define F_IF(x,y) F_IF_(x,y)
31421.32Skamil
31431.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
31441.61Skre	"Verify " #function "(2) called with 0"				\
31451.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
31461.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
31471.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
31481.61Skre	" in EVENT_MASK."						\
31491.61Skre	F_IF(dchildbit," Detach child in this test.")			\
31501.61Skre	F_IF(dparentbit," Detach parent in this test.")
31511.1Skamil
31521.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
31531.31Skamil#if defined(TWAIT_HAVE_PID)
31541.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
31551.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
31561.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
31571.31Skamil#endif
31581.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
31591.31Skamil#if defined(TWAIT_HAVE_PID)
31601.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
31611.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
31621.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
31631.31Skamil#endif
31641.1Skamil
31651.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
31661.31Skamil#if defined(TWAIT_HAVE_PID)
31671.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
31681.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
31691.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
31701.31Skamil#endif
31711.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
31721.31Skamil#if defined(TWAIT_HAVE_PID)
31731.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
31741.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
31751.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
31761.31Skamil#endif
31771.31Skamil
31781.54Skamil/// ----------------------------------------------------------------------------
31791.31Skamil
31801.54Skamilenum bytes_transfer_type {
31811.54Skamil	BYTES_TRANSFER_DATA,
31821.54Skamil	BYTES_TRANSFER_DATAIO,
31831.54Skamil	BYTES_TRANSFER_TEXT,
31841.54Skamil	BYTES_TRANSFER_TEXTIO,
31851.54Skamil	BYTES_TRANSFER_AUXV
31861.54Skamil};
31871.31Skamil
31881.54Skamilstatic int __used
31891.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
31901.54Skamil{
31911.54Skamil	int e, f, g, h;
31921.1Skamil
31931.54Skamil	a *= 4;
31941.54Skamil	b += 3;
31951.54Skamil	c -= 2;
31961.54Skamil	d /= 1;
31971.1Skamil
31981.54Skamil	e = strtol("10", NULL, 10);
31991.54Skamil	f = strtol("20", NULL, 10);
32001.54Skamil	g = strtol("30", NULL, 10);
32011.54Skamil	h = strtol("40", NULL, 10);
32021.1Skamil
32031.54Skamil	return (a + b * c - d) + (e * f - g / h);
32041.1Skamil}
32051.1Skamil
32061.54Skamilstatic void
32071.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
32081.1Skamil{
32091.1Skamil	const int exitval = 5;
32101.1Skamil	const int sigval = SIGSTOP;
32111.1Skamil	pid_t child, wpid;
32121.54Skamil	bool skip = false;
32131.1Skamil
32141.54Skamil	int lookup_me = 0;
32151.54Skamil	uint8_t lookup_me8 = 0;
32161.54Skamil	uint16_t lookup_me16 = 0;
32171.54Skamil	uint32_t lookup_me32 = 0;
32181.54Skamil	uint64_t lookup_me64 = 0;
32191.1Skamil
32201.54Skamil	int magic = 0x13579246;
32211.54Skamil	uint8_t magic8 = 0xab;
32221.54Skamil	uint16_t magic16 = 0x1234;
32231.54Skamil	uint32_t magic32 = 0x98765432;
32241.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
32251.1Skamil
32261.54Skamil	struct ptrace_io_desc io;
32271.1Skamil#if defined(TWAIT_HAVE_STATUS)
32281.1Skamil	int status;
32291.1Skamil#endif
32301.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
32311.60Skre	AuxInfo ai[513], *aip;
32321.55Schristos
32331.55Schristos	ATF_REQUIRE(size < sizeof(ai));
32341.1Skamil
32351.54Skamil	/* Prepare variables for .TEXT transfers */
32361.54Skamil	switch (type) {
32371.54Skamil	case BYTES_TRANSFER_TEXT:
32381.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
32391.54Skamil		break;
32401.54Skamil	case BYTES_TRANSFER_TEXTIO:
32411.54Skamil		switch (size) {
32421.54Skamil		case 8:
32431.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
32441.54Skamil			break;
32451.54Skamil		case 16:
32461.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
32471.54Skamil			break;
32481.54Skamil		case 32:
32491.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
32501.54Skamil			break;
32511.54Skamil		case 64:
32521.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
32531.54Skamil			break;
32541.54Skamil		}
32551.54Skamil		break;
32561.54Skamil	default:
32571.54Skamil		break;
32581.54Skamil	}
32591.1Skamil
32601.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
32611.54Skamil	switch (type) {
32621.54Skamil	case BYTES_TRANSFER_TEXTIO:
32631.54Skamil	case BYTES_TRANSFER_DATAIO:
32641.54Skamil		io.piod_op = operation;
32651.54Skamil		switch (size) {
32661.54Skamil		case 8:
32671.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
32681.54Skamil			               (void *)bytes_transfer_dummy :
32691.54Skamil			               &lookup_me8;
32701.54Skamil			io.piod_addr = &lookup_me8;
32711.54Skamil			io.piod_len = sizeof(lookup_me8);
32721.54Skamil			break;
32731.54Skamil		case 16:
32741.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
32751.54Skamil			               (void *)bytes_transfer_dummy :
32761.54Skamil			               &lookup_me16;
32771.54Skamil			io.piod_addr = &lookup_me16;
32781.54Skamil			io.piod_len = sizeof(lookup_me16);
32791.54Skamil			break;
32801.54Skamil		case 32:
32811.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
32821.54Skamil			               (void *)bytes_transfer_dummy :
32831.54Skamil			               &lookup_me32;
32841.54Skamil			io.piod_addr = &lookup_me32;
32851.54Skamil			io.piod_len = sizeof(lookup_me32);
32861.54Skamil			break;
32871.54Skamil		case 64:
32881.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
32891.54Skamil			               (void *)bytes_transfer_dummy :
32901.54Skamil			               &lookup_me64;
32911.54Skamil			io.piod_addr = &lookup_me64;
32921.54Skamil			io.piod_len = sizeof(lookup_me64);
32931.54Skamil			break;
32941.54Skamil		default:
32951.54Skamil			break;
32961.54Skamil		}
32971.54Skamil		break;
32981.54Skamil	case BYTES_TRANSFER_AUXV:
32991.54Skamil		io.piod_op = operation;
33001.54Skamil		io.piod_offs = 0;
33011.54Skamil		io.piod_addr = ai;
33021.54Skamil		io.piod_len = size;
33031.54Skamil		break;
33041.54Skamil	default:
33051.54Skamil		break;
33061.1Skamil	}
33071.1Skamil
33081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33101.1Skamil	if (child == 0) {
33111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33131.1Skamil
33141.54Skamil		switch (type) {
33151.54Skamil		case BYTES_TRANSFER_DATA:
33161.54Skamil			switch (operation) {
33171.54Skamil			case PT_READ_D:
33181.54Skamil			case PT_READ_I:
33191.54Skamil				lookup_me = magic;
33201.54Skamil				break;
33211.54Skamil			default:
33221.54Skamil				break;
33231.54Skamil			}
33241.54Skamil			break;
33251.54Skamil		case BYTES_TRANSFER_DATAIO:
33261.54Skamil			switch (operation) {
33271.54Skamil			case PIOD_READ_D:
33281.54Skamil			case PIOD_READ_I:
33291.54Skamil				switch (size) {
33301.54Skamil				case 8:
33311.54Skamil					lookup_me8 = magic8;
33321.54Skamil					break;
33331.54Skamil				case 16:
33341.54Skamil					lookup_me16 = magic16;
33351.54Skamil					break;
33361.54Skamil				case 32:
33371.54Skamil					lookup_me32 = magic32;
33381.54Skamil					break;
33391.54Skamil				case 64:
33401.54Skamil					lookup_me64 = magic64;
33411.54Skamil					break;
33421.54Skamil				default:
33431.54Skamil					break;
33441.54Skamil				}
33451.54Skamil				break;
33461.54Skamil			default:
33471.54Skamil				break;
33481.54Skamil			}
33491.54Skamil		default:
33501.54Skamil			break;
33511.54Skamil		}
33521.54Skamil
33531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33551.1Skamil
33561.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
33571.54Skamil		switch (type) {
33581.54Skamil		case BYTES_TRANSFER_DATA:
33591.54Skamil			switch (operation) {
33601.54Skamil			case PT_WRITE_D:
33611.54Skamil			case PT_WRITE_I:
33621.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
33631.54Skamil				break;
33641.54Skamil			default:
33651.54Skamil				break;
33661.54Skamil			}
33671.54Skamil			break;
33681.54Skamil		case BYTES_TRANSFER_DATAIO:
33691.54Skamil			switch (operation) {
33701.54Skamil			case PIOD_WRITE_D:
33711.54Skamil			case PIOD_WRITE_I:
33721.54Skamil				switch (size) {
33731.54Skamil				case 8:
33741.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
33751.54Skamil					break;
33761.54Skamil				case 16:
33771.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
33781.54Skamil					break;
33791.54Skamil				case 32:
33801.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
33811.54Skamil					break;
33821.54Skamil				case 64:
33831.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
33841.54Skamil					break;
33851.54Skamil				default:
33861.54Skamil					break;
33871.54Skamil				}
33881.54Skamil				break;
33891.54Skamil			default:
33901.54Skamil				break;
33911.54Skamil			}
33921.54Skamil			break;
33931.54Skamil		case BYTES_TRANSFER_TEXT:
33941.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
33951.54Skamil			                     sizeof(magic)) == 0);
33961.54Skamil			break;
33971.54Skamil		case BYTES_TRANSFER_TEXTIO:
33981.54Skamil			switch (size) {
33991.54Skamil			case 8:
34001.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
34011.54Skamil				                     bytes_transfer_dummy,
34021.54Skamil				                     sizeof(magic8)) == 0);
34031.54Skamil				break;
34041.54Skamil			case 16:
34051.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
34061.54Skamil				                     bytes_transfer_dummy,
34071.54Skamil				                     sizeof(magic16)) == 0);
34081.54Skamil				break;
34091.54Skamil			case 32:
34101.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
34111.54Skamil				                     bytes_transfer_dummy,
34121.54Skamil				                     sizeof(magic32)) == 0);
34131.54Skamil				break;
34141.54Skamil			case 64:
34151.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
34161.54Skamil				                     bytes_transfer_dummy,
34171.54Skamil				                     sizeof(magic64)) == 0);
34181.54Skamil				break;
34191.54Skamil			}
34201.54Skamil			break;
34211.54Skamil		default:
34221.54Skamil			break;
34231.54Skamil		}
34241.54Skamil
34251.13Schristos		DPRINTF("Before exiting of the child process\n");
34261.1Skamil		_exit(exitval);
34271.1Skamil	}
34281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34291.1Skamil
34301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34321.1Skamil
34331.1Skamil	validate_status_stopped(status, sigval);
34341.1Skamil
34351.54Skamil	/* Check PaX MPROTECT */
34361.54Skamil	if (!can_we_write_to_text(child)) {
34371.54Skamil		switch (type) {
34381.54Skamil		case BYTES_TRANSFER_TEXTIO:
34391.54Skamil			switch (operation) {
34401.54Skamil			case PIOD_WRITE_D:
34411.54Skamil			case PIOD_WRITE_I:
34421.54Skamil				skip = true;
34431.54Skamil				break;
34441.54Skamil			default:
34451.54Skamil				break;
34461.54Skamil			}
34471.54Skamil			break;
34481.54Skamil		case BYTES_TRANSFER_TEXT:
34491.54Skamil			switch (operation) {
34501.54Skamil			case PT_WRITE_D:
34511.54Skamil			case PT_WRITE_I:
34521.54Skamil				skip = true;
34531.54Skamil				break;
34541.54Skamil			default:
34551.54Skamil				break;
34561.54Skamil			}
34571.54Skamil			break;
34581.54Skamil		default:
34591.54Skamil			break;
34601.54Skamil		}
34611.54Skamil	}
34621.1Skamil
34631.54Skamil	/* Bailout cleanly killing the child process */
34641.54Skamil	if (skip) {
34651.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
34661.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34671.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
34681.54Skamil		                      child);
34691.1Skamil
34701.54Skamil		validate_status_signaled(status, SIGKILL, 0);
34711.1Skamil
34721.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
34731.54Skamil	}
34741.1Skamil
34751.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
34761.54Skamil	       "parent=%d\n", child, getpid());
34771.1Skamil
34781.54Skamil	switch (type) {
34791.54Skamil	case BYTES_TRANSFER_TEXTIO:
34801.54Skamil	case BYTES_TRANSFER_DATAIO:
34811.54Skamil	case BYTES_TRANSFER_AUXV:
34821.54Skamil		switch (operation) {
34831.54Skamil		case PIOD_WRITE_D:
34841.54Skamil		case PIOD_WRITE_I:
34851.54Skamil			switch (size) {
34861.54Skamil			case 8:
34871.54Skamil				lookup_me8 = magic8;
34881.54Skamil				break;
34891.54Skamil			case 16:
34901.54Skamil				lookup_me16 = magic16;
34911.54Skamil				break;
34921.54Skamil			case 32:
34931.54Skamil				lookup_me32 = magic32;
34941.54Skamil				break;
34951.54Skamil			case 64:
34961.54Skamil				lookup_me64 = magic64;
34971.54Skamil				break;
34981.54Skamil			default:
34991.54Skamil				break;
35001.54Skamil			}
35011.54Skamil			break;
35021.54Skamil		default:
35031.54Skamil			break;
35041.54Skamil		}
35051.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35061.54Skamil		switch (operation) {
35071.54Skamil		case PIOD_READ_D:
35081.54Skamil		case PIOD_READ_I:
35091.54Skamil			switch (size) {
35101.54Skamil			case 8:
35111.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
35121.54Skamil				break;
35131.54Skamil			case 16:
35141.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
35151.54Skamil				break;
35161.54Skamil			case 32:
35171.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
35181.54Skamil				break;
35191.54Skamil			case 64:
35201.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
35211.54Skamil				break;
35221.54Skamil			default:
35231.54Skamil				break;
35241.54Skamil			}
35251.54Skamil			break;
35261.54Skamil		case PIOD_READ_AUXV:
35271.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
35281.54Skamil			        io.piod_len);
35291.54Skamil			ATF_REQUIRE(io.piod_len > 0);
35301.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
35311.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
35321.54Skamil				    (long long int)aip->a_type,
35331.54Skamil				    (long long int)aip->a_v);
35341.54Skamil			break;
35351.54Skamil		default:
35361.54Skamil			break;
35371.54Skamil		}
35381.54Skamil		break;
35391.54Skamil	case BYTES_TRANSFER_TEXT:
35401.54Skamil		switch (operation) {
35411.54Skamil		case PT_READ_D:
35421.54Skamil		case PT_READ_I:
35431.54Skamil			errno = 0;
35441.54Skamil			lookup_me = ptrace(operation, child,
35451.54Skamil			                   bytes_transfer_dummy, 0);
35461.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
35471.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
35481.54Skamil			break;
35491.54Skamil		case PT_WRITE_D:
35501.54Skamil		case PT_WRITE_I:
35511.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
35521.54Skamil			                       bytes_transfer_dummy, magic)
35531.54Skamil			                != -1);
35541.54Skamil			break;
35551.54Skamil		default:
35561.54Skamil			break;
35571.54Skamil		}
35581.54Skamil		break;
35591.54Skamil	case BYTES_TRANSFER_DATA:
35601.54Skamil		switch (operation) {
35611.54Skamil		case PT_READ_D:
35621.54Skamil		case PT_READ_I:
35631.54Skamil			errno = 0;
35641.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
35651.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
35661.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
35671.54Skamil			break;
35681.54Skamil		case PT_WRITE_D:
35691.54Skamil		case PT_WRITE_I:
35701.54Skamil			lookup_me = magic;
35711.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
35721.54Skamil			                       magic) != -1);
35731.54Skamil			break;
35741.54Skamil		default:
35751.54Skamil			break;
35761.54Skamil		}
35771.54Skamil		break;
35781.54Skamil	default:
35791.54Skamil		break;
35801.54Skamil	}
35811.1Skamil
35821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35831.1Skamil	    "without signal to be sent\n");
35841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35851.1Skamil
35861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35881.1Skamil
35891.1Skamil	validate_status_exited(status, exitval);
35901.1Skamil
35911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35931.1Skamil}
35941.1Skamil
35951.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
35961.61SkreATF_TC(test);								\
35971.61SkreATF_TC_HEAD(test, tc)							\
35981.61Skre{									\
35991.61Skre	atf_tc_set_md_var(tc, "descr",					\
36001.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
36011.61Skre	    " of type " #type);						\
36021.61Skre}									\
36031.61Skre									\
36041.61SkreATF_TC_BODY(test, tc)							\
36051.61Skre{									\
36061.61Skre									\
36071.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
36081.1Skamil}
36091.1Skamil
36101.54Skamil// DATA
36111.1Skamil
36121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
36131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
36141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
36151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
36161.54Skamil
36171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
36181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
36191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
36201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
36211.54Skamil
36221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
36231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
36241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
36251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
36261.54Skamil
36271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
36281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
36291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
36301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
36311.54Skamil
36321.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
36331.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
36341.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
36351.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
36361.54Skamil
36371.54Skamil// TEXT
36381.54Skamil
36391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
36401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
36411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
36421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
36431.54Skamil
36441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
36451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
36461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
36471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
36481.54Skamil
36491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
36501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
36511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
36521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
36531.54Skamil
36541.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
36551.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
36561.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
36571.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
36581.54Skamil
36591.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
36601.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
36611.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
36621.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
36631.1Skamil
36641.54Skamil// AUXV
36651.1Skamil
36661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
36671.1Skamil
36681.54Skamil/// ----------------------------------------------------------------------------
36691.1Skamil
36701.101Skamilstatic void
36711.101Skamilbytes_transfer_alignment(const char *operation)
36721.101Skamil{
36731.101Skamil	const int exitval = 5;
36741.101Skamil	const int sigval = SIGSTOP;
36751.101Skamil	pid_t child, wpid;
36761.101Skamil#if defined(TWAIT_HAVE_STATUS)
36771.101Skamil	int status;
36781.101Skamil#endif
36791.101Skamil	char *buffer;
36801.101Skamil	int vector;
36811.101Skamil	size_t len;
36821.101Skamil	size_t i;
36831.101Skamil	int op;
36841.101Skamil
36851.101Skamil	struct ptrace_io_desc io;
36861.101Skamil	struct ptrace_siginfo info;
36871.101Skamil
36881.101Skamil	memset(&io, 0, sizeof(io));
36891.101Skamil	memset(&info, 0, sizeof(info));
36901.101Skamil
36911.101Skamil	/* Testing misaligned byte transfer crossing page boundaries */
36921.101Skamil	len = sysconf(_SC_PAGESIZE) * 2;
36931.101Skamil	buffer = malloc(len);
36941.101Skamil	ATF_REQUIRE(buffer != NULL);
36951.101Skamil
36961.101Skamil	/* Initialize the buffer with random data */
36971.101Skamil	for (i = 0; i < len; i++)
36981.101Skamil		buffer[i] = i & 0xff;
36991.101Skamil
37001.101Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
37011.101Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
37021.101Skamil	if (child == 0) {
37031.101Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37041.101Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37051.101Skamil
37061.101Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37071.101Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37081.101Skamil
37091.101Skamil		DPRINTF("Before exiting of the child process\n");
37101.101Skamil		_exit(exitval);
37111.101Skamil	}
37121.101Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37131.101Skamil
37141.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37151.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37161.101Skamil
37171.101Skamil	validate_status_stopped(status, sigval);
37181.101Skamil
37191.101Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37201.101Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
37211.101Skamil		!= -1);
37221.101Skamil
37231.101Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37241.101Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
37251.101Skamil		"si_errno=%#x\n",
37261.101Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37271.101Skamil		info.psi_siginfo.si_errno);
37281.101Skamil
37291.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
37301.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
37311.101Skamil
37321.101Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
37331.101Skamil	    strcmp(operation, "PT_READ_D") == 0) {
37341.101Skamil		if (strcmp(operation, "PT_READ_I"))
37351.101Skamil			op = PT_READ_I;
37361.101Skamil		else
37371.101Skamil			op = PT_READ_D;
37381.101Skamil
37391.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
37401.101Skamil			errno = 0;
37411.101Skamil			vector = ptrace(op, child, buffer + i, 0);
37421.101Skamil			ATF_REQUIRE_EQ(errno, 0);
37431.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
37441.101Skamil		}
37451.101Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
37461.101Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
37471.101Skamil		if (strcmp(operation, "PT_WRITE_I"))
37481.101Skamil			op = PT_WRITE_I;
37491.101Skamil		else
37501.101Skamil			op = PT_WRITE_D;
37511.101Skamil
37521.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
37531.101Skamil			memcpy(&vector, buffer + i, sizeof(int));
37541.101Skamil			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
37551.101Skamil			    != -1);
37561.101Skamil		}
37571.101Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
37581.101Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
37591.101Skamil		if (strcmp(operation, "PIOD_READ_I"))
37601.101Skamil			op = PIOD_READ_I;
37611.101Skamil		else
37621.101Skamil			op = PIOD_READ_D;
37631.101Skamil
37641.101Skamil		io.piod_op = op;
37651.101Skamil		io.piod_addr = &vector;
37661.101Skamil		io.piod_len = sizeof(int);
37671.101Skamil
37681.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
37691.101Skamil			io.piod_offs = buffer + i;
37701.101Skamil
37711.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
37721.101Skamil			                != -1);
37731.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
37741.101Skamil		}
37751.101Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
37761.101Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
37771.101Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
37781.101Skamil			op = PIOD_WRITE_I;
37791.101Skamil		else
37801.101Skamil			op = PIOD_WRITE_D;
37811.101Skamil
37821.101Skamil		io.piod_op = op;
37831.101Skamil		io.piod_addr = &vector;
37841.101Skamil		io.piod_len = sizeof(int);
37851.101Skamil
37861.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
37871.101Skamil			io.piod_offs = buffer + i;
37881.101Skamil
37891.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
37901.101Skamil			                != -1);
37911.101Skamil		}
37921.101Skamil	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
37931.101Skamil		io.piod_op = PIOD_READ_AUXV;
37941.101Skamil		io.piod_addr = &vector;
37951.101Skamil		io.piod_len = sizeof(int);
37961.101Skamil
37971.101Skamil		errno = 0;
37981.101Skamil		i = 0;
37991.101Skamil		/* Read the whole AUXV vector, it has no clear length */
38001.101Skamil		while (errno != EIO) {
38011.101Skamil			io.piod_offs = (void *)(intptr_t)i;
38021.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38031.101Skamil			                != -1 || (errno == EIO && i > 0));
38041.101Skamil			++i;
38051.101Skamil		}
38061.101Skamil	}
38071.101Skamil
38081.101Skamil	DPRINTF("Before resuming the child process where it left off "
38091.101Skamil	    "and without signal to be sent\n");
38101.101Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38111.101Skamil
38121.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38131.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
38141.101Skamil	    child);
38151.101Skamil
38161.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38171.101Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38181.101Skamil}
38191.101Skamil
38201.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
38211.101SkamilATF_TC(test);								\
38221.101SkamilATF_TC_HEAD(test, tc)							\
38231.101Skamil{									\
38241.101Skamil	atf_tc_set_md_var(tc, "descr",					\
38251.101Skamil	    "Verify bytes transfer for potentially misaligned "		\
38261.101Skamil	    "operation " operation);					\
38271.101Skamil}									\
38281.101Skamil									\
38291.101SkamilATF_TC_BODY(test, tc)							\
38301.101Skamil{									\
38311.101Skamil									\
38321.101Skamil	bytes_transfer_alignment(operation);				\
38331.101Skamil}
38341.101Skamil
38351.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
38361.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
38371.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
38381.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
38391.101Skamil
38401.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
38411.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
38421.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
38431.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
38441.101Skamil
38451.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
38461.101Skamil
38471.101Skamil/// ----------------------------------------------------------------------------
38481.101Skamil
38491.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
38501.72Skamilstatic void
38511.72Skamilaccess_regs(const char *regset, const char *aux)
38521.1Skamil{
38531.1Skamil	const int exitval = 5;
38541.1Skamil	const int sigval = SIGSTOP;
38551.1Skamil	pid_t child, wpid;
38561.1Skamil#if defined(TWAIT_HAVE_STATUS)
38571.1Skamil	int status;
38581.1Skamil#endif
38591.72Skamil#if defined(HAVE_GPREGS)
38601.72Skamil	struct reg gpr;
38611.76Sscole	register_t rgstr;
38621.1Skamil#endif
38631.72Skamil#if defined(HAVE_FPREGS)
38641.72Skamil	struct fpreg fpr;
38651.1Skamil#endif
38661.76Sscole
38671.72Skamil#if !defined(HAVE_GPREGS)
38681.72Skamil	if (strcmp(regset, "regs") == 0)
38691.72Skamil		atf_tc_fail("Impossible test scenario!");
38701.1Skamil#endif
38711.1Skamil
38721.72Skamil#if !defined(HAVE_FPREGS)
38731.72Skamil	if (strcmp(regset, "fpregs") == 0)
38741.72Skamil		atf_tc_fail("Impossible test scenario!");
38751.1Skamil#endif
38761.1Skamil
38771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38791.1Skamil	if (child == 0) {
38801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38821.1Skamil
38831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38851.1Skamil
38861.13Schristos		DPRINTF("Before exiting of the child process\n");
38871.1Skamil		_exit(exitval);
38881.1Skamil	}
38891.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38901.1Skamil
38911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38931.1Skamil
38941.1Skamil	validate_status_stopped(status, sigval);
38951.1Skamil
38961.1Skamil#if defined(HAVE_GPREGS)
38971.72Skamil	if (strcmp(regset, "regs") == 0) {
38981.72Skamil		DPRINTF("Call GETREGS for the child process\n");
38991.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
39001.72Skamil
39011.72Skamil		if (strcmp(aux, "none") == 0) {
39021.72Skamil			DPRINTF("Retrieved registers\n");
39031.72Skamil		} else if (strcmp(aux, "pc") == 0) {
39041.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
39051.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39061.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
39071.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
39081.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
39091.72Skamil		} else if (strcmp(aux, "sp") == 0) {
39101.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
39111.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39121.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
39131.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
39141.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39151.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
39161.72Skamil			DPRINTF("Call SETREGS for the child process\n");
39171.72Skamil			SYSCALL_REQUIRE(
39181.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
39191.72Skamil		}
39201.72Skamil	}
39211.1Skamil#endif
39221.1Skamil
39231.72Skamil#if defined(HAVE_FPREGS)
39241.72Skamil	if (strcmp(regset, "fpregs") == 0) {
39251.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
39261.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
39271.72Skamil
39281.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
39291.72Skamil			DPRINTF("Retrieved FP registers\n");
39301.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
39311.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
39321.72Skamil			SYSCALL_REQUIRE(
39331.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
39341.72Skamil		}
39351.1Skamil	}
39361.1Skamil#endif
39371.1Skamil
39381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39391.1Skamil	    "without signal to be sent\n");
39401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39411.1Skamil
39421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39441.1Skamil
39451.1Skamil	validate_status_exited(status, exitval);
39461.1Skamil
39471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39491.1Skamil}
39501.1Skamil
39511.72Skamil#define ACCESS_REGS(test, regset, aux)					\
39521.72SkamilATF_TC(test);								\
39531.72SkamilATF_TC_HEAD(test, tc)							\
39541.72Skamil{									\
39551.72Skamil        atf_tc_set_md_var(tc, "descr",					\
39561.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
39571.72Skamil}									\
39581.72Skamil									\
39591.72SkamilATF_TC_BODY(test, tc)							\
39601.72Skamil{									\
39611.72Skamil									\
39621.72Skamil        access_regs(regset, aux);					\
39631.1Skamil}
39641.1Skamil#endif
39651.1Skamil
39661.72Skamil#if defined(HAVE_GPREGS)
39671.72SkamilACCESS_REGS(access_regs1, "regs", "none")
39681.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
39691.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
39701.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
39711.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
39721.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
39731.1Skamil#endif
39741.1Skamil#if defined(HAVE_FPREGS)
39751.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
39761.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
39771.1Skamil#endif
39781.1Skamil
39791.72Skamil/// ----------------------------------------------------------------------------
39801.1Skamil
39811.1Skamil#if defined(PT_STEP)
39821.1Skamilstatic void
39831.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
39841.1Skamil{
39851.1Skamil	const int exitval = 5;
39861.1Skamil	const int sigval = SIGSTOP;
39871.1Skamil	pid_t child, wpid;
39881.1Skamil#if defined(TWAIT_HAVE_STATUS)
39891.1Skamil	int status;
39901.1Skamil#endif
39911.1Skamil	int happy;
39921.95Skamil	struct sigaction sa;
39931.81Skamil	struct ptrace_siginfo info;
39941.95Skamil	sigset_t intmask;
39951.95Skamil	struct kinfo_proc2 kp;
39961.95Skamil	size_t len = sizeof(kp);
39971.95Skamil
39981.95Skamil	int name[6];
39991.95Skamil	const size_t namelen = __arraycount(name);
40001.95Skamil	ki_sigset_t kp_sigmask;
40011.95Skamil	ki_sigset_t kp_sigignore;
40021.1Skamil
40031.1Skamil#if defined(__arm__)
40041.1Skamil	/* PT_STEP not supported on arm 32-bit */
40051.1Skamil	atf_tc_expect_fail("PR kern/52119");
40061.1Skamil#endif
40071.1Skamil
40081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40101.1Skamil	if (child == 0) {
40111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40131.1Skamil
40141.95Skamil		if (masked) {
40151.95Skamil			sigemptyset(&intmask);
40161.95Skamil			sigaddset(&intmask, SIGTRAP);
40171.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
40181.95Skamil		}
40191.95Skamil
40201.95Skamil		if (ignored) {
40211.95Skamil			memset(&sa, 0, sizeof(sa));
40221.95Skamil			sa.sa_handler = SIG_IGN;
40231.95Skamil			sigemptyset(&sa.sa_mask);
40241.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
40251.95Skamil		}
40261.95Skamil
40271.1Skamil		happy = check_happy(999);
40281.1Skamil
40291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40311.1Skamil
40321.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
40331.1Skamil
40341.13Schristos		DPRINTF("Before exiting of the child process\n");
40351.1Skamil		_exit(exitval);
40361.1Skamil	}
40371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40381.1Skamil
40391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40411.1Skamil
40421.1Skamil	validate_status_stopped(status, sigval);
40431.1Skamil
40441.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40451.81Skamil	SYSCALL_REQUIRE(
40461.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
40471.81Skamil
40481.81Skamil	DPRINTF("Before checking siginfo_t\n");
40491.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
40501.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
40511.81Skamil
40521.95Skamil	name[0] = CTL_KERN,
40531.95Skamil	name[1] = KERN_PROC2,
40541.95Skamil	name[2] = KERN_PROC_PID;
40551.95Skamil	name[3] = child;
40561.95Skamil	name[4] = sizeof(kp);
40571.95Skamil	name[5] = 1;
40581.95Skamil
40591.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
40601.95Skamil
40611.95Skamil	if (masked)
40621.95Skamil		kp_sigmask = kp.p_sigmask;
40631.95Skamil
40641.95Skamil	if (ignored)
40651.95Skamil		kp_sigignore = kp.p_sigignore;
40661.95Skamil
40671.1Skamil	while (N --> 0) {
40681.2Skamil		if (setstep) {
40691.13Schristos			DPRINTF("Before resuming the child process where it "
40701.2Skamil			    "left off and without signal to be sent (use "
40711.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
40721.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
40731.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
40741.2Skamil			    != -1);
40751.2Skamil		} else {
40761.13Schristos			DPRINTF("Before resuming the child process where it "
40771.2Skamil			    "left off and without signal to be sent (use "
40781.2Skamil			    "PT_STEP)\n");
40791.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
40801.2Skamil			    != -1);
40811.2Skamil		}
40821.1Skamil
40831.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40841.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
40851.1Skamil		    child);
40861.1Skamil
40871.1Skamil		validate_status_stopped(status, SIGTRAP);
40881.2Skamil
40891.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40901.81Skamil		SYSCALL_REQUIRE(
40911.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
40921.81Skamil
40931.81Skamil		DPRINTF("Before checking siginfo_t\n");
40941.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
40951.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
40961.81Skamil
40971.2Skamil		if (setstep) {
40981.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
40991.2Skamil		}
41001.95Skamil
41011.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
41021.95Skamil
41031.95Skamil		if (masked) {
41041.95Skamil			DPRINTF("kp_sigmask="
41051.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41061.95Skamil			    PRIx32 "\n",
41071.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
41081.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
41091.95Skamil
41101.95Skamil			DPRINTF("kp.p_sigmask="
41111.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41121.95Skamil			    PRIx32 "\n",
41131.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
41141.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
41151.95Skamil
41161.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
41171.95Skamil			    sizeof(kp_sigmask)));
41181.95Skamil		}
41191.95Skamil
41201.95Skamil		if (ignored) {
41211.95Skamil			DPRINTF("kp_sigignore="
41221.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41231.95Skamil			    PRIx32 "\n",
41241.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
41251.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
41261.95Skamil
41271.95Skamil			DPRINTF("kp.p_sigignore="
41281.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41291.95Skamil			    PRIx32 "\n",
41301.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
41311.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
41321.95Skamil
41331.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
41341.95Skamil			    sizeof(kp_sigignore)));
41351.95Skamil		}
41361.1Skamil	}
41371.1Skamil
41381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41391.1Skamil	    "without signal to be sent\n");
41401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41411.1Skamil
41421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41441.1Skamil
41451.1Skamil	validate_status_exited(status, exitval);
41461.1Skamil
41471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41491.1Skamil}
41501.1Skamil
41511.73Skamil#define PTRACE_STEP(test, N, setstep)					\
41521.73SkamilATF_TC(test);								\
41531.73SkamilATF_TC_HEAD(test, tc)							\
41541.73Skamil{									\
41551.73Skamil        atf_tc_set_md_var(tc, "descr",					\
41561.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
41571.73Skamil}									\
41581.73Skamil									\
41591.73SkamilATF_TC_BODY(test, tc)							\
41601.73Skamil{									\
41611.73Skamil									\
41621.95Skamil        ptrace_step(N, setstep, false, false);				\
41631.1Skamil}
41641.1Skamil
41651.73SkamilPTRACE_STEP(step1, 1, 0)
41661.73SkamilPTRACE_STEP(step2, 2, 0)
41671.73SkamilPTRACE_STEP(step3, 3, 0)
41681.73SkamilPTRACE_STEP(step4, 4, 0)
41691.73SkamilPTRACE_STEP(setstep1, 1, 1)
41701.73SkamilPTRACE_STEP(setstep2, 2, 1)
41711.73SkamilPTRACE_STEP(setstep3, 3, 1)
41721.73SkamilPTRACE_STEP(setstep4, 4, 1)
41731.95Skamil
41741.95SkamilATF_TC(step_signalmasked);
41751.95SkamilATF_TC_HEAD(step_signalmasked, tc)
41761.95Skamil{
41771.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
41781.95Skamil}
41791.95Skamil
41801.95SkamilATF_TC_BODY(step_signalmasked, tc)
41811.95Skamil{
41821.95Skamil
41831.95Skamil	ptrace_step(1, 0, true, false);
41841.95Skamil}
41851.95Skamil
41861.95SkamilATF_TC(step_signalignored);
41871.95SkamilATF_TC_HEAD(step_signalignored, tc)
41881.95Skamil{
41891.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
41901.95Skamil}
41911.95Skamil
41921.95SkamilATF_TC_BODY(step_signalignored, tc)
41931.95Skamil{
41941.95Skamil
41951.95Skamil	ptrace_step(1, 0, false, true);
41961.95Skamil}
41971.1Skamil#endif
41981.1Skamil
41991.73Skamil/// ----------------------------------------------------------------------------
42001.1Skamil
42011.75Skamilstatic void
42021.75Skamilptrace_kill(const char *type)
42031.1Skamil{
42041.75Skamil	const int sigval = SIGSTOP;
42051.1Skamil	pid_t child, wpid;
42061.1Skamil#if defined(TWAIT_HAVE_STATUS)
42071.1Skamil	int status;
42081.1Skamil#endif
42091.1Skamil
42101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42121.1Skamil	if (child == 0) {
42131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42151.1Skamil
42161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42181.1Skamil
42191.1Skamil		/* NOTREACHED */
42201.1Skamil		FORKEE_ASSERTX(0 &&
42211.1Skamil		    "Child should be terminated by a signal from its parent");
42221.1Skamil	}
42231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42241.1Skamil
42251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42271.1Skamil
42281.1Skamil	validate_status_stopped(status, sigval);
42291.1Skamil
42301.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
42311.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
42321.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
42331.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
42341.75Skamil		kill(child, SIGKILL);
42351.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
42361.75Skamil		setpgid(child, 0);
42371.75Skamil		killpg(getpgid(child), SIGKILL);
42381.75Skamil	}
42391.1Skamil
42401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42421.1Skamil
42431.75Skamil	validate_status_signaled(status, SIGKILL, 0);
42441.1Skamil
42451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42471.1Skamil}
42481.1Skamil
42491.75Skamil#define PTRACE_KILL(test, type)						\
42501.75SkamilATF_TC(test);								\
42511.75SkamilATF_TC_HEAD(test, tc)							\
42521.75Skamil{									\
42531.75Skamil        atf_tc_set_md_var(tc, "descr",					\
42541.75Skamil            "Verify killing the child with " type);			\
42551.75Skamil}									\
42561.75Skamil									\
42571.75SkamilATF_TC_BODY(test, tc)							\
42581.75Skamil{									\
42591.75Skamil									\
42601.75Skamil        ptrace_kill(type);						\
42611.1Skamil}
42621.1Skamil
42631.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
42641.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
42651.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
42661.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
42671.1Skamil
42681.75Skamil/// ----------------------------------------------------------------------------
42691.1Skamil
42701.77Skamilstatic void
42711.77Skamiltraceme_lwpinfo(const int threads)
42721.1Skamil{
42731.1Skamil	const int sigval = SIGSTOP;
42741.77Skamil	const int sigval2 = SIGINT;
42751.1Skamil	pid_t child, wpid;
42761.1Skamil#if defined(TWAIT_HAVE_STATUS)
42771.1Skamil	int status;
42781.1Skamil#endif
42791.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
42801.77Skamil	struct ptrace_siginfo info;
42811.77Skamil
42821.77Skamil	/* Maximum number of supported threads in this test */
42831.77Skamil	pthread_t t[3];
42841.77Skamil	int n, rv;
42851.77Skamil
42861.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
42871.1Skamil
42881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42901.1Skamil	if (child == 0) {
42911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42931.1Skamil
42941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42961.1Skamil
42971.77Skamil		for (n = 0; n < threads; n++) {
42981.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
42991.77Skamil			FORKEE_ASSERT(rv == 0);
43001.77Skamil		}
43011.77Skamil
43021.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
43031.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
43041.77Skamil
43051.77Skamil		/* NOTREACHED */
43061.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
43071.1Skamil	}
43081.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43091.1Skamil
43101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43121.1Skamil
43131.1Skamil	validate_status_stopped(status, sigval);
43141.1Skamil
43151.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
43161.77Skamil	SYSCALL_REQUIRE(
43171.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
43181.77Skamil
43191.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
43201.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
43211.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
43221.77Skamil	    info.psi_siginfo.si_errno);
43231.77Skamil
43241.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
43251.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
43261.77Skamil
43271.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
43281.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
43291.1Skamil
43301.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
43311.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
43321.1Skamil
43331.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
43341.77Skamil	    lwp.pl_lwpid);
43351.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
43361.1Skamil
43371.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
43381.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
43391.1Skamil
43401.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
43411.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
43421.1Skamil
43431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43441.1Skamil	    "without signal to be sent\n");
43451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43461.1Skamil
43471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43491.1Skamil
43501.77Skamil	validate_status_stopped(status, sigval2);
43511.77Skamil
43521.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
43531.77Skamil	SYSCALL_REQUIRE(
43541.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
43551.77Skamil
43561.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
43571.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
43581.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
43591.77Skamil	    info.psi_siginfo.si_errno);
43601.77Skamil
43611.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
43621.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
43631.77Skamil
43641.77Skamil	memset(&lwp, 0, sizeof(lwp));
43651.77Skamil
43661.77Skamil	for (n = 0; n <= threads; n++) {
43671.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
43681.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
43691.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
43701.77Skamil
43711.77Skamil		DPRINTF("Assert that the thread exists\n");
43721.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
43731.77Skamil
43741.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
43751.77Skamil		    lwp.pl_lwpid);
43761.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
43771.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
43781.77Skamil	}
43791.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
43801.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
43811.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
43821.77Skamil
43831.77Skamil	DPRINTF("Assert that there are no more threads\n");
43841.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
43851.77Skamil
43861.77Skamil	DPRINTF("Before resuming the child process where it left off and "
43871.77Skamil	    "without signal to be sent\n");
43881.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
43891.77Skamil
43901.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43911.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43921.77Skamil
43931.77Skamil	validate_status_signaled(status, SIGKILL, 0);
43941.1Skamil
43951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43971.1Skamil}
43981.1Skamil
43991.77Skamil#define TRACEME_LWPINFO(test, threads)					\
44001.77SkamilATF_TC(test);								\
44011.77SkamilATF_TC_HEAD(test, tc)							\
44021.77Skamil{									\
44031.77Skamil	atf_tc_set_md_var(tc, "descr",					\
44041.77Skamil	    "Verify LWPINFO with the child with " #threads		\
44051.77Skamil	    " spawned extra threads");					\
44061.77Skamil}									\
44071.77Skamil									\
44081.77SkamilATF_TC_BODY(test, tc)							\
44091.77Skamil{									\
44101.77Skamil									\
44111.77Skamil	traceme_lwpinfo(threads);					\
44121.1Skamil}
44131.1Skamil
44141.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
44151.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
44161.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
44171.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
44181.77Skamil
44191.77Skamil/// ----------------------------------------------------------------------------
44201.77Skamil
44211.77Skamil#if defined(TWAIT_HAVE_PID)
44221.77Skamilstatic void
44231.77Skamilattach_lwpinfo(const int threads)
44241.1Skamil{
44251.77Skamil	const int sigval = SIGINT;
44261.1Skamil	struct msg_fds parent_tracee, parent_tracer;
44271.1Skamil	const int exitval_tracer = 10;
44281.1Skamil	pid_t tracee, tracer, wpid;
44291.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
44301.1Skamil#if defined(TWAIT_HAVE_STATUS)
44311.1Skamil	int status;
44321.1Skamil#endif
44331.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
44341.77Skamil	struct ptrace_siginfo info;
44351.77Skamil
44361.77Skamil	/* Maximum number of supported threads in this test */
44371.77Skamil	pthread_t t[3];
44381.77Skamil	int n, rv;
44391.1Skamil
44401.13Schristos	DPRINTF("Spawn tracee\n");
44411.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
44421.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
44431.1Skamil	tracee = atf_utils_fork();
44441.1Skamil	if (tracee == 0) {
44451.1Skamil		/* Wait for message from the parent */
44461.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
44471.1Skamil
44481.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
44491.77Skamil
44501.77Skamil		for (n = 0; n < threads; n++) {
44511.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
44521.77Skamil			FORKEE_ASSERT(rv == 0);
44531.77Skamil		}
44541.77Skamil
44551.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
44561.77Skamil
44571.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44581.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44591.77Skamil
44601.77Skamil		/* NOTREACHED */
44611.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
44621.1Skamil	}
44631.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
44641.1Skamil
44651.13Schristos	DPRINTF("Spawn debugger\n");
44661.1Skamil	tracer = atf_utils_fork();
44671.1Skamil	if (tracer == 0) {
44681.1Skamil		/* No IPC to communicate with the child */
44691.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
44701.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
44711.1Skamil
44721.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
44731.1Skamil		FORKEE_REQUIRE_SUCCESS(
44741.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
44751.1Skamil
44761.1Skamil		forkee_status_stopped(status, SIGSTOP);
44771.1Skamil
44781.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
44791.77Skamil		    "tracee");
44801.77Skamil		FORKEE_ASSERT(
44811.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
44821.77Skamil
44831.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
44841.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
44851.77Skamil		    "si_errno=%#x\n",
44861.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
44871.77Skamil		    info.psi_siginfo.si_errno);
44881.77Skamil
44891.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
44901.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
44911.77Skamil
44921.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
44931.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
44941.1Skamil		    != -1);
44951.1Skamil
44961.13Schristos		DPRINTF("Assert that there exists a thread\n");
44971.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
44981.1Skamil
44991.13Schristos		DPRINTF("Assert that lwp thread %d received event "
45001.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
45011.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
45021.1Skamil
45031.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
45041.77Skamil		    "tracee\n");
45051.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
45061.1Skamil		    != -1);
45071.1Skamil
45081.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
45091.77Skamil		    "tracee\n");
45101.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
45111.1Skamil
45121.1Skamil		/* Resume tracee with PT_CONTINUE */
45131.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
45141.1Skamil
45151.1Skamil		/* Inform parent that tracer has attached to tracee */
45161.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
45171.77Skamil
45181.1Skamil		/* Wait for parent */
45191.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
45201.1Skamil
45211.77Skamil		/* Wait for tracee and assert that it raised a signal */
45221.77Skamil		FORKEE_REQUIRE_SUCCESS(
45231.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
45241.77Skamil
45251.77Skamil		forkee_status_stopped(status, SIGINT);
45261.77Skamil
45271.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
45281.77Skamil		    "child");
45291.77Skamil		FORKEE_ASSERT(
45301.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
45311.77Skamil
45321.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45331.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
45341.77Skamil		    "si_errno=%#x\n",
45351.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45361.77Skamil		    info.psi_siginfo.si_errno);
45371.77Skamil
45381.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
45391.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
45401.77Skamil
45411.77Skamil		memset(&lwp, 0, sizeof(lwp));
45421.77Skamil
45431.77Skamil		for (n = 0; n <= threads; n++) {
45441.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
45451.77Skamil			    "child\n");
45461.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
45471.77Skamil			    sizeof(lwp)) != -1);
45481.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
45491.77Skamil
45501.77Skamil			DPRINTF("Assert that the thread exists\n");
45511.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
45521.77Skamil
45531.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
45541.77Skamil			    "event\n", lwp.pl_lwpid);
45551.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
45561.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
45571.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
45581.77Skamil		}
45591.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
45601.77Skamil		    "tracee\n");
45611.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
45621.77Skamil		    != -1);
45631.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
45641.77Skamil
45651.77Skamil		DPRINTF("Assert that there are no more threads\n");
45661.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
45671.77Skamil
45681.77Skamil		DPRINTF("Before resuming the child process where it left off "
45691.77Skamil		    "and without signal to be sent\n");
45701.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
45711.77Skamil		    != -1);
45721.77Skamil
45731.1Skamil		/* Wait for tracee and assert that it exited */
45741.1Skamil		FORKEE_REQUIRE_SUCCESS(
45751.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
45761.1Skamil
45771.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
45781.1Skamil
45791.13Schristos		DPRINTF("Before exiting of the tracer process\n");
45801.1Skamil		_exit(exitval_tracer);
45811.1Skamil	}
45821.1Skamil
45831.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
45841.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
45851.1Skamil
45861.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
45871.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
45881.77Skamil
45891.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
45901.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
45911.1Skamil
45921.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
45931.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
45941.1Skamil
45951.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
45961.1Skamil	    TWAIT_FNAME);
45971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
45981.1Skamil	    tracer);
45991.1Skamil
46001.1Skamil	validate_status_exited(status, exitval_tracer);
46011.1Skamil
46021.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
46031.1Skamil	    TWAIT_FNAME);
46041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
46051.1Skamil	    tracee);
46061.1Skamil
46071.77Skamil	validate_status_signaled(status, SIGKILL, 0);
46081.1Skamil
46091.1Skamil	msg_close(&parent_tracer);
46101.1Skamil	msg_close(&parent_tracee);
46111.1Skamil}
46121.77Skamil
46131.77Skamil#define ATTACH_LWPINFO(test, threads)					\
46141.77SkamilATF_TC(test);								\
46151.77SkamilATF_TC_HEAD(test, tc)							\
46161.77Skamil{									\
46171.77Skamil	atf_tc_set_md_var(tc, "descr",					\
46181.77Skamil	    "Verify LWPINFO with the child with " #threads		\
46191.77Skamil	    " spawned extra threads (tracer is not the original "	\
46201.77Skamil	    "parent)");							\
46211.77Skamil}									\
46221.77Skamil									\
46231.77SkamilATF_TC_BODY(test, tc)							\
46241.77Skamil{									\
46251.77Skamil									\
46261.77Skamil	attach_lwpinfo(threads);					\
46271.77Skamil}
46281.77Skamil
46291.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
46301.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
46311.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
46321.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
46331.1Skamil#endif
46341.1Skamil
46351.77Skamil/// ----------------------------------------------------------------------------
46361.77Skamil
46371.1Skamilstatic void
46381.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
46391.1Skamil{
46401.1Skamil	const int exitval = 5;
46411.1Skamil	const int sigval = SIGINT;
46421.1Skamil	const int sigfaked = SIGTRAP;
46431.1Skamil	const int sicodefaked = TRAP_BRKPT;
46441.1Skamil	pid_t child, wpid;
46451.1Skamil	struct sigaction sa;
46461.1Skamil#if defined(TWAIT_HAVE_STATUS)
46471.1Skamil	int status;
46481.1Skamil#endif
46491.1Skamil	struct ptrace_siginfo info;
46501.1Skamil	memset(&info, 0, sizeof(info));
46511.1Skamil
46521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46541.1Skamil	if (child == 0) {
46551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46571.1Skamil
46581.79Skamil		sa.sa_sigaction = sah;
46591.1Skamil		sa.sa_flags = SA_SIGINFO;
46601.1Skamil		sigemptyset(&sa.sa_mask);
46611.1Skamil
46621.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
46631.79Skamil		    != -1);
46641.1Skamil
46651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46671.1Skamil
46681.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
46691.1Skamil
46701.13Schristos		DPRINTF("Before exiting of the child process\n");
46711.1Skamil		_exit(exitval);
46721.1Skamil	}
46731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46741.1Skamil
46751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46771.1Skamil
46781.1Skamil	validate_status_stopped(status, sigval);
46791.1Skamil
46801.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
46811.61Skre	SYSCALL_REQUIRE(
46821.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
46831.1Skamil
46841.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
46851.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
46861.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
46871.1Skamil	    info.psi_siginfo.si_errno);
46881.1Skamil
46891.79Skamil	if (faked) {
46901.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
46911.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
46921.79Skamil		info.psi_siginfo.si_signo = sigfaked;
46931.79Skamil		info.psi_siginfo.si_code = sicodefaked;
46941.79Skamil	}
46951.1Skamil
46961.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
46971.61Skre	SYSCALL_REQUIRE(
46981.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
46991.1Skamil
47001.79Skamil	if (faked) {
47011.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
47021.79Skamil		    "child\n");
47031.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
47041.79Skamil		    sizeof(info)) != -1);
47051.1Skamil
47061.79Skamil		DPRINTF("Before checking siginfo_t\n");
47071.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
47081.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
47091.79Skamil	}
47101.1Skamil
47111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47121.1Skamil	    "without signal to be sent\n");
47131.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
47141.79Skamil	    faked ? sigfaked : sigval) != -1);
47151.1Skamil
47161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47181.1Skamil
47191.1Skamil	validate_status_exited(status, exitval);
47201.1Skamil
47211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47221.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47231.1Skamil}
47241.1Skamil
47251.79Skamil#define PTRACE_SIGINFO(test, faked)					\
47261.79SkamilATF_TC(test);								\
47271.79SkamilATF_TC_HEAD(test, tc)							\
47281.79Skamil{									\
47291.79Skamil	atf_tc_set_md_var(tc, "descr",					\
47301.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
47311.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
47321.79Skamil}									\
47331.79Skamil									\
47341.79Skamilstatic int test##_caught = 0;						\
47351.79Skamil									\
47361.79Skamilstatic void								\
47371.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
47381.79Skamil{									\
47391.79Skamil	if (faked) {							\
47401.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
47411.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
47421.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
47431.79Skamil	} else {							\
47441.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
47451.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
47461.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
47471.79Skamil	}								\
47481.79Skamil									\
47491.79Skamil	++ test##_caught;						\
47501.79Skamil}									\
47511.79Skamil									\
47521.79SkamilATF_TC_BODY(test, tc)							\
47531.79Skamil{									\
47541.79Skamil									\
47551.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
47561.79Skamil}
47571.79Skamil
47581.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
47591.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
47601.79Skamil
47611.79Skamil/// ----------------------------------------------------------------------------
47621.79Skamil
47631.97Skamilstatic void
47641.97Skamiltraceme_exec(bool masked, bool ignored)
47651.1Skamil{
47661.1Skamil	const int sigval = SIGTRAP;
47671.1Skamil	pid_t child, wpid;
47681.1Skamil#if defined(TWAIT_HAVE_STATUS)
47691.1Skamil	int status;
47701.1Skamil#endif
47711.97Skamil	struct sigaction sa;
47721.97Skamil	struct ptrace_siginfo info;
47731.97Skamil	sigset_t intmask;
47741.97Skamil	struct kinfo_proc2 kp;
47751.97Skamil	size_t len = sizeof(kp);
47761.97Skamil
47771.97Skamil	int name[6];
47781.97Skamil	const size_t namelen = __arraycount(name);
47791.97Skamil	ki_sigset_t kp_sigmask;
47801.97Skamil	ki_sigset_t kp_sigignore;
47811.1Skamil
47821.1Skamil	memset(&info, 0, sizeof(info));
47831.1Skamil
47841.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47851.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47861.1Skamil	if (child == 0) {
47871.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47881.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47891.1Skamil
47901.97Skamil		if (masked) {
47911.97Skamil			sigemptyset(&intmask);
47921.97Skamil			sigaddset(&intmask, sigval);
47931.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
47941.97Skamil		}
47951.97Skamil
47961.97Skamil		if (ignored) {
47971.97Skamil			memset(&sa, 0, sizeof(sa));
47981.97Skamil			sa.sa_handler = SIG_IGN;
47991.97Skamil			sigemptyset(&sa.sa_mask);
48001.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
48011.97Skamil		}
48021.97Skamil
48031.13Schristos		DPRINTF("Before calling execve(2) from child\n");
48041.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
48051.1Skamil
48061.1Skamil		FORKEE_ASSERT(0 && "Not reached");
48071.1Skamil	}
48081.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48091.1Skamil
48101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48121.1Skamil
48131.1Skamil	validate_status_stopped(status, sigval);
48141.1Skamil
48151.97Skamil	name[0] = CTL_KERN,
48161.97Skamil	name[1] = KERN_PROC2,
48171.97Skamil	name[2] = KERN_PROC_PID;
48181.97Skamil	name[3] = getpid();
48191.97Skamil	name[4] = sizeof(kp);
48201.97Skamil	name[5] = 1;
48211.97Skamil
48221.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
48231.97Skamil
48241.97Skamil	if (masked)
48251.97Skamil		kp_sigmask = kp.p_sigmask;
48261.97Skamil
48271.97Skamil	if (ignored)
48281.97Skamil		kp_sigignore = kp.p_sigignore;
48291.97Skamil
48301.97Skamil	name[3] = getpid();
48311.97Skamil
48321.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
48331.97Skamil
48341.97Skamil	if (masked) {
48351.97Skamil		DPRINTF("kp_sigmask="
48361.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
48371.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
48381.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
48391.97Skamil
48401.97Skamil		DPRINTF("kp.p_sigmask="
48411.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
48421.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
48431.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
48441.97Skamil
48451.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
48461.97Skamil		    sizeof(kp_sigmask)));
48471.97Skamil	}
48481.97Skamil
48491.97Skamil	if (ignored) {
48501.97Skamil		DPRINTF("kp_sigignore="
48511.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
48521.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
48531.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
48541.97Skamil
48551.97Skamil		DPRINTF("kp.p_sigignore="
48561.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
48571.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
48581.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
48591.97Skamil
48601.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
48611.97Skamil		    sizeof(kp_sigignore)));
48621.97Skamil	}
48631.97Skamil
48641.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48651.61Skre	SYSCALL_REQUIRE(
48661.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48671.1Skamil
48681.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48691.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48701.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48711.1Skamil	    info.psi_siginfo.si_errno);
48721.1Skamil
48731.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
48741.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
48751.1Skamil
48761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48771.1Skamil	    "without signal to be sent\n");
48781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48791.1Skamil
48801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48821.1Skamil
48831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48851.1Skamil}
48861.1Skamil
48871.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
48881.97SkamilATF_TC(test);								\
48891.97SkamilATF_TC_HEAD(test, tc)							\
48901.97Skamil{									\
48911.97Skamil       atf_tc_set_md_var(tc, "descr",					\
48921.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
48931.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
48941.97Skamil           masked ? " with ignored signal" : "");			\
48951.97Skamil}									\
48961.97Skamil									\
48971.97SkamilATF_TC_BODY(test, tc)							\
48981.97Skamil{									\
48991.97Skamil									\
49001.97Skamil       traceme_exec(masked, ignored);					\
49011.97Skamil}
49021.97Skamil
49031.97SkamilTRACEME_EXEC(traceme_exec, false, false)
49041.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
49051.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
49061.97Skamil
49071.82Skamil/// ----------------------------------------------------------------------------
49081.82Skamil
49091.83Skamilstatic volatile int done;
49101.1Skamil
49111.83Skamilstatic void *
49121.83Skamiltrace_threads_cb(void *arg __unused)
49131.1Skamil{
49141.1Skamil
49151.83Skamil	done++;
49161.83Skamil
49171.83Skamil	while (done < 3)
49181.83Skamil		continue;
49191.83Skamil
49201.83Skamil	return NULL;
49211.1Skamil}
49221.1Skamil
49231.83Skamilstatic void
49241.83Skamiltrace_threads(bool trace_create, bool trace_exit)
49251.1Skamil{
49261.1Skamil	const int sigval = SIGSTOP;
49271.1Skamil	pid_t child, wpid;
49281.1Skamil#if defined(TWAIT_HAVE_STATUS)
49291.1Skamil	int status;
49301.1Skamil#endif
49311.1Skamil	ptrace_state_t state;
49321.1Skamil	const int slen = sizeof(state);
49331.1Skamil	ptrace_event_t event;
49341.1Skamil	const int elen = sizeof(event);
49351.83Skamil	struct ptrace_siginfo info;
49361.83Skamil
49371.83Skamil	pthread_t t[3];
49381.83Skamil	int rv;
49391.83Skamil	size_t n;
49401.1Skamil	lwpid_t lid;
49411.83Skamil
49421.83Skamil	/* Track created and exited threads */
49431.83Skamil	bool traced_lwps[__arraycount(t)];
49441.83Skamil
49451.83Skamil	atf_tc_skip("PR kern/51995");
49461.1Skamil
49471.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49481.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49491.1Skamil	if (child == 0) {
49501.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49511.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49521.1Skamil
49531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49551.1Skamil
49561.83Skamil		for (n = 0; n < __arraycount(t); n++) {
49571.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
49581.83Skamil			    NULL);
49591.83Skamil			FORKEE_ASSERT(rv == 0);
49601.83Skamil		}
49611.1Skamil
49621.83Skamil		for (n = 0; n < __arraycount(t); n++) {
49631.83Skamil			rv = pthread_join(t[n], NULL);
49641.83Skamil			FORKEE_ASSERT(rv == 0);
49651.83Skamil		}
49661.1Skamil
49671.83Skamil		/*
49681.83Skamil		 * There is race between _exit() and pthread_join() detaching
49691.83Skamil		 * a thread. For simplicity kill the process after detecting
49701.83Skamil		 * LWP events.
49711.83Skamil		 */
49721.83Skamil		while (true)
49731.83Skamil			continue;
49741.1Skamil
49751.83Skamil		FORKEE_ASSERT(0 && "Not reached");
49761.1Skamil	}
49771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49781.1Skamil
49791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49811.1Skamil
49821.1Skamil	validate_status_stopped(status, sigval);
49831.1Skamil
49841.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49851.83Skamil	SYSCALL_REQUIRE(
49861.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49871.1Skamil
49881.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49891.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49901.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49911.83Skamil	    info.psi_siginfo.si_errno);
49921.1Skamil
49931.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
49941.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
49951.1Skamil
49961.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
49971.83Skamil	memset(&event, 0, sizeof(event));
49981.83Skamil	if (trace_create)
49991.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
50001.83Skamil	if (trace_exit)
50011.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
50021.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50031.1Skamil
50041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50051.1Skamil	    "without signal to be sent\n");
50061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50071.1Skamil
50081.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
50091.1Skamil
50101.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
50111.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
50121.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
50131.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
50141.83Skamil		    child);
50151.1Skamil
50161.83Skamil		validate_status_stopped(status, SIGTRAP);
50171.1Skamil
50181.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
50191.83Skamil		    "child\n");
50201.83Skamil		SYSCALL_REQUIRE(
50211.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50221.1Skamil
50231.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50241.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50251.83Skamil		    "si_errno=%#x\n",
50261.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50271.83Skamil		    info.psi_siginfo.si_errno);
50281.1Skamil
50291.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
50301.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
50311.1Skamil
50321.83Skamil		SYSCALL_REQUIRE(
50331.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50341.1Skamil
50351.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
50361.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
50371.1Skamil
50381.83Skamil		lid = state.pe_lwp;
50391.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
50401.1Skamil
50411.83Skamil		traced_lwps[lid - 1] = true;
50421.1Skamil
50431.83Skamil		DPRINTF("Before resuming the child process where it left off "
50441.83Skamil		    "and without signal to be sent\n");
50451.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50461.83Skamil	}
50471.1Skamil
50481.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
50491.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
50501.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
50511.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
50521.83Skamil		    child);
50531.1Skamil
50541.83Skamil		validate_status_stopped(status, SIGTRAP);
50551.1Skamil
50561.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
50571.83Skamil		    "child\n");
50581.83Skamil		SYSCALL_REQUIRE(
50591.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50601.1Skamil
50611.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50621.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50631.83Skamil		    "si_errno=%#x\n",
50641.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50651.83Skamil		    info.psi_siginfo.si_errno);
50661.1Skamil
50671.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
50681.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
50691.1Skamil
50701.83Skamil		SYSCALL_REQUIRE(
50711.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50721.1Skamil
50731.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
50741.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
50751.1Skamil
50761.83Skamil		lid = state.pe_lwp;
50771.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
50781.1Skamil
50791.83Skamil		if (trace_create) {
50801.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
50811.83Skamil			traced_lwps[lid - 1] = false;
50821.83Skamil		}
50831.1Skamil
50841.83Skamil		DPRINTF("Before resuming the child process where it left off "
50851.83Skamil		    "and without signal to be sent\n");
50861.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50871.83Skamil	}
50881.1Skamil
50891.83Skamil	kill(child, SIGKILL);
50901.1Skamil
50911.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
50921.1Skamil	    TWAIT_FNAME);
50931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50941.1Skamil
50951.83Skamil	validate_status_signaled(status, SIGKILL, 0);
50961.1Skamil
50971.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
50981.1Skamil	    TWAIT_FNAME);
50991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51001.1Skamil}
51011.1Skamil
51021.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
51031.83SkamilATF_TC(test);								\
51041.83SkamilATF_TC_HEAD(test, tc)							\
51051.83Skamil{									\
51061.83Skamil        atf_tc_set_md_var(tc, "descr",					\
51071.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
51081.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
51091.83Skamil	    trace_exit ? "" : "out");					\
51101.83Skamil}									\
51111.83Skamil									\
51121.83SkamilATF_TC_BODY(test, tc)							\
51131.83Skamil{									\
51141.83Skamil									\
51151.83Skamil        trace_threads(trace_create, trace_exit);			\
51161.83Skamil}
51171.83Skamil
51181.83SkamilTRACE_THREADS(trace_thread1, false, false)
51191.83SkamilTRACE_THREADS(trace_thread2, false, true)
51201.83SkamilTRACE_THREADS(trace_thread3, true, false)
51211.83SkamilTRACE_THREADS(trace_thread4, true, true)
51221.83Skamil
51231.83Skamil/// ----------------------------------------------------------------------------
51241.83Skamil
51251.84SkamilATF_TC(signal_mask_unrelated);
51261.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
51271.1Skamil{
51281.1Skamil	atf_tc_set_md_var(tc, "descr",
51291.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
51301.1Skamil	    "from catching other signals");
51311.1Skamil}
51321.1Skamil
51331.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
51341.1Skamil{
51351.1Skamil	const int exitval = 5;
51361.1Skamil	const int sigval = SIGSTOP;
51371.1Skamil	const int sigmasked = SIGTRAP;
51381.1Skamil	const int signotmasked = SIGINT;
51391.1Skamil	pid_t child, wpid;
51401.1Skamil#if defined(TWAIT_HAVE_STATUS)
51411.1Skamil	int status;
51421.1Skamil#endif
51431.1Skamil	sigset_t intmask;
51441.1Skamil
51451.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51461.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51471.1Skamil	if (child == 0) {
51481.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51491.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51501.1Skamil
51511.1Skamil		sigemptyset(&intmask);
51521.1Skamil		sigaddset(&intmask, sigmasked);
51531.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
51541.1Skamil
51551.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51561.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51571.1Skamil
51581.13Schristos		DPRINTF("Before raising %s from child\n",
51591.1Skamil		    strsignal(signotmasked));
51601.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
51611.1Skamil
51621.13Schristos		DPRINTF("Before exiting of the child process\n");
51631.1Skamil		_exit(exitval);
51641.1Skamil	}
51651.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51661.1Skamil
51671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51691.1Skamil
51701.1Skamil	validate_status_stopped(status, sigval);
51711.1Skamil
51721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51731.1Skamil	    "without signal to be sent\n");
51741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51751.1Skamil
51761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51781.1Skamil
51791.1Skamil	validate_status_stopped(status, signotmasked);
51801.1Skamil
51811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51821.1Skamil	    "without signal to be sent\n");
51831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51841.1Skamil
51851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51871.1Skamil
51881.1Skamil	validate_status_exited(status, exitval);
51891.1Skamil
51901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51921.1Skamil}
51931.1Skamil
51941.84Skamil/// ----------------------------------------------------------------------------
51951.84Skamil
51961.1Skamil#if defined(TWAIT_HAVE_PID)
51971.99Skamilstatic void
51981.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked,
51991.99Skamil           bool ignored)
52001.1Skamil{
52011.1Skamil	const int exitval = 5;
52021.1Skamil	const int exitval2 = 15;
52031.1Skamil	const int sigval = SIGSTOP;
52041.99Skamil	pid_t child, child2 = 0, wpid;
52051.1Skamil#if defined(TWAIT_HAVE_STATUS)
52061.1Skamil	int status;
52071.1Skamil#endif
52081.1Skamil	ptrace_state_t state;
52091.1Skamil	const int slen = sizeof(state);
52101.1Skamil	ptrace_event_t event;
52111.1Skamil	const int elen = sizeof(event);
52121.99Skamil	pid_t (*fn)(void);
52131.99Skamil	struct sigaction sa;
52141.99Skamil	struct ptrace_siginfo info;
52151.99Skamil	sigset_t intmask;
52161.99Skamil	struct kinfo_proc2 kp;
52171.99Skamil	size_t len = sizeof(kp);
52181.99Skamil
52191.99Skamil	int name[6];
52201.99Skamil	const size_t namelen = __arraycount(name);
52211.99Skamil	ki_sigset_t kp_sigmask;
52221.99Skamil	ki_sigset_t kp_sigignore;
52231.1Skamil
52241.99Skamil	if (masked)
52251.99Skamil		atf_tc_expect_fail("Masked signal invisible to tracer");
52261.99Skamil
52271.99Skamil	if (trackfork)
52281.99Skamil		fn = fork;
52291.99Skamil	if (trackvfork || trackvforkdone)
52301.99Skamil		fn = vfork;
52311.14Schristos
52321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52341.1Skamil	if (child == 0) {
52351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52371.1Skamil
52381.99Skamil		if (masked) {
52391.99Skamil			sigemptyset(&intmask);
52401.99Skamil			sigaddset(&intmask, SIGTRAP);
52411.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
52421.99Skamil		}
52431.99Skamil
52441.99Skamil		if (ignored) {
52451.99Skamil			memset(&sa, 0, sizeof(sa));
52461.99Skamil			sa.sa_handler = SIG_IGN;
52471.99Skamil			sigemptyset(&sa.sa_mask);
52481.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
52491.99Skamil		}
52501.1Skamil
52511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52531.1Skamil
52541.99Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
52551.1Skamil
52561.1Skamil		if (child2 == 0)
52571.1Skamil			_exit(exitval2);
52581.1Skamil
52591.1Skamil		FORKEE_REQUIRE_SUCCESS
52601.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
52611.1Skamil
52621.1Skamil		forkee_status_exited(status, exitval2);
52631.1Skamil
52641.13Schristos		DPRINTF("Before exiting of the child process\n");
52651.1Skamil		_exit(exitval);
52661.1Skamil	}
52671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52681.1Skamil
52691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52711.1Skamil
52721.1Skamil	validate_status_stopped(status, sigval);
52731.1Skamil
52741.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52751.99Skamil	SYSCALL_REQUIRE(
52761.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52771.99Skamil
52781.99Skamil	DPRINTF("Before checking siginfo_t\n");
52791.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
52801.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
52811.1Skamil
52821.99Skamil	name[0] = CTL_KERN,
52831.99Skamil	name[1] = KERN_PROC2,
52841.99Skamil	name[2] = KERN_PROC_PID;
52851.99Skamil	name[3] = child;
52861.99Skamil	name[4] = sizeof(kp);
52871.99Skamil	name[5] = 1;
52881.1Skamil
52891.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
52901.1Skamil
52911.99Skamil	if (masked)
52921.99Skamil		kp_sigmask = kp.p_sigmask;
52931.1Skamil
52941.99Skamil	if (ignored)
52951.99Skamil		kp_sigignore = kp.p_sigignore;
52961.1Skamil
52971.99Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
52981.99Skamil	    trackfork ? "|PTRACE_FORK" : "",
52991.99Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
53001.99Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
53011.99Skamil	event.pe_set_event = 0;
53021.99Skamil	if (trackfork)
53031.99Skamil		event.pe_set_event |= PTRACE_FORK;
53041.99Skamil	if (trackvfork)
53051.99Skamil		event.pe_set_event |= PTRACE_VFORK;
53061.99Skamil	if (trackvforkdone)
53071.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
53081.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
53091.1Skamil
53101.99Skamil	DPRINTF("Before resuming the child process where it left off and "
53111.99Skamil	    "without signal to be sent\n");
53121.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53131.1Skamil
53141.99Skamil	if (trackfork || trackvfork) {
53151.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
53161.99Skamil		    child);
53171.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
53181.99Skamil		    child);
53191.1Skamil
53201.99Skamil		validate_status_stopped(status, SIGTRAP);
53211.1Skamil
53221.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53231.1Skamil
53241.99Skamil		if (masked) {
53251.99Skamil			DPRINTF("kp_sigmask="
53261.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53271.99Skamil			    PRIx32 "\n",
53281.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
53291.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
53301.1Skamil
53311.99Skamil			DPRINTF("kp.p_sigmask="
53321.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53331.99Skamil			    PRIx32 "\n",
53341.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
53351.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
53361.1Skamil
53371.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
53381.99Skamil			    sizeof(kp_sigmask)));
53391.99Skamil		}
53401.1Skamil
53411.99Skamil		if (ignored) {
53421.99Skamil			DPRINTF("kp_sigignore="
53431.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53441.99Skamil			    PRIx32 "\n",
53451.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
53461.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
53471.1Skamil
53481.99Skamil			DPRINTF("kp.p_sigignore="
53491.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53501.99Skamil			    PRIx32 "\n",
53511.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
53521.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
53531.1Skamil
53541.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
53551.99Skamil			    sizeof(kp_sigignore)));
53561.99Skamil		}
53571.1Skamil
53581.99Skamil		SYSCALL_REQUIRE(
53591.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
53601.99Skamil		if (trackfork) {
53611.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
53621.99Skamil			       PTRACE_FORK);
53631.99Skamil		}
53641.99Skamil		if (trackvfork) {
53651.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
53661.99Skamil			       PTRACE_VFORK);
53671.99Skamil		}
53681.1Skamil
53691.99Skamil		child2 = state.pe_other_pid;
53701.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
53711.1Skamil
53721.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
53731.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
53741.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
53751.99Skamil		    child2);
53761.1Skamil
53771.99Skamil		validate_status_stopped(status, SIGTRAP);
53781.1Skamil
53791.99Skamil		name[3] = child2;
53801.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53811.1Skamil
53821.99Skamil		if (masked) {
53831.99Skamil			DPRINTF("kp_sigmask="
53841.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53851.99Skamil			    PRIx32 "\n",
53861.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
53871.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
53881.1Skamil
53891.99Skamil			DPRINTF("kp.p_sigmask="
53901.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53911.99Skamil			    PRIx32 "\n",
53921.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
53931.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
53941.14Schristos
53951.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
53961.99Skamil			    sizeof(kp_sigmask)));
53971.99Skamil		}
53981.1Skamil
53991.99Skamil		if (ignored) {
54001.99Skamil			DPRINTF("kp_sigignore="
54011.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54021.99Skamil			    PRIx32 "\n",
54031.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
54041.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
54051.1Skamil
54061.99Skamil			DPRINTF("kp.p_sigignore="
54071.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54081.99Skamil			    PRIx32 "\n",
54091.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
54101.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
54111.1Skamil
54121.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
54131.99Skamil			    sizeof(kp_sigignore)));
54141.99Skamil		}
54151.1Skamil
54161.99Skamil		SYSCALL_REQUIRE(
54171.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
54181.99Skamil		if (trackfork) {
54191.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
54201.99Skamil			       PTRACE_FORK);
54211.99Skamil		}
54221.99Skamil		if (trackvfork) {
54231.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
54241.99Skamil			       PTRACE_VFORK);
54251.99Skamil		}
54261.1Skamil
54271.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
54281.1Skamil
54291.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
54301.99Skamil		    "and without signal to be sent\n");
54311.99Skamil		SYSCALL_REQUIRE(
54321.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
54331.1Skamil
54341.99Skamil		DPRINTF("Before resuming the child process where it left off "
54351.99Skamil		    "and without signal to be sent\n");
54361.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54371.1Skamil	}
54381.1Skamil
54391.99Skamil	if (trackvforkdone) {
54401.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
54411.99Skamil		    child);
54421.99Skamil		TWAIT_REQUIRE_SUCCESS(
54431.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
54441.1Skamil
54451.99Skamil		validate_status_stopped(status, SIGTRAP);
54461.1Skamil
54471.99Skamil		name[3] = child;
54481.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
54491.1Skamil
54501.99Skamil		if (masked) {
54511.99Skamil			DPRINTF("kp_sigmask="
54521.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54531.99Skamil			    PRIx32 "\n",
54541.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
54551.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
54561.1Skamil
54571.99Skamil			DPRINTF("kp.p_sigmask="
54581.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54591.99Skamil			    PRIx32 "\n",
54601.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
54611.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
54621.1Skamil
54631.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
54641.99Skamil			    sizeof(kp_sigmask)));
54651.99Skamil		}
54661.1Skamil
54671.99Skamil		if (ignored) {
54681.99Skamil			DPRINTF("kp_sigignore="
54691.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54701.99Skamil			    PRIx32 "\n",
54711.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
54721.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
54731.1Skamil
54741.99Skamil			DPRINTF("kp.p_sigignore="
54751.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54761.99Skamil			    PRIx32 "\n",
54771.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
54781.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
54791.1Skamil
54801.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
54811.99Skamil			    sizeof(kp_sigignore)));
54821.99Skamil		}
54831.1Skamil
54841.99Skamil		SYSCALL_REQUIRE(
54851.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54861.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
54871.1Skamil
54881.99Skamil		child2 = state.pe_other_pid;
54891.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
54901.99Skamil		    child2);
54911.1Skamil
54921.99Skamil		DPRINTF("Before resuming the child process where it left off "
54931.99Skamil		    "and without signal to be sent\n");
54941.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54951.99Skamil	}
54961.1Skamil
54971.99Skamil	if (trackfork || trackvfork) {
54981.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
54991.99Skamil		    "\n", TWAIT_FNAME);
55001.99Skamil		TWAIT_REQUIRE_SUCCESS(
55011.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
55021.1Skamil
55031.99Skamil		validate_status_exited(status, exitval2);
55041.1Skamil
55051.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
55061.99Skamil		    "process\n", TWAIT_FNAME);
55071.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
55081.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
55091.99Skamil	}
55101.1Skamil
55111.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
55121.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
55131.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55141.1Skamil
55151.1Skamil	validate_status_stopped(status, SIGCHLD);
55161.1Skamil
55171.57Skamil	DPRINTF("Before resuming the child process where it left off and "
55181.1Skamil	    "without signal to be sent\n");
55191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55201.1Skamil
55211.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55221.1Skamil	    TWAIT_FNAME);
55231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55241.1Skamil
55251.1Skamil	validate_status_exited(status, exitval);
55261.1Skamil
55271.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55281.57Skamil	    TWAIT_FNAME);
55291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55301.1Skamil}
55311.1Skamil
55321.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone,		\
55331.99Skamil                   masked,ignored)					\
55341.99SkamilATF_TC(name);								\
55351.99SkamilATF_TC_HEAD(name, tc)							\
55361.99Skamil{									\
55371.99Skamil	atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught "	\
55381.99Skamil	    "regardless of signal %s%s", 				\
55391.99Skamil	    trackfork ? "PTRACE_FORK" : "",				\
55401.99Skamil	    trackvfork ? "PTRACE_VFORK" : "",				\
55411.99Skamil	    trackvforkdone ? "PTRACE_VFORK_DONE" : "",			\
55421.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
55431.99Skamil}									\
55441.99Skamil									\
55451.99SkamilATF_TC_BODY(name, tc)							\
55461.99Skamil{									\
55471.99Skamil									\
55481.99Skamil	fork2_body(trackfork, trackvfork, trackvforkdone, masked,	\
55491.99Skamil	           ignored);						\
55501.1Skamil}
55511.1Skamil
55521.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false)
55531.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true)
55541.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false)
55551.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true)
55561.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false)
55571.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true)
55581.1Skamil#endif
55591.1Skamil
55601.99Skamil/// ----------------------------------------------------------------------------
55611.1Skamil
55621.83Skamilvolatile lwpid_t the_lwp_id = 0;
55631.83Skamil
55641.83Skamilstatic void
55651.83Skamillwp_main_func(void *arg)
55661.83Skamil{
55671.83Skamil	the_lwp_id = _lwp_self();
55681.83Skamil	_lwp_exit();
55691.83Skamil}
55701.83Skamil
55711.1SkamilATF_TC(signal9);
55721.1SkamilATF_TC_HEAD(signal9, tc)
55731.1Skamil{
55741.1Skamil	atf_tc_set_md_var(tc, "descr",
55751.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
55761.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
55771.1Skamil}
55781.1Skamil
55791.1SkamilATF_TC_BODY(signal9, tc)
55801.1Skamil{
55811.1Skamil	const int exitval = 5;
55821.1Skamil	const int sigval = SIGSTOP;
55831.1Skamil	const int sigmasked = SIGTRAP;
55841.1Skamil	pid_t child, wpid;
55851.1Skamil#if defined(TWAIT_HAVE_STATUS)
55861.1Skamil	int status;
55871.1Skamil#endif
55881.1Skamil	sigset_t intmask;
55891.1Skamil	ptrace_state_t state;
55901.1Skamil	const int slen = sizeof(state);
55911.1Skamil	ptrace_event_t event;
55921.1Skamil	const int elen = sizeof(event);
55931.1Skamil	ucontext_t uc;
55941.1Skamil	lwpid_t lid;
55951.1Skamil	static const size_t ssize = 16*1024;
55961.1Skamil	void *stack;
55971.1Skamil
55981.14Schristos	atf_tc_expect_fail("PR kern/51918");
55991.14Schristos
56001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56021.1Skamil	if (child == 0) {
56031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56051.1Skamil
56061.1Skamil		sigemptyset(&intmask);
56071.1Skamil		sigaddset(&intmask, sigmasked);
56081.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56091.1Skamil
56101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56121.1Skamil
56131.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
56141.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
56151.1Skamil
56161.13Schristos		DPRINTF("Before making context for new lwp in child\n");
56171.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
56181.1Skamil
56191.13Schristos		DPRINTF("Before creating new in child\n");
56201.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
56211.1Skamil
56221.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
56231.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
56241.1Skamil
56251.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
56261.1Skamil		    "are the same\n", lid, the_lwp_id);
56271.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
56281.1Skamil
56291.13Schristos		DPRINTF("Before exiting of the child process\n");
56301.1Skamil		_exit(exitval);
56311.1Skamil	}
56321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56331.1Skamil
56341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56361.1Skamil
56371.1Skamil	validate_status_stopped(status, sigval);
56381.1Skamil
56391.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
56401.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
56411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
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	    "SIGTRAP\n", TWAIT_FNAME);
56491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56501.1Skamil
56511.1Skamil	validate_status_stopped(status, sigmasked);
56521.1Skamil
56531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
56541.1Skamil
56551.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
56561.1Skamil
56571.1Skamil	lid = state.pe_lwp;
56581.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
56591.1Skamil
56601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56611.1Skamil	    "without signal to be sent\n");
56621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56631.1Skamil
56641.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
56651.1Skamil	    TWAIT_FNAME);
56661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56671.1Skamil
56681.1Skamil	validate_status_exited(status, exitval);
56691.1Skamil
56701.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
56711.1Skamil	    TWAIT_FNAME);
56721.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56731.1Skamil}
56741.1Skamil
56751.1SkamilATF_TC(signal10);
56761.1SkamilATF_TC_HEAD(signal10, tc)
56771.1Skamil{
56781.1Skamil	atf_tc_set_md_var(tc, "descr",
56791.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
56801.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
56811.1Skamil}
56821.1Skamil
56831.1SkamilATF_TC_BODY(signal10, tc)
56841.1Skamil{
56851.1Skamil	const int exitval = 5;
56861.1Skamil	const int sigval = SIGSTOP;
56871.1Skamil	const int sigmasked = SIGTRAP;
56881.1Skamil	pid_t child, wpid;
56891.1Skamil#if defined(TWAIT_HAVE_STATUS)
56901.1Skamil	int status;
56911.1Skamil#endif
56921.1Skamil	sigset_t intmask;
56931.1Skamil	ptrace_state_t state;
56941.1Skamil	const int slen = sizeof(state);
56951.1Skamil	ptrace_event_t event;
56961.1Skamil	const int elen = sizeof(event);
56971.1Skamil	ucontext_t uc;
56981.1Skamil	lwpid_t lid;
56991.1Skamil	static const size_t ssize = 16*1024;
57001.1Skamil	void *stack;
57011.1Skamil
57021.14Schristos	atf_tc_expect_fail("PR kern/51918");
57031.14Schristos
57041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57061.1Skamil	if (child == 0) {
57071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57091.1Skamil
57101.1Skamil		sigemptyset(&intmask);
57111.1Skamil		sigaddset(&intmask, sigmasked);
57121.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57131.1Skamil
57141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57161.1Skamil
57171.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
57181.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
57191.1Skamil
57201.13Schristos		DPRINTF("Before making context for new lwp in child\n");
57211.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
57221.1Skamil
57231.13Schristos		DPRINTF("Before creating new in child\n");
57241.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
57251.1Skamil
57261.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
57271.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
57281.1Skamil
57291.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
57301.1Skamil		    "are the same\n", lid, the_lwp_id);
57311.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
57321.1Skamil
57331.13Schristos		DPRINTF("Before exiting of the child process\n");
57341.1Skamil		_exit(exitval);
57351.1Skamil	}
57361.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57371.1Skamil
57381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57401.1Skamil
57411.1Skamil	validate_status_stopped(status, sigval);
57421.1Skamil
57431.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
57441.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
57451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
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_CONTINUE, child, (void *)1, 0) != -1);
57501.1Skamil
57511.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
57521.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
57531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57541.1Skamil
57551.1Skamil	validate_status_stopped(status, sigmasked);
57561.1Skamil
57571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
57581.1Skamil
57591.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
57601.1Skamil
57611.1Skamil	lid = state.pe_lwp;
57621.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
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 - expected exited\n",
57691.1Skamil	    TWAIT_FNAME);
57701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57711.1Skamil
57721.1Skamil	validate_status_exited(status, exitval);
57731.1Skamil
57741.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
57751.1Skamil	    TWAIT_FNAME);
57761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57771.1Skamil}
57781.1Skamil
57791.1Skamilstatic void
57801.1Skamillwp_main_stop(void *arg)
57811.1Skamil{
57821.1Skamil	the_lwp_id = _lwp_self();
57831.1Skamil
57841.1Skamil	raise(SIGTRAP);
57851.1Skamil
57861.1Skamil	_lwp_exit();
57871.1Skamil}
57881.1Skamil
57891.1SkamilATF_TC(suspend1);
57901.1SkamilATF_TC_HEAD(suspend1, tc)
57911.1Skamil{
57921.1Skamil	atf_tc_set_md_var(tc, "descr",
57931.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
57941.1Skamil	    "resumed by a tracee");
57951.1Skamil}
57961.1Skamil
57971.1SkamilATF_TC_BODY(suspend1, tc)
57981.1Skamil{
57991.1Skamil	const int exitval = 5;
58001.1Skamil	const int sigval = SIGSTOP;
58011.1Skamil	pid_t child, wpid;
58021.1Skamil#if defined(TWAIT_HAVE_STATUS)
58031.1Skamil	int status;
58041.1Skamil#endif
58051.1Skamil	ucontext_t uc;
58061.1Skamil	lwpid_t lid;
58071.1Skamil	static const size_t ssize = 16*1024;
58081.1Skamil	void *stack;
58091.1Skamil	struct ptrace_lwpinfo pl;
58101.1Skamil	struct ptrace_siginfo psi;
58111.1Skamil	volatile int go = 0;
58121.1Skamil
58131.17Skamil	// Feature pending for refactoring
58141.17Skamil	atf_tc_expect_fail("PR kern/51995");
58151.17Skamil
58161.16Skamil	// Hangs with qemu
58171.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
58181.16Skamil
58191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58211.1Skamil	if (child == 0) {
58221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58241.1Skamil
58251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58271.1Skamil
58281.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
58291.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
58301.1Skamil
58311.13Schristos		DPRINTF("Before making context for new lwp in child\n");
58321.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
58331.1Skamil
58341.13Schristos		DPRINTF("Before creating new in child\n");
58351.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
58361.1Skamil
58371.1Skamil		while (go == 0)
58381.1Skamil			continue;
58391.1Skamil
58401.1Skamil		raise(SIGINT);
58411.1Skamil
58421.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
58431.1Skamil
58441.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
58451.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
58461.1Skamil
58471.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
58481.1Skamil		    "are the same\n", lid, the_lwp_id);
58491.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
58501.1Skamil
58511.13Schristos		DPRINTF("Before exiting of the child process\n");
58521.1Skamil		_exit(exitval);
58531.1Skamil	}
58541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58551.1Skamil
58561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58581.1Skamil
58591.1Skamil	validate_status_stopped(status, sigval);
58601.1Skamil
58611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58621.1Skamil	    "without signal to be sent\n");
58631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58641.1Skamil
58651.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
58661.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
58671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58681.1Skamil
58691.1Skamil	validate_status_stopped(status, SIGTRAP);
58701.1Skamil
58711.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
58721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
58731.1Skamil
58741.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
58751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
58761.1Skamil
58771.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
58781.1Skamil	    child, getpid());
58791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
58801.1Skamil
58811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58821.1Skamil	    "without signal to be sent\n");
58831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58841.1Skamil
58851.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
58861.1Skamil	    "SIGINT\n", TWAIT_FNAME);
58871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58881.1Skamil
58891.1Skamil	validate_status_stopped(status, SIGINT);
58901.1Skamil
58911.1Skamil	pl.pl_lwpid = 0;
58921.1Skamil
58931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
58941.1Skamil	while (pl.pl_lwpid != 0) {
58951.1Skamil
58961.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
58971.1Skamil		switch (pl.pl_lwpid) {
58981.1Skamil		case 1:
58991.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
59001.1Skamil			break;
59011.1Skamil		case 2:
59021.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
59031.1Skamil			break;
59041.1Skamil		}
59051.1Skamil	}
59061.1Skamil
59071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59081.1Skamil	    "without signal to be sent\n");
59091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59101.1Skamil
59111.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59121.1Skamil	    TWAIT_FNAME);
59131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59141.1Skamil
59151.1Skamil	validate_status_exited(status, exitval);
59161.1Skamil
59171.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59181.1Skamil	    TWAIT_FNAME);
59191.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59201.1Skamil}
59211.1Skamil
59221.1SkamilATF_TC(suspend2);
59231.1SkamilATF_TC_HEAD(suspend2, tc)
59241.1Skamil{
59251.1Skamil	atf_tc_set_md_var(tc, "descr",
59261.1Skamil	    "Verify that the while the only thread within a process is "
59271.1Skamil	    "suspended, the whole process cannot be unstopped");
59281.1Skamil}
59291.1Skamil
59301.1SkamilATF_TC_BODY(suspend2, tc)
59311.1Skamil{
59321.1Skamil	const int exitval = 5;
59331.1Skamil	const int sigval = SIGSTOP;
59341.1Skamil	pid_t child, wpid;
59351.1Skamil#if defined(TWAIT_HAVE_STATUS)
59361.1Skamil	int status;
59371.1Skamil#endif
59381.1Skamil	struct ptrace_siginfo psi;
59391.1Skamil
59401.17Skamil	// Feature pending for refactoring
59411.17Skamil	atf_tc_expect_fail("PR kern/51995");
59421.17Skamil
59431.16Skamil	// Hangs with qemu
59441.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
59451.16Skamil
59461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59481.1Skamil	if (child == 0) {
59491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59511.1Skamil
59521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59541.1Skamil
59551.13Schristos		DPRINTF("Before exiting of the child process\n");
59561.1Skamil		_exit(exitval);
59571.1Skamil	}
59581.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59591.1Skamil
59601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59621.1Skamil
59631.1Skamil	validate_status_stopped(status, sigval);
59641.1Skamil
59651.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
59661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
59671.1Skamil
59681.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
59691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
59701.1Skamil
59711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59721.1Skamil	    "without signal to be sent\n");
59731.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
59741.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
59751.1Skamil
59761.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
59771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
59781.1Skamil
59791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59801.1Skamil	    "without signal to be sent\n");
59811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59821.1Skamil
59831.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59841.1Skamil	    TWAIT_FNAME);
59851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59861.1Skamil
59871.1Skamil	validate_status_exited(status, exitval);
59881.1Skamil
59891.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59901.1Skamil	    TWAIT_FNAME);
59911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59921.1Skamil}
59931.1Skamil
59941.1SkamilATF_TC(resume1);
59951.1SkamilATF_TC_HEAD(resume1, tc)
59961.1Skamil{
59971.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
59981.1Skamil	atf_tc_set_md_var(tc, "descr",
59991.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
60001.1Skamil	    "resumed by the debugger");
60011.1Skamil}
60021.1Skamil
60031.1SkamilATF_TC_BODY(resume1, tc)
60041.1Skamil{
60051.1Skamil	struct msg_fds fds;
60061.1Skamil	const int exitval = 5;
60071.1Skamil	const int sigval = SIGSTOP;
60081.1Skamil	pid_t child, wpid;
60091.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
60101.1Skamil#if defined(TWAIT_HAVE_STATUS)
60111.1Skamil	int status;
60121.1Skamil#endif
60131.1Skamil	ucontext_t uc;
60141.1Skamil	lwpid_t lid;
60151.1Skamil	static const size_t ssize = 16*1024;
60161.1Skamil	void *stack;
60171.1Skamil	struct ptrace_lwpinfo pl;
60181.1Skamil	struct ptrace_siginfo psi;
60191.1Skamil
60201.17Skamil	// Feature pending for refactoring
60211.17Skamil	atf_tc_expect_fail("PR kern/51995");
60221.17Skamil
60231.15Schristos	// Hangs with qemu
60241.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
60251.1Skamil
60261.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
60271.1Skamil
60281.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60291.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60301.1Skamil	if (child == 0) {
60311.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60321.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60331.1Skamil
60341.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60351.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60361.1Skamil
60371.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
60381.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
60391.1Skamil
60401.13Schristos		DPRINTF("Before making context for new lwp in child\n");
60411.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
60421.1Skamil
60431.13Schristos		DPRINTF("Before creating new in child\n");
60441.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
60451.1Skamil
60461.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
60471.1Skamil
60481.1Skamil		raise(SIGINT);
60491.1Skamil
60501.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
60511.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
60521.1Skamil
60531.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
60541.1Skamil		    "are the same\n", lid, the_lwp_id);
60551.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
60561.1Skamil
60571.13Schristos		DPRINTF("Before exiting of the child process\n");
60581.1Skamil		_exit(exitval);
60591.1Skamil	}
60601.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60611.1Skamil
60621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60641.1Skamil
60651.1Skamil	validate_status_stopped(status, sigval);
60661.1Skamil
60671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60681.1Skamil	    "without signal to be sent\n");
60691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60701.1Skamil
60711.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60721.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
60731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60741.1Skamil
60751.1Skamil	validate_status_stopped(status, SIGTRAP);
60761.1Skamil
60771.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
60781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
60791.1Skamil
60801.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
60811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
60821.1Skamil
60831.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
60841.1Skamil
60851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60861.1Skamil	    "without signal to be sent\n");
60871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60881.1Skamil
60891.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60901.1Skamil	    "SIGINT\n", TWAIT_FNAME);
60911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60921.1Skamil
60931.1Skamil	validate_status_stopped(status, SIGINT);
60941.1Skamil
60951.1Skamil	pl.pl_lwpid = 0;
60961.1Skamil
60971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
60981.1Skamil	while (pl.pl_lwpid != 0) {
60991.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
61001.1Skamil		switch (pl.pl_lwpid) {
61011.1Skamil		case 1:
61021.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
61031.1Skamil			break;
61041.1Skamil		case 2:
61051.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
61061.1Skamil			break;
61071.1Skamil		}
61081.1Skamil	}
61091.1Skamil
61101.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
61111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
61121.1Skamil
61131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61141.1Skamil	    "without signal to be sent\n");
61151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61161.1Skamil
61171.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61181.1Skamil	    TWAIT_FNAME);
61191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61201.1Skamil
61211.1Skamil	validate_status_exited(status, exitval);
61221.1Skamil
61231.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61241.1Skamil	    TWAIT_FNAME);
61251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61261.1Skamil
61271.1Skamil	msg_close(&fds);
61281.1Skamil
61291.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
61301.1Skamil	sleep(10);
61311.1Skamil}
61321.1Skamil
61331.1SkamilATF_TC(syscall1);
61341.1SkamilATF_TC_HEAD(syscall1, tc)
61351.1Skamil{
61361.1Skamil	atf_tc_set_md_var(tc, "descr",
61371.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
61381.1Skamil}
61391.1Skamil
61401.1SkamilATF_TC_BODY(syscall1, tc)
61411.1Skamil{
61421.1Skamil	const int exitval = 5;
61431.1Skamil	const int sigval = SIGSTOP;
61441.1Skamil	pid_t child, wpid;
61451.1Skamil#if defined(TWAIT_HAVE_STATUS)
61461.1Skamil	int status;
61471.1Skamil#endif
61481.1Skamil	struct ptrace_siginfo info;
61491.1Skamil	memset(&info, 0, sizeof(info));
61501.1Skamil
61511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61531.1Skamil	if (child == 0) {
61541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61561.1Skamil
61571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61591.1Skamil
61601.1Skamil		syscall(SYS_getpid);
61611.1Skamil
61621.13Schristos		DPRINTF("Before exiting of the child process\n");
61631.1Skamil		_exit(exitval);
61641.1Skamil	}
61651.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61661.1Skamil
61671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61691.1Skamil
61701.1Skamil	validate_status_stopped(status, sigval);
61711.1Skamil
61721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61731.1Skamil	    "without signal to be sent\n");
61741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
61751.1Skamil
61761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61781.1Skamil
61791.1Skamil	validate_status_stopped(status, SIGTRAP);
61801.1Skamil
61811.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
61821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
61831.1Skamil
61841.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
61851.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
61861.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
61871.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
61881.1Skamil
61891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61901.1Skamil	    "without signal to be sent\n");
61911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
61921.1Skamil
61931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61951.1Skamil
61961.1Skamil	validate_status_stopped(status, SIGTRAP);
61971.1Skamil
61981.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
61991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
62001.1Skamil
62011.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
62021.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
62031.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
62041.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
62051.1Skamil
62061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62071.1Skamil	    "without signal to be sent\n");
62081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62091.1Skamil
62101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62121.1Skamil
62131.1Skamil	validate_status_exited(status, exitval);
62141.1Skamil
62151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62171.1Skamil}
62181.1Skamil
62191.1SkamilATF_TC(syscallemu1);
62201.1SkamilATF_TC_HEAD(syscallemu1, tc)
62211.1Skamil{
62221.1Skamil	atf_tc_set_md_var(tc, "descr",
62231.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
62241.1Skamil}
62251.1Skamil
62261.1SkamilATF_TC_BODY(syscallemu1, tc)
62271.1Skamil{
62281.1Skamil	const int exitval = 5;
62291.1Skamil	const int sigval = SIGSTOP;
62301.1Skamil	pid_t child, wpid;
62311.1Skamil#if defined(TWAIT_HAVE_STATUS)
62321.1Skamil	int status;
62331.1Skamil#endif
62341.1Skamil
62351.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
62361.6Skamil	/* syscallemu does not work on sparc (32-bit) */
62371.6Skamil	atf_tc_expect_fail("PR kern/52166");
62381.6Skamil#endif
62391.6Skamil
62401.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62411.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62421.1Skamil	if (child == 0) {
62431.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62441.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62451.1Skamil
62461.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62471.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62481.1Skamil
62491.1Skamil		syscall(SYS_exit, 100);
62501.1Skamil
62511.13Schristos		DPRINTF("Before exiting of the child process\n");
62521.1Skamil		_exit(exitval);
62531.1Skamil	}
62541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62551.1Skamil
62561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62581.1Skamil
62591.1Skamil	validate_status_stopped(status, sigval);
62601.1Skamil
62611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62621.1Skamil	    "without signal to be sent\n");
62631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
62641.1Skamil
62651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62671.1Skamil
62681.1Skamil	validate_status_stopped(status, SIGTRAP);
62691.1Skamil
62701.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
62711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
62721.1Skamil
62731.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62741.1Skamil	    "without signal to be sent\n");
62751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
62761.1Skamil
62771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62791.1Skamil
62801.1Skamil	validate_status_stopped(status, SIGTRAP);
62811.1Skamil
62821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62831.1Skamil	    "without signal to be sent\n");
62841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62851.1Skamil
62861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62881.1Skamil
62891.1Skamil	validate_status_exited(status, exitval);
62901.1Skamil
62911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62931.1Skamil}
62941.1Skamil
62951.1Skamil#include "t_ptrace_amd64_wait.h"
62961.1Skamil#include "t_ptrace_i386_wait.h"
62971.1Skamil#include "t_ptrace_x86_wait.h"
62981.1Skamil
62991.1SkamilATF_TP_ADD_TCS(tp)
63001.1Skamil{
63011.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
63021.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
63031.33Skamil
63041.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
63051.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
63061.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
63071.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
63081.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
63091.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
63101.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
63111.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
63121.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
63131.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
63141.33Skamil
63151.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
63161.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
63171.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
63181.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
63191.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
63201.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
63211.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
63221.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
63231.87Skamil
63241.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
63251.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
63261.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
63271.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
63281.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
63291.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
63301.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
63311.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
63321.86Skamil
63331.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
63341.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
63351.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
63361.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
63371.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
63381.59Skamil
63391.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
63401.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
63411.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
63421.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
63431.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
63441.88Skamil
63451.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
63461.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
63471.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
63481.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
63491.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
63501.88Skamil
63511.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
63521.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
63531.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
63541.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
63551.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
63561.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
63571.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
63581.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
63591.50Skamil
63601.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
63611.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
63621.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
63631.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
63641.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
63651.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
63661.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
63671.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
63681.50Skamil
63691.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
63701.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
63711.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
63721.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
63731.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
63741.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
63751.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
63761.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
63771.50Skamil
63781.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
63791.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
63801.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
63811.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
63821.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
63831.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
63841.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
63851.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
63861.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
63871.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
63881.1Skamil
63891.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
63901.37Skamil
63911.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
63921.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
63931.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
63941.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
63951.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
63961.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
63971.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
63981.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
63991.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
64001.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
64011.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
64021.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
64031.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
64041.40Skamil
64051.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
64061.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
64071.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
64081.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
64091.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
64101.41Skamil
64111.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
64121.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
64131.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
64141.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
64151.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
64161.92Skamil
64171.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
64181.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
64191.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
64201.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
64211.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
64221.92Skamil
64231.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
64241.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
64251.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
64261.43Skamil
64271.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
64281.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
64291.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
64301.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
64311.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
64321.59Skamil
64331.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64341.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
64351.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64361.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
64371.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64381.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
64391.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64401.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
64411.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64421.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
64431.94Skamil
64441.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64451.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
64461.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64471.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
64481.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64491.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
64501.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64511.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
64521.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64531.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
64541.94Skamil
64551.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
64561.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
64571.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
64581.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
64591.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
64601.51Skamil
64611.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
64621.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
64631.51Skamil
64641.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
64651.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
64661.51Skamil
64671.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64681.51Skamil		tracee_sees_its_original_parent_getppid);
64691.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64701.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
64711.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
64721.51Skamil		tracee_sees_its_original_parent_procfs_status);
64731.1Skamil
64741.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
64751.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
64761.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
64771.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
64781.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
64791.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
64801.1Skamil
64811.31Skamil	ATF_TP_ADD_TC(tp, fork1);
64821.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
64831.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
64841.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
64851.31Skamil	ATF_TP_ADD_TC(tp, fork5);
64861.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
64871.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
64881.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
64891.31Skamil
64901.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
64911.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
64921.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
64931.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
64941.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
64951.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
64961.64Smartin// thes tests hang on SMP machines, disable them for now
64971.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
64981.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
64991.1Skamil
65001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
65011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
65021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
65031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
65041.54Skamil
65051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
65061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
65071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
65081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
65091.54Skamil
65101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
65111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
65121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
65131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
65141.54Skamil
65151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
65161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
65171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
65181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
65191.54Skamil
65201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
65211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
65221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
65231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
65241.54Skamil
65251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
65261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
65271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
65281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
65291.54Skamil
65301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
65311.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
65321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
65331.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
65341.54Skamil
65351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
65361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
65371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
65381.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
65391.54Skamil
65401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
65411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
65421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
65431.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
65441.54Skamil
65451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
65461.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
65471.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
65481.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
65491.1Skamil
65501.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
65511.1Skamil
65521.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i);
65531.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d);
65541.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i);
65551.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d);
65561.101Skamil
65571.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i);
65581.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d);
65591.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i);
65601.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d);
65611.101Skamil
65621.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv);
65631.101Skamil
65641.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
65651.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
65661.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
65671.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
65681.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
65691.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
65701.1Skamil
65711.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
65721.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
65731.1Skamil
65741.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
65751.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
65761.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
65771.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
65781.1Skamil
65791.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
65801.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
65811.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
65821.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
65831.2Skamil
65841.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
65851.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
65861.95Skamil
65871.1Skamil	ATF_TP_ADD_TC(tp, kill1);
65881.1Skamil	ATF_TP_ADD_TC(tp, kill2);
65891.75Skamil	ATF_TP_ADD_TC(tp, kill3);
65901.1Skamil
65911.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
65921.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
65931.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
65941.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
65951.77Skamil
65961.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
65971.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
65981.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
65991.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
66001.1Skamil
66011.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
66021.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
66031.79Skamil
66041.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
66051.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
66061.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
66071.1Skamil
66081.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
66091.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
66101.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
66111.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
66121.1Skamil
66131.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
66141.84Skamil
66151.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
66161.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
66171.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
66181.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
66191.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
66201.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
66211.99Skamil
66221.1Skamil	ATF_TP_ADD_TC(tp, signal9);
66231.1Skamil	ATF_TP_ADD_TC(tp, signal10);
66241.1Skamil
66251.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
66261.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
66271.1Skamil
66281.1Skamil	ATF_TP_ADD_TC(tp, resume1);
66291.1Skamil
66301.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
66311.1Skamil
66321.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
66331.1Skamil
66341.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
66351.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
66361.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
66371.1Skamil
66381.1Skamil	return atf_no_error();
66391.1Skamil}
6640