t_ptrace_wait.c revision 1.112
11.112Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.112 2019/04/25 11:45:12 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.112Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.112 2019/04/25 11:45:12 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.110Skamil#ifndef TEST_VFORK_ENABLED
911.109Skamil#define TEST_VFORK_ENABLED 0
921.110Skamil#endif
931.109Skamil
941.34Skamil/// ----------------------------------------------------------------------------
951.34Skamil
961.33Skamilstatic void
971.33Skamiltraceme_raise(int sigval)
981.1Skamil{
991.1Skamil	const int exitval = 5;
1001.1Skamil	pid_t child, wpid;
1011.1Skamil#if defined(TWAIT_HAVE_STATUS)
1021.1Skamil	int status;
1031.1Skamil#endif
1041.1Skamil
1051.45Skamil	struct ptrace_siginfo info;
1061.45Skamil	memset(&info, 0, sizeof(info));
1071.45Skamil
1081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1101.1Skamil	if (child == 0) {
1111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1131.1Skamil
1141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1161.1Skamil
1171.36Skamil		switch (sigval) {
1181.36Skamil		case SIGKILL:
1191.36Skamil			/* NOTREACHED */
1201.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1211.70Smrg			__unreachable();
1221.36Skamil		default:
1231.36Skamil			DPRINTF("Before exiting of the child process\n");
1241.36Skamil			_exit(exitval);
1251.36Skamil		}
1261.1Skamil	}
1271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1281.1Skamil
1291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1311.1Skamil
1321.36Skamil	switch (sigval) {
1331.36Skamil	case SIGKILL:
1341.36Skamil		validate_status_signaled(status, sigval, 0);
1351.36Skamil		break;
1361.36Skamil	default:
1371.36Skamil		validate_status_stopped(status, sigval);
1381.1Skamil
1391.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1401.61Skre			"child\n");
1411.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1421.61Skre			sizeof(info)) != -1);
1431.45Skamil
1441.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1451.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1461.61Skre			"si_errno=%#x\n",
1471.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1481.61Skre			info.psi_siginfo.si_errno);
1491.45Skamil
1501.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1511.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1521.45Skamil
1531.36Skamil		DPRINTF("Before resuming the child process where it left off "
1541.36Skamil		    "and without signal to be sent\n");
1551.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1561.1Skamil
1571.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1581.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1591.61Skre		    child);
1601.36Skamil		break;
1611.36Skamil	}
1621.1Skamil
1631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1651.1Skamil}
1661.1Skamil
1671.61Skre#define TRACEME_RAISE(test, sig)					\
1681.61SkreATF_TC(test);								\
1691.61SkreATF_TC_HEAD(test, tc)							\
1701.61Skre{									\
1711.61Skre	atf_tc_set_md_var(tc, "descr",					\
1721.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1731.61Skre}									\
1741.61Skre									\
1751.61SkreATF_TC_BODY(test, tc)							\
1761.61Skre{									\
1771.61Skre									\
1781.61Skre	traceme_raise(sig);						\
1791.33Skamil}
1801.33Skamil
1811.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1821.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1831.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1841.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1851.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1861.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1871.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1881.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1891.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
1901.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
1911.33Skamil
1921.34Skamil/// ----------------------------------------------------------------------------
1931.1Skamil
1941.1Skamilstatic void
1951.87Skamiltraceme_raisesignal_ignored(int sigignored)
1961.87Skamil{
1971.87Skamil	const int exitval = 5;
1981.87Skamil	const int sigval = SIGSTOP;
1991.87Skamil	pid_t child, wpid;
2001.87Skamil	struct sigaction sa;
2011.87Skamil#if defined(TWAIT_HAVE_STATUS)
2021.87Skamil	int status;
2031.87Skamil#endif
2041.87Skamil	struct ptrace_siginfo info;
2051.87Skamil
2061.87Skamil	memset(&info, 0, sizeof(info));
2071.87Skamil
2081.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2091.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2101.87Skamil	if (child == 0) {
2111.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2121.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2131.87Skamil
2141.87Skamil		memset(&sa, 0, sizeof(sa));
2151.87Skamil		sa.sa_handler = SIG_IGN;
2161.87Skamil		sigemptyset(&sa.sa_mask);
2171.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2181.87Skamil
2191.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2201.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2211.87Skamil
2221.87Skamil		DPRINTF("Before raising %s from child\n",
2231.87Skamil		    strsignal(sigignored));
2241.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2251.87Skamil
2261.87Skamil		DPRINTF("Before exiting of the child process\n");
2271.87Skamil		_exit(exitval);
2281.87Skamil	}
2291.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2301.87Skamil
2311.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2321.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2331.87Skamil
2341.87Skamil	validate_status_stopped(status, sigval);
2351.87Skamil
2361.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2371.87Skamil	SYSCALL_REQUIRE(
2381.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2391.87Skamil
2401.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2411.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2421.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2431.87Skamil	    info.psi_siginfo.si_errno);
2441.87Skamil
2451.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2461.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2471.87Skamil
2481.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2491.87Skamil	    "without signal to be sent\n");
2501.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2511.87Skamil
2521.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2531.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2541.87Skamil
2551.87Skamil	validate_status_stopped(status, sigignored);
2561.87Skamil
2571.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2581.87Skamil	SYSCALL_REQUIRE(
2591.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2601.87Skamil
2611.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2621.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2631.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2641.87Skamil	    info.psi_siginfo.si_errno);
2651.87Skamil
2661.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2671.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2681.87Skamil
2691.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2701.87Skamil	    "without signal to be sent\n");
2711.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2721.87Skamil
2731.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2741.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2751.87Skamil
2761.87Skamil	validate_status_exited(status, exitval);
2771.87Skamil
2781.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2791.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2801.87Skamil}
2811.87Skamil
2821.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2831.87SkamilATF_TC(test);								\
2841.87SkamilATF_TC_HEAD(test, tc)							\
2851.87Skamil{									\
2861.87Skamil	atf_tc_set_md_var(tc, "descr",					\
2871.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
2881.87Skamil	    "does not stop tracer from catching this raised signal");	\
2891.87Skamil}									\
2901.87Skamil									\
2911.87SkamilATF_TC_BODY(test, tc)							\
2921.87Skamil{									\
2931.87Skamil									\
2941.87Skamil	traceme_raisesignal_ignored(sig);				\
2951.87Skamil}
2961.87Skamil
2971.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
2981.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
2991.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
3001.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
3011.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
3021.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
3031.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3041.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3051.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3061.87Skamil
3071.87Skamil/// ----------------------------------------------------------------------------
3081.87Skamil
3091.87Skamilstatic void
3101.86Skamiltraceme_raisesignal_masked(int sigmasked)
3111.86Skamil{
3121.86Skamil	const int exitval = 5;
3131.86Skamil	const int sigval = SIGSTOP;
3141.86Skamil	pid_t child, wpid;
3151.86Skamil#if defined(TWAIT_HAVE_STATUS)
3161.86Skamil	int status;
3171.86Skamil#endif
3181.86Skamil	sigset_t intmask;
3191.86Skamil	struct ptrace_siginfo info;
3201.86Skamil
3211.86Skamil	memset(&info, 0, sizeof(info));
3221.86Skamil
3231.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3241.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3251.86Skamil	if (child == 0) {
3261.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3271.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3281.86Skamil
3291.86Skamil		sigemptyset(&intmask);
3301.86Skamil		sigaddset(&intmask, sigmasked);
3311.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3321.86Skamil
3331.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3341.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3351.86Skamil
3361.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3371.86Skamil		    strsignal(sigmasked));
3381.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3391.86Skamil
3401.86Skamil		DPRINTF("Before exiting of the child process\n");
3411.86Skamil		_exit(exitval);
3421.86Skamil	}
3431.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3441.86Skamil
3451.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3461.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3471.86Skamil
3481.86Skamil	validate_status_stopped(status, sigval);
3491.86Skamil
3501.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3511.86Skamil	SYSCALL_REQUIRE(
3521.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3531.86Skamil
3541.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3551.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3561.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3571.86Skamil	    info.psi_siginfo.si_errno);
3581.86Skamil
3591.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3601.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3611.86Skamil
3621.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3631.86Skamil	    "without signal to be sent\n");
3641.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3651.86Skamil
3661.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3671.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3681.86Skamil
3691.86Skamil	validate_status_exited(status, exitval);
3701.86Skamil
3711.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3721.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3731.86Skamil}
3741.86Skamil
3751.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3761.86SkamilATF_TC(test);								\
3771.86SkamilATF_TC_HEAD(test, tc)							\
3781.86Skamil{									\
3791.86Skamil	atf_tc_set_md_var(tc, "descr",					\
3801.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3811.86Skamil	    "stops tracer from catching this raised signal");		\
3821.86Skamil}									\
3831.86Skamil									\
3841.86SkamilATF_TC_BODY(test, tc)							\
3851.86Skamil{									\
3861.86Skamil									\
3871.86Skamil	traceme_raisesignal_masked(sig);				\
3881.86Skamil}
3891.86Skamil
3901.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
3911.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
3921.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
3931.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
3941.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
3951.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
3961.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
3971.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
3981.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
3991.86Skamil
4001.86Skamil/// ----------------------------------------------------------------------------
4011.86Skamil
4021.86Skamilstatic void
4031.59Skamiltraceme_crash(int sig)
4041.59Skamil{
4051.59Skamil	pid_t child, wpid;
4061.59Skamil#if defined(TWAIT_HAVE_STATUS)
4071.59Skamil	int status;
4081.59Skamil#endif
4091.59Skamil	struct ptrace_siginfo info;
4101.61Skre
4111.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4121.71Skamil	if (sig == SIGILL)
4131.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4141.71Skamil#endif
4151.71Skamil
4161.59Skamil	memset(&info, 0, sizeof(info));
4171.59Skamil
4181.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4191.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4201.59Skamil	if (child == 0) {
4211.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4221.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4231.59Skamil
4241.59Skamil		DPRINTF("Before executing a trap\n");
4251.59Skamil		switch (sig) {
4261.59Skamil		case SIGTRAP:
4271.59Skamil			trigger_trap();
4281.59Skamil			break;
4291.59Skamil		case SIGSEGV:
4301.59Skamil			trigger_segv();
4311.59Skamil			break;
4321.59Skamil		case SIGILL:
4331.59Skamil			trigger_ill();
4341.59Skamil			break;
4351.59Skamil		case SIGFPE:
4361.59Skamil			trigger_fpe();
4371.59Skamil			break;
4381.59Skamil		case SIGBUS:
4391.59Skamil			trigger_bus();
4401.59Skamil			break;
4411.59Skamil		default:
4421.59Skamil			/* NOTREACHED */
4431.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4441.59Skamil		}
4451.59Skamil
4461.59Skamil		/* NOTREACHED */
4471.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4481.59Skamil	}
4491.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4501.59Skamil
4511.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4521.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4531.59Skamil
4541.59Skamil	validate_status_stopped(status, sig);
4551.59Skamil
4561.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4571.61Skre	SYSCALL_REQUIRE(
4581.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4591.59Skamil
4601.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4611.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4621.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4631.61Skre	    info.psi_siginfo.si_errno);
4641.59Skamil
4651.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4661.59Skamil	switch (sig) {
4671.59Skamil	case SIGTRAP:
4681.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4691.59Skamil		break;
4701.59Skamil	case SIGSEGV:
4711.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4721.59Skamil		break;
4731.71Skamil	case SIGILL:
4741.112Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= 0 &&
4751.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
4761.71Skamil		break;
4771.59Skamil	case SIGFPE:
4781.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4791.59Skamil		break;
4801.59Skamil	case SIGBUS:
4811.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
4821.59Skamil		break;
4831.59Skamil	}
4841.59Skamil
4851.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
4861.59Skamil
4871.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4881.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4891.59Skamil
4901.59Skamil	validate_status_signaled(status, SIGKILL, 0);
4911.59Skamil
4921.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4931.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4941.59Skamil}
4951.59Skamil
4961.61Skre#define TRACEME_CRASH(test, sig)					\
4971.61SkreATF_TC(test);								\
4981.61SkreATF_TC_HEAD(test, tc)							\
4991.61Skre{									\
5001.61Skre	atf_tc_set_md_var(tc, "descr",					\
5011.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
5021.61Skre}									\
5031.61Skre									\
5041.61SkreATF_TC_BODY(test, tc)							\
5051.61Skre{									\
5061.61Skre									\
5071.61Skre	traceme_crash(sig);						\
5081.59Skamil}
5091.59Skamil
5101.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5111.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5121.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5131.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5141.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5151.59Skamil
5161.59Skamil/// ----------------------------------------------------------------------------
5171.59Skamil
5181.59Skamilstatic void
5191.88Skamiltraceme_signalmasked_crash(int sig)
5201.88Skamil{
5211.89Skamil	const int sigval = SIGSTOP;
5221.88Skamil	pid_t child, wpid;
5231.88Skamil#if defined(TWAIT_HAVE_STATUS)
5241.88Skamil	int status;
5251.88Skamil#endif
5261.88Skamil	struct ptrace_siginfo info;
5271.88Skamil	sigset_t intmask;
5281.89Skamil	struct kinfo_proc2 kp;
5291.89Skamil	size_t len = sizeof(kp);
5301.89Skamil
5311.89Skamil	int name[6];
5321.89Skamil	const size_t namelen = __arraycount(name);
5331.89Skamil	ki_sigset_t kp_sigmask;
5341.88Skamil
5351.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5361.88Skamil	if (sig == SIGILL)
5371.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5381.88Skamil#endif
5391.88Skamil
5401.88Skamil	memset(&info, 0, sizeof(info));
5411.88Skamil
5421.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5431.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5441.88Skamil	if (child == 0) {
5451.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5461.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5471.88Skamil
5481.88Skamil		sigemptyset(&intmask);
5491.88Skamil		sigaddset(&intmask, sig);
5501.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5511.88Skamil
5521.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5531.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5541.89Skamil
5551.88Skamil		DPRINTF("Before executing a trap\n");
5561.88Skamil		switch (sig) {
5571.88Skamil		case SIGTRAP:
5581.88Skamil			trigger_trap();
5591.88Skamil			break;
5601.88Skamil		case SIGSEGV:
5611.88Skamil			trigger_segv();
5621.88Skamil			break;
5631.88Skamil		case SIGILL:
5641.88Skamil			trigger_ill();
5651.88Skamil			break;
5661.88Skamil		case SIGFPE:
5671.88Skamil			trigger_fpe();
5681.88Skamil			break;
5691.88Skamil		case SIGBUS:
5701.88Skamil			trigger_bus();
5711.88Skamil			break;
5721.88Skamil		default:
5731.88Skamil			/* NOTREACHED */
5741.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5751.88Skamil		}
5761.88Skamil
5771.88Skamil		/* NOTREACHED */
5781.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5791.88Skamil	}
5801.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5811.88Skamil
5821.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5831.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5841.88Skamil
5851.89Skamil	validate_status_stopped(status, sigval);
5861.89Skamil
5871.89Skamil	name[0] = CTL_KERN,
5881.89Skamil	name[1] = KERN_PROC2,
5891.89Skamil	name[2] = KERN_PROC_PID;
5901.89Skamil	name[3] = child;
5911.89Skamil	name[4] = sizeof(kp);
5921.89Skamil	name[5] = 1;
5931.89Skamil
5941.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
5951.89Skamil
5961.89Skamil	kp_sigmask = kp.p_sigmask;
5971.89Skamil
5981.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5991.89Skamil	SYSCALL_REQUIRE(
6001.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6011.89Skamil
6021.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6031.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6041.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6051.89Skamil	    info.psi_siginfo.si_errno);
6061.89Skamil
6071.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6081.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6091.89Skamil
6101.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6111.89Skamil	    "without signal to be sent\n");
6121.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6131.89Skamil
6141.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6151.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6161.89Skamil
6171.88Skamil	validate_status_stopped(status, sig);
6181.88Skamil
6191.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6201.88Skamil	SYSCALL_REQUIRE(
6211.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6221.88Skamil
6231.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6241.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6251.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6261.88Skamil	    info.psi_siginfo.si_errno);
6271.88Skamil
6281.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6291.89Skamil
6301.89Skamil	DPRINTF("kp_sigmask="
6311.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6321.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6331.89Skamil	    kp_sigmask.__bits[3]);
6341.89Skamil
6351.89Skamil	DPRINTF("kp.p_sigmask="
6361.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6371.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6381.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6391.89Skamil
6401.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6411.89Skamil
6421.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6431.88Skamil	switch (sig) {
6441.88Skamil	case SIGTRAP:
6451.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6461.88Skamil		break;
6471.88Skamil	case SIGSEGV:
6481.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6491.88Skamil		break;
6501.88Skamil	case SIGILL:
6511.112Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= 0 &&
6521.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
6531.88Skamil		break;
6541.88Skamil	case SIGFPE:
6551.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6561.88Skamil		break;
6571.88Skamil	case SIGBUS:
6581.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6591.88Skamil		break;
6601.88Skamil	}
6611.88Skamil
6621.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6631.88Skamil
6641.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6651.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6661.88Skamil
6671.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6681.88Skamil
6691.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6701.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6711.88Skamil}
6721.88Skamil
6731.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6741.88SkamilATF_TC(test);								\
6751.88SkamilATF_TC_HEAD(test, tc)							\
6761.88Skamil{									\
6771.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6781.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6791.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6801.88Skamil}									\
6811.88Skamil									\
6821.88SkamilATF_TC_BODY(test, tc)							\
6831.88Skamil{									\
6841.88Skamil									\
6851.88Skamil	traceme_signalmasked_crash(sig);				\
6861.88Skamil}
6871.88Skamil
6881.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
6891.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
6901.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
6911.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
6921.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
6931.88Skamil
6941.88Skamil/// ----------------------------------------------------------------------------
6951.88Skamil
6961.88Skamilstatic void
6971.88Skamiltraceme_signalignored_crash(int sig)
6981.88Skamil{
6991.90Skamil	const int sigval = SIGSTOP;
7001.88Skamil	pid_t child, wpid;
7011.88Skamil#if defined(TWAIT_HAVE_STATUS)
7021.88Skamil	int status;
7031.88Skamil#endif
7041.88Skamil	struct sigaction sa;
7051.88Skamil	struct ptrace_siginfo info;
7061.90Skamil	struct kinfo_proc2 kp;
7071.90Skamil	size_t len = sizeof(kp);
7081.90Skamil
7091.90Skamil	int name[6];
7101.90Skamil	const size_t namelen = __arraycount(name);
7111.90Skamil	ki_sigset_t kp_sigignore;
7121.88Skamil
7131.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7141.88Skamil	if (sig == SIGILL)
7151.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7161.88Skamil#endif
7171.88Skamil
7181.88Skamil	memset(&info, 0, sizeof(info));
7191.88Skamil
7201.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7211.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7221.88Skamil	if (child == 0) {
7231.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7241.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7251.88Skamil
7261.88Skamil		memset(&sa, 0, sizeof(sa));
7271.88Skamil		sa.sa_handler = SIG_IGN;
7281.88Skamil		sigemptyset(&sa.sa_mask);
7291.88Skamil
7301.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7311.88Skamil
7321.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7331.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7341.90Skamil
7351.88Skamil		DPRINTF("Before executing a trap\n");
7361.88Skamil		switch (sig) {
7371.88Skamil		case SIGTRAP:
7381.88Skamil			trigger_trap();
7391.88Skamil			break;
7401.88Skamil		case SIGSEGV:
7411.88Skamil			trigger_segv();
7421.88Skamil			break;
7431.88Skamil		case SIGILL:
7441.88Skamil			trigger_ill();
7451.88Skamil			break;
7461.88Skamil		case SIGFPE:
7471.88Skamil			trigger_fpe();
7481.88Skamil			break;
7491.88Skamil		case SIGBUS:
7501.88Skamil			trigger_bus();
7511.88Skamil			break;
7521.88Skamil		default:
7531.88Skamil			/* NOTREACHED */
7541.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7551.88Skamil		}
7561.88Skamil
7571.88Skamil		/* NOTREACHED */
7581.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7591.88Skamil	}
7601.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7611.88Skamil
7621.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7631.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7641.88Skamil
7651.90Skamil	validate_status_stopped(status, sigval);
7661.90Skamil
7671.90Skamil	name[0] = CTL_KERN,
7681.90Skamil	name[1] = KERN_PROC2,
7691.90Skamil	name[2] = KERN_PROC_PID;
7701.90Skamil	name[3] = child;
7711.90Skamil	name[4] = sizeof(kp);
7721.90Skamil	name[5] = 1;
7731.90Skamil
7741.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
7751.90Skamil
7761.90Skamil	kp_sigignore = kp.p_sigignore;
7771.90Skamil
7781.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7791.90Skamil	SYSCALL_REQUIRE(
7801.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7811.90Skamil
7821.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7831.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7841.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7851.90Skamil	    info.psi_siginfo.si_errno);
7861.90Skamil
7871.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
7881.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
7891.90Skamil
7901.90Skamil	DPRINTF("Before resuming the child process where it left off and "
7911.90Skamil	    "without signal to be sent\n");
7921.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
7931.90Skamil
7941.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7951.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7961.90Skamil
7971.88Skamil	validate_status_stopped(status, sig);
7981.88Skamil
7991.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
8001.88Skamil	SYSCALL_REQUIRE(
8011.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8021.88Skamil
8031.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8041.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8051.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8061.88Skamil	    info.psi_siginfo.si_errno);
8071.88Skamil
8081.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8091.90Skamil
8101.90Skamil	DPRINTF("kp_sigignore="
8111.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8121.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8131.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8141.90Skamil
8151.90Skamil	DPRINTF("kp.p_sigignore="
8161.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8171.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8181.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8191.90Skamil
8201.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8211.90Skamil
8221.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8231.88Skamil	switch (sig) {
8241.88Skamil	case SIGTRAP:
8251.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8261.88Skamil		break;
8271.88Skamil	case SIGSEGV:
8281.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8291.88Skamil		break;
8301.88Skamil	case SIGILL:
8311.112Skamil		ATF_REQUIRE(info.psi_siginfo.si_code >= 0 &&
8321.112Skamil		            info.psi_siginfo.si_code <= ILL_BADSTK);
8331.88Skamil		break;
8341.88Skamil	case SIGFPE:
8351.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8361.88Skamil		break;
8371.88Skamil	case SIGBUS:
8381.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8391.88Skamil		break;
8401.88Skamil	}
8411.88Skamil
8421.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8431.88Skamil
8441.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8451.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8461.88Skamil
8471.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8481.88Skamil
8491.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8501.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8511.88Skamil}
8521.88Skamil
8531.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8541.88SkamilATF_TC(test);								\
8551.88SkamilATF_TC_HEAD(test, tc)							\
8561.88Skamil{									\
8571.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8581.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8591.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8601.88Skamil}									\
8611.88Skamil									\
8621.88SkamilATF_TC_BODY(test, tc)							\
8631.88Skamil{									\
8641.88Skamil									\
8651.88Skamil	traceme_signalignored_crash(sig);				\
8661.88Skamil}
8671.88Skamil
8681.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8691.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8701.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8711.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8721.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8731.88Skamil
8741.88Skamil/// ----------------------------------------------------------------------------
8751.88Skamil
8761.88Skamilstatic void
8771.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
8781.1Skamil{
8791.1Skamil	const int exitval = 5;
8801.34Skamil	const int sigval = SIGSTOP;
8811.1Skamil	pid_t child, wpid;
8821.1Skamil	struct sigaction sa;
8831.1Skamil#if defined(TWAIT_HAVE_STATUS)
8841.1Skamil	int status;
8851.1Skamil#endif
8861.61Skre	struct ptrace_siginfo info;
8871.1Skamil
8881.45Skamil	memset(&info, 0, sizeof(info));
8891.45Skamil
8901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
8911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
8921.1Skamil	if (child == 0) {
8931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8951.1Skamil
8961.34Skamil		sa.sa_handler = sah;
8971.1Skamil		sa.sa_flags = SA_SIGINFO;
8981.1Skamil		sigemptyset(&sa.sa_mask);
8991.1Skamil
9001.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
9011.1Skamil
9021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9041.1Skamil
9051.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9061.1Skamil
9071.13Schristos		DPRINTF("Before exiting of the child process\n");
9081.1Skamil		_exit(exitval);
9091.1Skamil	}
9101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9111.1Skamil
9121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9141.1Skamil
9151.1Skamil	validate_status_stopped(status, sigval);
9161.1Skamil
9171.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9181.61Skre	SYSCALL_REQUIRE(
9191.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9201.45Skamil
9211.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9221.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9231.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9241.45Skamil	    info.psi_siginfo.si_errno);
9251.45Skamil
9261.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9271.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9281.45Skamil
9291.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9301.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9321.1Skamil
9331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9351.1Skamil
9361.1Skamil	validate_status_exited(status, exitval);
9371.1Skamil
9381.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9401.1Skamil}
9411.1Skamil
9421.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9431.61SkreATF_TC(test);								\
9441.61SkreATF_TC_HEAD(test, tc)							\
9451.61Skre{									\
9461.61Skre	atf_tc_set_md_var(tc, "descr",					\
9471.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9481.61Skre	    "handled correctly and caught by a signal handler");	\
9491.61Skre}									\
9501.61Skre									\
9511.61Skrestatic int test##_caught = 0;						\
9521.61Skre									\
9531.61Skrestatic void								\
9541.61Skretest##_sighandler(int arg)						\
9551.61Skre{									\
9561.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9571.61Skre									\
9581.61Skre	++ test##_caught;						\
9591.61Skre}									\
9601.61Skre									\
9611.61SkreATF_TC_BODY(test, tc)							\
9621.61Skre{									\
9631.61Skre									\
9641.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9651.34Skamil}
9661.34Skamil
9671.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9681.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9691.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9701.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9711.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9721.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9731.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9741.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
9751.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
9761.34Skamil
9771.34Skamil/// ----------------------------------------------------------------------------
9781.34Skamil
9791.35Skamilstatic void
9801.50Skamiltraceme_sendsignal_masked(int sigsent)
9811.50Skamil{
9821.50Skamil	const int exitval = 5;
9831.50Skamil	const int sigval = SIGSTOP;
9841.50Skamil	pid_t child, wpid;
9851.50Skamil	sigset_t set;
9861.50Skamil#if defined(TWAIT_HAVE_STATUS)
9871.50Skamil	int status;
9881.50Skamil#endif
9891.61Skre	struct ptrace_siginfo info;
9901.50Skamil
9911.50Skamil	memset(&info, 0, sizeof(info));
9921.50Skamil
9931.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9941.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
9951.50Skamil	if (child == 0) {
9961.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9971.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9981.50Skamil
9991.50Skamil		sigemptyset(&set);
10001.50Skamil		sigaddset(&set, sigsent);
10011.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
10021.50Skamil
10031.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10041.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10051.50Skamil
10061.50Skamil		_exit(exitval);
10071.50Skamil	}
10081.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10091.50Skamil
10101.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10111.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10121.50Skamil
10131.50Skamil	validate_status_stopped(status, sigval);
10141.50Skamil
10151.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10161.61Skre	SYSCALL_REQUIRE(
10171.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10181.50Skamil
10191.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10201.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10211.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10221.50Skamil	    info.psi_siginfo.si_errno);
10231.50Skamil
10241.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10251.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10261.50Skamil
10271.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10281.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10291.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10301.50Skamil
10311.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10321.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10331.50Skamil
10341.50Skamil	validate_status_exited(status, exitval);
10351.50Skamil
10361.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10371.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10381.50Skamil}
10391.50Skamil
10401.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10411.61SkreATF_TC(test);								\
10421.61SkreATF_TC_HEAD(test, tc)							\
10431.61Skre{									\
10441.61Skre	atf_tc_set_md_var(tc, "descr",					\
10451.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10461.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10471.61Skre}									\
10481.61Skre									\
10491.61SkreATF_TC_BODY(test, tc)							\
10501.61Skre{									\
10511.61Skre									\
10521.61Skre	traceme_sendsignal_masked(sig);					\
10531.50Skamil}
10541.50Skamil
10551.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10561.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10571.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10581.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10591.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10601.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10611.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10621.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10631.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10641.50Skamil
10651.50Skamil/// ----------------------------------------------------------------------------
10661.50Skamil
10671.50Skamilstatic void
10681.50Skamiltraceme_sendsignal_ignored(int sigsent)
10691.50Skamil{
10701.50Skamil	const int exitval = 5;
10711.50Skamil	const int sigval = SIGSTOP;
10721.50Skamil	pid_t child, wpid;
10731.50Skamil	struct sigaction sa;
10741.50Skamil#if defined(TWAIT_HAVE_STATUS)
10751.50Skamil	int status;
10761.50Skamil#endif
10771.61Skre	struct ptrace_siginfo info;
10781.50Skamil
10791.50Skamil	memset(&info, 0, sizeof(info));
10801.50Skamil
10811.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10821.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10831.50Skamil	if (child == 0) {
10841.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10851.61Skre
10861.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10871.50Skamil
10881.50Skamil		memset(&sa, 0, sizeof(sa));
10891.50Skamil		sa.sa_handler = SIG_IGN;
10901.50Skamil		sigemptyset(&sa.sa_mask);
10911.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
10921.50Skamil
10931.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10941.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10951.50Skamil
10961.50Skamil		_exit(exitval);
10971.50Skamil	}
10981.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10991.50Skamil
11001.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11011.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11021.50Skamil
11031.50Skamil	validate_status_stopped(status, sigval);
11041.50Skamil
11051.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11061.61Skre	SYSCALL_REQUIRE(
11071.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11081.50Skamil
11091.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11101.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11111.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11121.50Skamil	    info.psi_siginfo.si_errno);
11131.50Skamil
11141.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11151.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11161.50Skamil
11171.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11181.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11191.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11201.50Skamil
11211.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11221.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11231.50Skamil
11241.50Skamil	validate_status_exited(status, exitval);
11251.50Skamil
11261.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11271.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11281.50Skamil}
11291.50Skamil
11301.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11311.61SkreATF_TC(test);								\
11321.61SkreATF_TC_HEAD(test, tc)							\
11331.61Skre{									\
11341.61Skre	atf_tc_set_md_var(tc, "descr",					\
11351.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11361.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11371.61Skre}									\
11381.61Skre									\
11391.61SkreATF_TC_BODY(test, tc)							\
11401.61Skre{									\
11411.61Skre									\
11421.61Skre	traceme_sendsignal_ignored(sig);				\
11431.50Skamil}
11441.50Skamil
11451.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11461.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11471.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11481.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11491.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11501.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11511.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11521.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11531.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11541.50Skamil
11551.50Skamil/// ----------------------------------------------------------------------------
11561.50Skamil
11571.50Skamilstatic void
11581.50Skamiltraceme_sendsignal_simple(int sigsent)
11591.1Skamil{
11601.35Skamil	const int sigval = SIGSTOP;
11611.35Skamil	int exitval = 0;
11621.1Skamil	pid_t child, wpid;
11631.1Skamil#if defined(TWAIT_HAVE_STATUS)
11641.1Skamil	int status;
11651.85Skamil	int expect_core;
11661.85Skamil
11671.85Skamil	switch (sigsent) {
11681.85Skamil	case SIGABRT:
11691.85Skamil	case SIGTRAP:
11701.85Skamil	case SIGBUS:
11711.85Skamil	case SIGILL:
11721.85Skamil	case SIGFPE:
11731.85Skamil	case SIGSEGV:
11741.85Skamil		expect_core = 1;
11751.85Skamil		break;
11761.85Skamil	default:
11771.85Skamil		expect_core = 0;
11781.85Skamil		break;
11791.85Skamil	}
11801.1Skamil#endif
11811.61Skre	struct ptrace_siginfo info;
11821.1Skamil
11831.45Skamil	memset(&info, 0, sizeof(info));
11841.45Skamil
11851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
11861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
11871.1Skamil	if (child == 0) {
11881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11901.1Skamil
11911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11931.1Skamil
11941.35Skamil		switch (sigsent) {
11951.35Skamil		case SIGCONT:
11961.48Skamil		case SIGSTOP:
11971.35Skamil			_exit(exitval);
11981.35Skamil		default:
11991.35Skamil			/* NOTREACHED */
12001.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
12011.35Skamil		}
12021.1Skamil	}
12031.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12041.1Skamil
12051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12071.1Skamil
12081.1Skamil	validate_status_stopped(status, sigval);
12091.1Skamil
12101.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12111.61Skre	SYSCALL_REQUIRE(
12121.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12131.45Skamil
12141.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12151.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12161.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12171.45Skamil	    info.psi_siginfo.si_errno);
12181.45Skamil
12191.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12201.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12211.45Skamil
12221.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12231.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12251.1Skamil
12261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12281.1Skamil
12291.35Skamil	switch (sigsent) {
12301.48Skamil	case SIGSTOP:
12311.48Skamil		validate_status_stopped(status, sigsent);
12321.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12331.61Skre		    "child\n");
12341.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12351.61Skre		    sizeof(info)) != -1);
12361.48Skamil
12371.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12381.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12391.61Skre		    "si_errno=%#x\n",
12401.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12411.61Skre		    info.psi_siginfo.si_errno);
12421.48Skamil
12431.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12441.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12451.48Skamil
12461.48Skamil		DPRINTF("Before resuming the child process where it left off "
12471.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12481.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12491.48Skamil
12501.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12511.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12521.61Skre		    child);
12531.48Skamil		/* FALLTHROUGH */
12541.35Skamil	case SIGCONT:
12551.35Skamil		validate_status_exited(status, exitval);
12561.35Skamil		break;
12571.35Skamil	default:
12581.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12591.35Skamil		break;
12601.35Skamil	}
12611.1Skamil
12621.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12641.1Skamil}
12651.1Skamil
12661.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12671.61SkreATF_TC(test);								\
12681.61SkreATF_TC_HEAD(test, tc)							\
12691.61Skre{									\
12701.61Skre	atf_tc_set_md_var(tc, "descr",					\
12711.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12721.61Skre	    "handled correctly in a child without a signal handler");	\
12731.61Skre}									\
12741.61Skre									\
12751.61SkreATF_TC_BODY(test, tc)							\
12761.61Skre{									\
12771.61Skre									\
12781.61Skre	traceme_sendsignal_simple(sig);					\
12791.35Skamil}
12801.35Skamil
12811.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
12821.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
12831.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
12841.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
12851.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
12861.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
12871.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
12881.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
12891.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
12901.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
12911.35Skamil
12921.35Skamil/// ----------------------------------------------------------------------------
12931.35Skamil
12941.37SkamilATF_TC(traceme_pid1_parent);
12951.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
12961.37Skamil{
12971.37Skamil	atf_tc_set_md_var(tc, "descr",
12981.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
12991.37Skamil}
13001.37Skamil
13011.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
13021.37Skamil{
13031.37Skamil	struct msg_fds parent_child;
13041.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13051.37Skamil	pid_t child1, child2, wpid;
13061.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13071.37Skamil#if defined(TWAIT_HAVE_STATUS)
13081.37Skamil	int status;
13091.37Skamil#endif
13101.37Skamil
13111.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13121.37Skamil
13131.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13141.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13151.37Skamil	if (child1 == 0) {
13161.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13171.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13181.37Skamil		if (child2 != 0) {
13191.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13201.61Skre			    getpid(), child2);
13211.37Skamil			_exit(exitval_child1);
13221.37Skamil		}
13231.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13241.37Skamil
13251.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13261.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13271.37Skamil
13281.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13291.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13301.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13311.37Skamil
13321.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13331.37Skamil
13341.37Skamil		_exit(exitval_child2);
13351.37Skamil	}
13361.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13371.37Skamil
13381.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13391.61Skre	TWAIT_REQUIRE_SUCCESS(
13401.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13411.37Skamil
13421.37Skamil	validate_status_exited(status, exitval_child1);
13431.37Skamil
13441.37Skamil	DPRINTF("Notify that child1 is dead\n");
13451.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13461.37Skamil
13471.37Skamil	DPRINTF("Wait for exiting of child2\n");
13481.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13491.37Skamil}
13501.37Skamil
13511.37Skamil/// ----------------------------------------------------------------------------
13521.37Skamil
13531.40Skamilstatic void
13541.40Skamiltraceme_vfork_raise(int sigval)
13551.40Skamil{
13561.46Skamil	const int exitval = 5, exitval_watcher = 10;
13571.46Skamil	pid_t child, parent, watcher, wpid;
13581.46Skamil	int rv;
13591.40Skamil#if defined(TWAIT_HAVE_STATUS)
13601.40Skamil	int status;
13611.85Skamil
13621.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13631.85Skamil	volatile int expect_core;
13641.85Skamil
13651.85Skamil	switch (sigval) {
13661.85Skamil	case SIGABRT:
13671.85Skamil	case SIGTRAP:
13681.85Skamil	case SIGBUS:
13691.85Skamil	case SIGILL:
13701.85Skamil	case SIGFPE:
13711.85Skamil	case SIGSEGV:
13721.85Skamil		expect_core = 1;
13731.85Skamil		break;
13741.85Skamil	default:
13751.85Skamil		expect_core = 0;
13761.85Skamil		break;
13771.85Skamil	}
13781.40Skamil#endif
13791.40Skamil
13801.46Skamil	/*
13811.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
13821.46Skamil	 * the SIGKILL signal to it.
13831.46Skamil	 *
13841.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
13851.46Skamil	 * simpler to reparent this process to initproc and forget about it.
13861.46Skamil	 */
13871.46Skamil	if (sigval == SIGSTOP) {
13881.46Skamil		parent = getpid();
13891.46Skamil
13901.46Skamil		watcher = fork();
13911.46Skamil		ATF_REQUIRE(watcher != 1);
13921.46Skamil		if (watcher == 0) {
13931.46Skamil			/* Double fork(2) trick to reparent to initproc */
13941.46Skamil			watcher = fork();
13951.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
13961.46Skamil			if (watcher != 0)
13971.46Skamil				_exit(exitval_watcher);
13981.46Skamil
13991.46Skamil			child = await_stopped_child(parent);
14001.46Skamil
14011.46Skamil			errno = 0;
14021.46Skamil			rv = kill(child, SIGKILL);
14031.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
14041.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14051.46Skamil
14061.46Skamil			/* This exit value will be collected by initproc */
14071.46Skamil			_exit(0);
14081.46Skamil		}
14091.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14101.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14111.61Skre		    watcher);
14121.46Skamil
14131.46Skamil		validate_status_exited(status, exitval_watcher);
14141.46Skamil
14151.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14161.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14171.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14181.46Skamil	}
14191.46Skamil
14201.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14211.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14221.40Skamil	if (child == 0) {
14231.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14241.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14251.40Skamil
14261.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14271.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14281.40Skamil
14291.40Skamil		switch (sigval) {
14301.46Skamil		case SIGSTOP:
14311.40Skamil		case SIGKILL:
14321.40Skamil		case SIGABRT:
14331.40Skamil		case SIGHUP:
14341.85Skamil		case SIGTRAP:
14351.85Skamil		case SIGBUS:
14361.85Skamil		case SIGILL:
14371.85Skamil		case SIGFPE:
14381.85Skamil		case SIGSEGV:
14391.40Skamil			/* NOTREACHED */
14401.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14411.70Smrg			__unreachable();
14421.40Skamil		default:
14431.40Skamil			DPRINTF("Before exiting of the child process\n");
14441.40Skamil			_exit(exitval);
14451.40Skamil		}
14461.40Skamil	}
14471.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14481.40Skamil
14491.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14501.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14511.40Skamil
14521.40Skamil	switch (sigval) {
14531.40Skamil	case SIGKILL:
14541.40Skamil	case SIGABRT:
14551.40Skamil	case SIGHUP:
14561.85Skamil	case SIGTRAP:
14571.85Skamil	case SIGBUS:
14581.85Skamil	case SIGILL:
14591.85Skamil	case SIGFPE:
14601.85Skamil	case SIGSEGV:
14611.40Skamil		validate_status_signaled(status, sigval, expect_core);
14621.40Skamil		break;
14631.40Skamil	case SIGSTOP:
14641.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14651.46Skamil		break;
14661.40Skamil	case SIGCONT:
14671.47Skamil	case SIGTSTP:
14681.47Skamil	case SIGTTIN:
14691.47Skamil	case SIGTTOU:
14701.40Skamil		validate_status_exited(status, exitval);
14711.40Skamil		break;
14721.40Skamil	default:
14731.40Skamil		/* NOTREACHED */
14741.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
14751.40Skamil		break;
14761.40Skamil	}
14771.40Skamil
14781.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14791.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14801.40Skamil}
14811.40Skamil
14821.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
14831.61SkreATF_TC(test);								\
14841.61SkreATF_TC_HEAD(test, tc)							\
14851.61Skre{									\
14861.61Skre	atf_tc_set_md_var(tc, "descr",					\
14871.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
14881.61Skre	    "vfork(2)ed child");					\
14891.61Skre}									\
14901.61Skre									\
14911.61SkreATF_TC_BODY(test, tc)							\
14921.61Skre{									\
14931.61Skre									\
14941.61Skre	traceme_vfork_raise(sig);					\
14951.40Skamil}
14961.40Skamil
14971.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
14981.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
14991.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
15001.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
15011.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
15021.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
15031.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
15041.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15051.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15061.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15071.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15081.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15091.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15101.40Skamil
15111.40Skamil/// ----------------------------------------------------------------------------
15121.40Skamil
15131.52Skamilstatic void
15141.52Skamiltraceme_vfork_crash(int sig)
15151.41Skamil{
15161.41Skamil	pid_t child, wpid;
15171.41Skamil#if defined(TWAIT_HAVE_STATUS)
15181.41Skamil	int status;
15191.41Skamil#endif
15201.41Skamil
15211.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15221.71Skamil	if (sig == SIGILL)
15231.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15241.71Skamil#endif
15251.71Skamil
15261.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15271.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15281.41Skamil	if (child == 0) {
15291.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15301.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15311.41Skamil
15321.52Skamil		DPRINTF("Before executing a trap\n");
15331.52Skamil		switch (sig) {
15341.52Skamil		case SIGTRAP:
15351.52Skamil			trigger_trap();
15361.52Skamil			break;
15371.52Skamil		case SIGSEGV:
15381.52Skamil			trigger_segv();
15391.52Skamil			break;
15401.52Skamil		case SIGILL:
15411.52Skamil			trigger_ill();
15421.52Skamil			break;
15431.52Skamil		case SIGFPE:
15441.52Skamil			trigger_fpe();
15451.52Skamil			break;
15461.52Skamil		case SIGBUS:
15471.52Skamil			trigger_bus();
15481.52Skamil			break;
15491.52Skamil		default:
15501.52Skamil			/* NOTREACHED */
15511.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15521.52Skamil		}
15531.41Skamil
15541.41Skamil		/* NOTREACHED */
15551.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15561.41Skamil	}
15571.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15581.41Skamil
15591.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15601.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15611.41Skamil
15621.52Skamil	validate_status_signaled(status, sig, 1);
15631.41Skamil
15641.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15651.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15661.41Skamil}
15671.41Skamil
15681.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15691.61SkreATF_TC(test);								\
15701.61SkreATF_TC_HEAD(test, tc)							\
15711.61Skre{									\
15721.61Skre	atf_tc_set_md_var(tc, "descr",					\
15731.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
15741.61Skre	    "vfork(2)ed child");					\
15751.61Skre}									\
15761.61Skre									\
15771.61SkreATF_TC_BODY(test, tc)							\
15781.61Skre{									\
15791.61Skre									\
15801.61Skre	traceme_vfork_crash(sig);					\
15811.52Skamil}
15821.52Skamil
15831.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
15841.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
15851.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
15861.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
15871.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
15881.52Skamil
15891.41Skamil/// ----------------------------------------------------------------------------
15901.41Skamil
15911.92Skamilstatic void
15921.92Skamiltraceme_vfork_signalmasked_crash(int sig)
15931.92Skamil{
15941.92Skamil	pid_t child, wpid;
15951.92Skamil#if defined(TWAIT_HAVE_STATUS)
15961.92Skamil	int status;
15971.92Skamil#endif
15981.92Skamil	sigset_t intmask;
15991.92Skamil
16001.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16011.92Skamil	if (sig == SIGILL)
16021.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16031.92Skamil#endif
16041.92Skamil
16051.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16061.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16071.92Skamil	if (child == 0) {
16081.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16091.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16101.92Skamil
16111.92Skamil		sigemptyset(&intmask);
16121.92Skamil		sigaddset(&intmask, sig);
16131.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16141.92Skamil
16151.92Skamil		DPRINTF("Before executing a trap\n");
16161.92Skamil		switch (sig) {
16171.92Skamil		case SIGTRAP:
16181.92Skamil			trigger_trap();
16191.92Skamil			break;
16201.92Skamil		case SIGSEGV:
16211.92Skamil			trigger_segv();
16221.92Skamil			break;
16231.92Skamil		case SIGILL:
16241.92Skamil			trigger_ill();
16251.92Skamil			break;
16261.92Skamil		case SIGFPE:
16271.92Skamil			trigger_fpe();
16281.92Skamil			break;
16291.92Skamil		case SIGBUS:
16301.92Skamil			trigger_bus();
16311.92Skamil			break;
16321.92Skamil		default:
16331.92Skamil			/* NOTREACHED */
16341.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16351.92Skamil		}
16361.92Skamil
16371.92Skamil		/* NOTREACHED */
16381.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16391.92Skamil	}
16401.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16411.92Skamil
16421.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16431.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16441.92Skamil
16451.92Skamil	validate_status_signaled(status, sig, 1);
16461.92Skamil
16471.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16481.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16491.92Skamil}
16501.92Skamil
16511.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16521.92SkamilATF_TC(test);								\
16531.92SkamilATF_TC_HEAD(test, tc)							\
16541.92Skamil{									\
16551.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16561.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16571.92Skamil	    "vfork(2)ed child with a masked signal");			\
16581.92Skamil}									\
16591.92Skamil									\
16601.92SkamilATF_TC_BODY(test, tc)							\
16611.92Skamil{									\
16621.92Skamil									\
16631.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16641.92Skamil}
16651.92Skamil
16661.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16671.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16681.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
16691.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
16701.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
16711.92Skamil
16721.92Skamil/// ----------------------------------------------------------------------------
16731.92Skamil
16741.92Skamilstatic void
16751.92Skamiltraceme_vfork_signalignored_crash(int sig)
16761.92Skamil{
16771.92Skamil	pid_t child, wpid;
16781.92Skamil#if defined(TWAIT_HAVE_STATUS)
16791.92Skamil	int status;
16801.92Skamil#endif
16811.92Skamil	struct sigaction sa;
16821.92Skamil
16831.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16841.92Skamil	if (sig == SIGILL)
16851.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16861.92Skamil#endif
16871.92Skamil
16881.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16891.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16901.92Skamil	if (child == 0) {
16911.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16921.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16931.92Skamil
16941.92Skamil		memset(&sa, 0, sizeof(sa));
16951.92Skamil		sa.sa_handler = SIG_IGN;
16961.92Skamil		sigemptyset(&sa.sa_mask);
16971.92Skamil
16981.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
16991.92Skamil
17001.92Skamil		DPRINTF("Before executing a trap\n");
17011.92Skamil		switch (sig) {
17021.92Skamil		case SIGTRAP:
17031.92Skamil			trigger_trap();
17041.92Skamil			break;
17051.92Skamil		case SIGSEGV:
17061.92Skamil			trigger_segv();
17071.92Skamil			break;
17081.92Skamil		case SIGILL:
17091.92Skamil			trigger_ill();
17101.92Skamil			break;
17111.92Skamil		case SIGFPE:
17121.92Skamil			trigger_fpe();
17131.92Skamil			break;
17141.92Skamil		case SIGBUS:
17151.92Skamil			trigger_bus();
17161.92Skamil			break;
17171.92Skamil		default:
17181.92Skamil			/* NOTREACHED */
17191.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17201.92Skamil		}
17211.92Skamil
17221.92Skamil		/* NOTREACHED */
17231.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17241.92Skamil	}
17251.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17261.92Skamil
17271.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17281.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17291.92Skamil
17301.92Skamil	validate_status_signaled(status, sig, 1);
17311.92Skamil
17321.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17331.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17341.92Skamil}
17351.92Skamil
17361.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17371.92SkamilATF_TC(test);								\
17381.92SkamilATF_TC_HEAD(test, tc)							\
17391.92Skamil{									\
17401.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17411.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17421.92Skamil	    "vfork(2)ed child with ignored signal");			\
17431.92Skamil}									\
17441.92Skamil									\
17451.92SkamilATF_TC_BODY(test, tc)							\
17461.92Skamil{									\
17471.92Skamil									\
17481.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17491.92Skamil}
17501.92Skamil
17511.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17521.92Skamil    SIGTRAP)
17531.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17541.92Skamil    SIGSEGV)
17551.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17561.92Skamil    SIGILL)
17571.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17581.92Skamil    SIGFPE)
17591.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17601.92Skamil    SIGBUS)
17611.92Skamil
17621.92Skamil/// ----------------------------------------------------------------------------
17631.92Skamil
17641.96Skamilstatic void
17651.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
17661.43Skamil{
17671.43Skamil	const int sigval = SIGTRAP;
17681.43Skamil	pid_t child, wpid;
17691.43Skamil#if defined(TWAIT_HAVE_STATUS)
17701.43Skamil	int status;
17711.43Skamil#endif
17721.96Skamil	struct sigaction sa;
17731.61Skre	struct ptrace_siginfo info;
17741.96Skamil	sigset_t intmask;
17751.96Skamil	struct kinfo_proc2 kp;
17761.96Skamil	size_t len = sizeof(kp);
17771.96Skamil
17781.96Skamil	int name[6];
17791.96Skamil	const size_t namelen = __arraycount(name);
17801.96Skamil	ki_sigset_t kp_sigmask;
17811.96Skamil	ki_sigset_t kp_sigignore;
17821.43Skamil
17831.43Skamil	memset(&info, 0, sizeof(info));
17841.43Skamil
17851.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17861.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17871.43Skamil	if (child == 0) {
17881.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17891.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17901.43Skamil
17911.96Skamil		if (masked) {
17921.96Skamil			sigemptyset(&intmask);
17931.96Skamil			sigaddset(&intmask, sigval);
17941.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
17951.96Skamil		}
17961.96Skamil
17971.96Skamil		if (ignored) {
17981.96Skamil			memset(&sa, 0, sizeof(sa));
17991.96Skamil			sa.sa_handler = SIG_IGN;
18001.96Skamil			sigemptyset(&sa.sa_mask);
18011.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
18021.96Skamil		}
18031.96Skamil
18041.43Skamil		DPRINTF("Before calling execve(2) from child\n");
18051.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
18061.43Skamil
18071.43Skamil		/* NOTREACHED */
18081.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18091.43Skamil	}
18101.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18111.43Skamil
18121.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18131.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18141.43Skamil
18151.43Skamil	validate_status_stopped(status, sigval);
18161.43Skamil
18171.96Skamil	name[0] = CTL_KERN,
18181.96Skamil	name[1] = KERN_PROC2,
18191.96Skamil	name[2] = KERN_PROC_PID;
18201.96Skamil	name[3] = getpid();
18211.96Skamil	name[4] = sizeof(kp);
18221.96Skamil	name[5] = 1;
18231.96Skamil
18241.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18251.96Skamil
18261.96Skamil	if (masked)
18271.96Skamil		kp_sigmask = kp.p_sigmask;
18281.96Skamil
18291.96Skamil	if (ignored)
18301.96Skamil		kp_sigignore = kp.p_sigignore;
18311.96Skamil
18321.96Skamil	name[3] = getpid();
18331.96Skamil
18341.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18351.96Skamil
18361.96Skamil	if (masked) {
18371.96Skamil		DPRINTF("kp_sigmask="
18381.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18391.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18401.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18411.96Skamil
18421.96Skamil	        DPRINTF("kp.p_sigmask="
18431.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18441.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18451.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18461.96Skamil
18471.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18481.96Skamil		    sizeof(kp_sigmask)));
18491.96Skamil	}
18501.96Skamil
18511.96Skamil	if (ignored) {
18521.96Skamil		DPRINTF("kp_sigignore="
18531.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18541.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18551.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18561.96Skamil
18571.96Skamil	        DPRINTF("kp.p_sigignore="
18581.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18591.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
18601.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
18611.96Skamil
18621.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
18631.96Skamil		    sizeof(kp_sigignore)));
18641.96Skamil	}
18651.96Skamil
18661.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
18671.61Skre	SYSCALL_REQUIRE(
18681.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
18691.43Skamil
18701.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
18711.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
18721.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
18731.43Skamil	    info.psi_siginfo.si_errno);
18741.43Skamil
18751.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
18761.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
18771.43Skamil
18781.43Skamil	DPRINTF("Before resuming the child process where it left off and "
18791.43Skamil	    "without signal to be sent\n");
18801.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18811.43Skamil
18821.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18831.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18841.43Skamil
18851.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18861.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18871.43Skamil}
18881.43Skamil
18891.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
18901.96SkamilATF_TC(test);								\
18911.96SkamilATF_TC_HEAD(test, tc)							\
18921.96Skamil{									\
18931.96Skamil	atf_tc_set_md_var(tc, "descr",					\
18941.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
18951.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
18961.96Skamil	    masked ? " with ignored signal" : "");			\
18971.96Skamil}									\
18981.96Skamil									\
18991.96SkamilATF_TC_BODY(test, tc)							\
19001.96Skamil{									\
19011.96Skamil									\
19021.96Skamil	traceme_vfork_exec(masked, ignored);				\
19031.96Skamil}
19041.96Skamil
19051.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
19061.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19071.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19081.96Skamil
19091.43Skamil/// ----------------------------------------------------------------------------
19101.43Skamil
19111.1Skamil#if defined(TWAIT_HAVE_PID)
19121.51Skamilstatic void
19131.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19141.59Skamil{
19151.94Skamil	const int sigval = SIGSTOP;
19161.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19171.59Skamil	const int exitval = 10;
19181.59Skamil	pid_t tracee, tracer, wpid;
19191.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19201.59Skamil#if defined(TWAIT_HAVE_STATUS)
19211.59Skamil	int status;
19221.59Skamil#endif
19231.94Skamil	struct sigaction sa;
19241.59Skamil	struct ptrace_siginfo info;
19251.94Skamil	sigset_t intmask;
19261.94Skamil	struct kinfo_proc2 kp;
19271.94Skamil	size_t len = sizeof(kp);
19281.94Skamil
19291.94Skamil	int name[6];
19301.94Skamil	const size_t namelen = __arraycount(name);
19311.94Skamil	ki_sigset_t kp_sigmask;
19321.94Skamil	ki_sigset_t kp_sigignore;
19331.61Skre
19341.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19351.71Skamil	if (sig == SIGILL)
19361.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19371.71Skamil#endif
19381.71Skamil
19391.59Skamil	memset(&info, 0, sizeof(info));
19401.59Skamil
19411.59Skamil	DPRINTF("Spawn tracee\n");
19421.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19431.59Skamil	tracee = atf_utils_fork();
19441.59Skamil	if (tracee == 0) {
19451.59Skamil		// Wait for parent to let us crash
19461.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19471.61Skre
19481.94Skamil		if (masked) {
19491.94Skamil			sigemptyset(&intmask);
19501.94Skamil			sigaddset(&intmask, sig);
19511.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19521.94Skamil		}
19531.94Skamil
19541.94Skamil		if (ignored) {
19551.94Skamil			memset(&sa, 0, sizeof(sa));
19561.94Skamil			sa.sa_handler = SIG_IGN;
19571.94Skamil			sigemptyset(&sa.sa_mask);
19581.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
19591.94Skamil		}
19601.94Skamil
19611.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19621.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19631.94Skamil
19641.59Skamil		DPRINTF("Before executing a trap\n");
19651.59Skamil		switch (sig) {
19661.59Skamil		case SIGTRAP:
19671.59Skamil			trigger_trap();
19681.59Skamil			break;
19691.59Skamil		case SIGSEGV:
19701.59Skamil			trigger_segv();
19711.59Skamil			break;
19721.59Skamil		case SIGILL:
19731.59Skamil			trigger_ill();
19741.59Skamil			break;
19751.59Skamil		case SIGFPE:
19761.59Skamil			trigger_fpe();
19771.59Skamil			break;
19781.59Skamil		case SIGBUS:
19791.59Skamil			trigger_bus();
19801.59Skamil			break;
19811.59Skamil		default:
19821.59Skamil			/* NOTREACHED */
19831.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
19841.59Skamil		}
19851.59Skamil
19861.59Skamil		/* NOTREACHED */
19871.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
19881.59Skamil	}
19891.59Skamil
19901.59Skamil	DPRINTF("Spawn debugger\n");
19911.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
19921.59Skamil	tracer = atf_utils_fork();
19931.59Skamil	if (tracer == 0) {
19941.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
19951.59Skamil		tracer = atf_utils_fork();
19961.59Skamil		if (tracer != 0)
19971.61Skre			_exit(exitval);
19981.59Skamil
19991.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
20001.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
20011.59Skamil
20021.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
20031.59Skamil		FORKEE_REQUIRE_SUCCESS(
20041.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20051.59Skamil
20061.59Skamil		forkee_status_stopped(status, SIGSTOP);
20071.59Skamil
20081.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20091.94Skamil		    "traced process\n");
20101.94Skamil		SYSCALL_REQUIRE(
20111.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20121.94Skamil
20131.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20141.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20151.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20161.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20171.94Skamil
20181.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20191.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20201.94Skamil
20211.59Skamil		/* Resume tracee with PT_CONTINUE */
20221.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20231.59Skamil
20241.59Skamil		/* Inform parent that tracer has attached to tracee */
20251.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20261.59Skamil
20271.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20281.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20291.59Skamil
20301.59Skamil		/* Wait for tracee and assert that it exited */
20311.59Skamil		FORKEE_REQUIRE_SUCCESS(
20321.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20331.59Skamil
20341.94Skamil		forkee_status_stopped(status, sigval);
20351.94Skamil
20361.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20371.94Skamil		    "traced process\n");
20381.94Skamil		SYSCALL_REQUIRE(
20391.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20401.94Skamil
20411.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20421.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20431.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20441.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20451.94Skamil
20461.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20471.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20481.94Skamil
20491.94Skamil		name[0] = CTL_KERN,
20501.94Skamil		name[1] = KERN_PROC2,
20511.94Skamil		name[2] = KERN_PROC_PID;
20521.94Skamil		name[3] = tracee;
20531.94Skamil		name[4] = sizeof(kp);
20541.94Skamil		name[5] = 1;
20551.94Skamil
20561.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20571.94Skamil
20581.94Skamil		if (masked)
20591.94Skamil			kp_sigmask = kp.p_sigmask;
20601.94Skamil
20611.94Skamil		if (ignored)
20621.94Skamil			kp_sigignore = kp.p_sigignore;
20631.94Skamil
20641.94Skamil		/* Resume tracee with PT_CONTINUE */
20651.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20661.94Skamil
20671.94Skamil		/* Wait for tracee and assert that it exited */
20681.94Skamil		FORKEE_REQUIRE_SUCCESS(
20691.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20701.94Skamil
20711.93Skamil		forkee_status_stopped(status, sig);
20721.59Skamil
20731.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20741.61Skre		    "traced process\n");
20751.61Skre		SYSCALL_REQUIRE(
20761.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20771.59Skamil
20781.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20791.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20801.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20811.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20821.59Skamil
20831.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
20841.94Skamil
20851.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20861.94Skamil
20871.94Skamil		if (masked) {
20881.94Skamil			DPRINTF("kp_sigmask="
20891.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
20901.94Skamil			    PRIx32 "\n",
20911.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
20921.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
20931.94Skamil
20941.94Skamil			DPRINTF("kp.p_sigmask="
20951.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
20961.94Skamil			    PRIx32 "\n",
20971.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
20981.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
20991.94Skamil
21001.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
21011.94Skamil			    sizeof(kp_sigmask)));
21021.94Skamil		}
21031.94Skamil
21041.94Skamil		if (ignored) {
21051.94Skamil			DPRINTF("kp_sigignore="
21061.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21071.94Skamil			    PRIx32 "\n",
21081.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21091.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21101.94Skamil
21111.94Skamil			DPRINTF("kp.p_sigignore="
21121.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21131.94Skamil			    PRIx32 "\n",
21141.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21151.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21161.94Skamil
21171.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21181.94Skamil			    sizeof(kp_sigignore)));
21191.94Skamil		}
21201.94Skamil
21211.59Skamil		switch (sig) {
21221.59Skamil		case SIGTRAP:
21231.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21241.59Skamil			break;
21251.59Skamil		case SIGSEGV:
21261.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21271.59Skamil			break;
21281.71Skamil		case SIGILL:
21291.112Skamil			FORKEE_ASSERT(info.psi_siginfo.si_code >= 0 &&
21301.112Skamil			            info.psi_siginfo.si_code <= ILL_BADSTK);
21311.71Skamil			break;
21321.59Skamil		case SIGFPE:
21331.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21341.59Skamil			break;
21351.59Skamil		case SIGBUS:
21361.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21371.59Skamil			break;
21381.59Skamil		}
21391.59Skamil
21401.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21411.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21421.93Skamil		FORKEE_REQUIRE_SUCCESS(
21431.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21441.59Skamil
21451.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21461.59Skamil
21471.71Skamil		/* Inform parent that tracer is exiting normally */
21481.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21491.71Skamil
21501.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21511.59Skamil		_exit(0 /* collect by initproc */);
21521.59Skamil	}
21531.59Skamil
21541.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21551.59Skamil	    "calling %s()\n", TWAIT_FNAME);
21561.59Skamil	TWAIT_REQUIRE_SUCCESS(
21571.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21581.59Skamil
21591.59Skamil	validate_status_exited(status, exitval);
21601.59Skamil
21611.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
21621.59Skamil	    TWAIT_FNAME);
21631.59Skamil	TWAIT_REQUIRE_SUCCESS(
21641.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
21651.59Skamil
21661.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
21671.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
21681.59Skamil
21691.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
21701.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
21711.59Skamil
21721.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
21731.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
21741.59Skamil
21751.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
21761.59Skamil	    TWAIT_FNAME);
21771.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21781.59Skamil
21791.59Skamil	validate_status_signaled(status, SIGKILL, 0);
21801.59Skamil
21811.71Skamil	DPRINTF("Await normal exit of tracer\n");
21821.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
21831.71Skamil
21841.59Skamil	msg_close(&parent_tracer);
21851.59Skamil	msg_close(&parent_tracee);
21861.59Skamil}
21871.59Skamil
21881.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
21891.61SkreATF_TC(test);								\
21901.61SkreATF_TC_HEAD(test, tc)							\
21911.61Skre{									\
21921.61Skre	atf_tc_set_md_var(tc, "descr",					\
21931.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
21941.94Skamil	    "the debuggee");						\
21951.61Skre}									\
21961.61Skre									\
21971.61SkreATF_TC_BODY(test, tc)							\
21981.61Skre{									\
21991.61Skre									\
22001.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
22011.59Skamil}
22021.59Skamil
22031.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
22041.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
22051.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
22061.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
22071.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22081.94Skamil
22091.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22101.94SkamilATF_TC(test);								\
22111.94SkamilATF_TC_HEAD(test, tc)							\
22121.94Skamil{									\
22131.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22141.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22151.94Skamil	    "the debuggee with masked signal");				\
22161.94Skamil}									\
22171.94Skamil									\
22181.94SkamilATF_TC_BODY(test, tc)							\
22191.94Skamil{									\
22201.94Skamil									\
22211.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22221.94Skamil}
22231.94Skamil
22241.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22251.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22261.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22271.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22281.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22291.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22301.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22311.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22321.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22331.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22341.94Skamil
22351.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22361.94SkamilATF_TC(test);								\
22371.94SkamilATF_TC_HEAD(test, tc)							\
22381.94Skamil{									\
22391.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22401.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22411.94Skamil	    "the debuggee with signal ignored");			\
22421.94Skamil}									\
22431.94Skamil									\
22441.94SkamilATF_TC_BODY(test, tc)							\
22451.94Skamil{									\
22461.94Skamil									\
22471.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22481.94Skamil}
22491.94Skamil
22501.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22511.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22521.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22531.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22541.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22551.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
22561.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22571.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
22581.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22591.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
22601.59Skamil#endif
22611.59Skamil
22621.59Skamil/// ----------------------------------------------------------------------------
22631.59Skamil
22641.59Skamil#if defined(TWAIT_HAVE_PID)
22651.59Skamilstatic void
22661.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
22671.67Skamil                                             bool stopped)
22681.1Skamil{
22691.51Skamil	/*
22701.51Skamil	 * notimeout - disable timeout in await zombie function
22711.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
22721.67Skamil	 * stopped - attach to a stopped process
22731.51Skamil	 */
22741.1Skamil
22751.1Skamil	struct msg_fds parent_tracee, parent_tracer;
22761.1Skamil	const int exitval_tracee = 5;
22771.1Skamil	const int exitval_tracer = 10;
22781.1Skamil	pid_t tracee, tracer, wpid;
22791.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
22801.1Skamil#if defined(TWAIT_HAVE_STATUS)
22811.1Skamil	int status;
22821.1Skamil#endif
22831.1Skamil
22841.67Skamil	/*
22851.67Skamil	 * Only a subset of options are supported.
22861.67Skamil	 */
22871.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
22881.67Skamil	            (!notimeout && unrelated && !stopped) ||
22891.67Skamil	            (notimeout && !unrelated && !stopped) ||
22901.67Skamil	            (!notimeout && unrelated && stopped));
22911.67Skamil
22921.13Schristos	DPRINTF("Spawn tracee\n");
22931.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
22941.1Skamil	tracee = atf_utils_fork();
22951.1Skamil	if (tracee == 0) {
22961.67Skamil		if (stopped) {
22971.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
22981.67Skamil			raise(SIGSTOP);
22991.67Skamil		}
23001.67Skamil
23011.1Skamil		// Wait for parent to let us exit
23021.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
23031.1Skamil		_exit(exitval_tracee);
23041.1Skamil	}
23051.1Skamil
23061.13Schristos	DPRINTF("Spawn debugger\n");
23071.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23081.1Skamil	tracer = atf_utils_fork();
23091.1Skamil	if (tracer == 0) {
23101.51Skamil		if(unrelated) {
23111.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23121.51Skamil			tracer = atf_utils_fork();
23131.51Skamil			if (tracer != 0)
23141.51Skamil				_exit(exitval_tracer);
23151.51Skamil		}
23161.51Skamil
23171.67Skamil		if (stopped) {
23181.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23191.67Skamil			await_stopped(tracee);
23201.67Skamil		}
23211.67Skamil
23221.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23231.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23241.1Skamil
23251.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23261.1Skamil		FORKEE_REQUIRE_SUCCESS(
23271.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23281.1Skamil
23291.1Skamil		forkee_status_stopped(status, SIGSTOP);
23301.1Skamil
23311.1Skamil		/* Resume tracee with PT_CONTINUE */
23321.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23331.1Skamil
23341.1Skamil		/* Inform parent that tracer has attached to tracee */
23351.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23361.1Skamil
23371.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23381.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23391.1Skamil
23401.1Skamil		/* Wait for tracee and assert that it exited */
23411.1Skamil		FORKEE_REQUIRE_SUCCESS(
23421.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23431.1Skamil
23441.1Skamil		forkee_status_exited(status, exitval_tracee);
23451.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23461.1Skamil
23471.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23481.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23491.51Skamil	}
23501.51Skamil
23511.51Skamil	if (unrelated) {
23521.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23531.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23541.51Skamil		TWAIT_REQUIRE_SUCCESS(
23551.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23561.51Skamil
23571.51Skamil		validate_status_exited(status, exitval_tracer);
23581.51Skamil
23591.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
23601.51Skamil		    TWAIT_FNAME);
23611.51Skamil		TWAIT_REQUIRE_SUCCESS(
23621.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
23631.1Skamil	}
23641.1Skamil
23651.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
23661.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
23671.1Skamil
23681.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
23691.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
23701.1Skamil
23711.13Schristos	DPRINTF("Detect that tracee is zombie\n");
23721.51Skamil	if (notimeout)
23731.26Skamil		await_zombie_raw(tracee, 0);
23741.26Skamil	else
23751.26Skamil		await_zombie(tracee);
23761.1Skamil
23771.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
23781.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
23791.1Skamil	    TWAIT_FNAME);
23801.1Skamil	TWAIT_REQUIRE_SUCCESS(
23811.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
23821.1Skamil
23831.51Skamil	if (unrelated) {
23841.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
23851.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
23861.51Skamil	} else {
23871.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
23881.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
23891.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
23901.59Skamil			"%s()\n", TWAIT_FNAME);
23911.51Skamil
23921.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
23931.59Skamil			"tracee\n");
23941.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
23951.51Skamil		    tracer);
23961.1Skamil
23971.51Skamil		validate_status_exited(status, exitval_tracer);
23981.51Skamil	}
23991.1Skamil
24001.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
24011.1Skamil	    TWAIT_FNAME);
24021.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
24031.1Skamil
24041.1Skamil	validate_status_exited(status, exitval_tracee);
24051.1Skamil
24061.1Skamil	msg_close(&parent_tracer);
24071.1Skamil	msg_close(&parent_tracee);
24081.1Skamil}
24091.26Skamil
24101.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24111.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24121.51Skamil{
24131.51Skamil	atf_tc_set_md_var(tc, "descr",
24141.51Skamil	    "Assert that tracer sees process termination before the parent");
24151.51Skamil}
24161.51Skamil
24171.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24181.26Skamil{
24191.26Skamil
24201.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24211.26Skamil}
24221.26Skamil
24231.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24241.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24251.1Skamil{
24261.1Skamil	atf_tc_set_md_var(tc, "descr",
24271.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24281.51Skamil	    "process and no other error is reported");
24291.1Skamil}
24301.1Skamil
24311.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24321.1Skamil{
24331.51Skamil	time_t start, end;
24341.51Skamil	double diff;
24351.51Skamil	unsigned long N = 0;
24361.1Skamil
24371.51Skamil	/*
24381.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24391.51Skamil	 * This test body isn't specific to this race, however it's just good
24401.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24411.51Skamil	 */
24421.1Skamil
24431.51Skamil	start = time(NULL);
24441.51Skamil	while (true) {
24451.51Skamil		DPRINTF("Step: %lu\n", N);
24461.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24471.67Skamil		                                             false);
24481.51Skamil		end = time(NULL);
24491.51Skamil		diff = difftime(end, start);
24501.51Skamil		if (diff >= 5.0)
24511.51Skamil			break;
24521.51Skamil		++N;
24531.1Skamil	}
24541.51Skamil	DPRINTF("Iterations: %lu\n", N);
24551.51Skamil}
24561.1Skamil
24571.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
24581.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24591.51Skamil{
24601.51Skamil	atf_tc_set_md_var(tc, "descr",
24611.51Skamil	    "Assert that tracer sees process termination before the parent");
24621.51Skamil}
24631.1Skamil
24641.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24651.51Skamil{
24661.1Skamil
24671.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
24681.67Skamil}
24691.67Skamil
24701.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
24711.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
24721.67Skamil{
24731.67Skamil	atf_tc_set_md_var(tc, "descr",
24741.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
24751.67Skamil}
24761.67Skamil
24771.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
24781.67Skamil{
24791.67Skamil
24801.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
24811.1Skamil}
24821.1Skamil#endif
24831.1Skamil
24841.51Skamil/// ----------------------------------------------------------------------------
24851.51Skamil
24861.66Skamilstatic void
24871.66Skamilparent_attach_to_its_child(bool stopped)
24881.1Skamil{
24891.1Skamil	struct msg_fds parent_tracee;
24901.1Skamil	const int exitval_tracee = 5;
24911.1Skamil	pid_t tracee, wpid;
24921.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
24931.1Skamil#if defined(TWAIT_HAVE_STATUS)
24941.1Skamil	int status;
24951.1Skamil#endif
24961.1Skamil
24971.13Schristos	DPRINTF("Spawn tracee\n");
24981.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
24991.1Skamil	tracee = atf_utils_fork();
25001.1Skamil	if (tracee == 0) {
25011.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25021.13Schristos		DPRINTF("Parent should now attach to tracee\n");
25031.1Skamil
25041.66Skamil		if (stopped) {
25051.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
25061.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
25071.66Skamil		}
25081.66Skamil
25091.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25101.1Skamil		/* Wait for message from the parent */
25111.1Skamil		_exit(exitval_tracee);
25121.1Skamil	}
25131.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25141.57Skamil
25151.66Skamil	if (stopped) {
25161.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25171.66Skamil		await_stopped(tracee);
25181.66Skamil	}
25191.66Skamil
25201.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25221.1Skamil
25231.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25241.1Skamil	    TWAIT_FNAME);
25251.1Skamil	TWAIT_REQUIRE_SUCCESS(
25261.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25271.1Skamil
25281.1Skamil	validate_status_stopped(status, SIGSTOP);
25291.1Skamil
25301.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25321.1Skamil
25331.13Schristos	DPRINTF("Let the tracee exit now\n");
25341.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25351.1Skamil
25361.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25371.1Skamil	TWAIT_REQUIRE_SUCCESS(
25381.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25391.1Skamil
25401.1Skamil	validate_status_exited(status, exitval_tracee);
25411.1Skamil
25421.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25441.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25451.1Skamil
25461.1Skamil	msg_close(&parent_tracee);
25471.1Skamil}
25481.1Skamil
25491.66SkamilATF_TC(parent_attach_to_its_child);
25501.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25511.66Skamil{
25521.66Skamil	atf_tc_set_md_var(tc, "descr",
25531.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25541.66Skamil}
25551.66Skamil
25561.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
25571.66Skamil{
25581.66Skamil
25591.66Skamil	parent_attach_to_its_child(false);
25601.66Skamil}
25611.66Skamil
25621.66SkamilATF_TC(parent_attach_to_its_stopped_child);
25631.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
25641.66Skamil{
25651.66Skamil	atf_tc_set_md_var(tc, "descr",
25661.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
25671.66Skamil}
25681.66Skamil
25691.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
25701.66Skamil{
25711.66Skamil
25721.66Skamil	parent_attach_to_its_child(true);
25731.66Skamil}
25741.66Skamil
25751.51Skamil/// ----------------------------------------------------------------------------
25761.51Skamil
25771.65Skamilstatic void
25781.65Skamilchild_attach_to_its_parent(bool stopped)
25791.1Skamil{
25801.1Skamil	struct msg_fds parent_tracee;
25811.1Skamil	const int exitval_tracer = 5;
25821.1Skamil	pid_t tracer, wpid;
25831.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25841.1Skamil#if defined(TWAIT_HAVE_STATUS)
25851.1Skamil	int status;
25861.1Skamil#endif
25871.1Skamil
25881.13Schristos	DPRINTF("Spawn tracer\n");
25891.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25901.1Skamil	tracer = atf_utils_fork();
25911.1Skamil	if (tracer == 0) {
25921.1Skamil		/* Wait for message from the parent */
25931.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25941.1Skamil
25951.65Skamil		if (stopped) {
25961.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
25971.65Skamil			        getppid());
25981.65Skamil			await_stopped(getppid());
25991.65Skamil		}
26001.65Skamil
26011.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
26021.1Skamil		    getppid());
26031.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
26041.1Skamil
26051.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
26061.1Skamil		    TWAIT_FNAME);
26071.1Skamil		FORKEE_REQUIRE_SUCCESS(
26081.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26091.1Skamil
26101.1Skamil		forkee_status_stopped(status, SIGSTOP);
26111.1Skamil
26121.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26131.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26141.1Skamil		    != -1);
26151.1Skamil
26161.1Skamil		/* Tell parent we are ready */
26171.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26181.1Skamil
26191.1Skamil		_exit(exitval_tracer);
26201.1Skamil	}
26211.1Skamil
26221.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26231.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26241.65Skamil
26251.65Skamil	if (stopped) {
26261.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26271.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26281.65Skamil	}
26291.65Skamil
26301.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26311.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26321.1Skamil
26331.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26341.1Skamil	TWAIT_REQUIRE_SUCCESS(
26351.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26361.1Skamil
26371.1Skamil	validate_status_exited(status, exitval_tracer);
26381.1Skamil
26391.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26411.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26421.1Skamil
26431.1Skamil	msg_close(&parent_tracee);
26441.1Skamil}
26451.1Skamil
26461.65SkamilATF_TC(child_attach_to_its_parent);
26471.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26481.65Skamil{
26491.65Skamil	atf_tc_set_md_var(tc, "descr",
26501.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26511.65Skamil}
26521.65Skamil
26531.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26541.65Skamil{
26551.65Skamil
26561.65Skamil	child_attach_to_its_parent(false);
26571.65Skamil}
26581.65Skamil
26591.65SkamilATF_TC(child_attach_to_its_stopped_parent);
26601.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
26611.65Skamil{
26621.65Skamil	atf_tc_set_md_var(tc, "descr",
26631.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
26641.65Skamil}
26651.65Skamil
26661.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
26671.65Skamil{
26681.65Skamil	/*
26691.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
26701.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
26711.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
26721.65Skamil	 *
26731.65Skamil	 * As a workaround spawn this test as a subprocess.
26741.65Skamil	 */
26751.65Skamil
26761.65Skamil	const int exitval = 15;
26771.65Skamil	pid_t child, wpid;
26781.65Skamil#if defined(TWAIT_HAVE_STATUS)
26791.65Skamil	int status;
26801.65Skamil#endif
26811.65Skamil
26821.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
26831.65Skamil	if (child == 0) {
26841.65Skamil		child_attach_to_its_parent(true);
26851.65Skamil		_exit(exitval);
26861.65Skamil	} else {
26871.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26881.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26891.65Skamil
26901.65Skamil		validate_status_exited(status, exitval);
26911.65Skamil
26921.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
26931.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26941.65Skamil	}
26951.65Skamil}
26961.65Skamil
26971.51Skamil/// ----------------------------------------------------------------------------
26981.51Skamil
26991.1Skamil#if defined(TWAIT_HAVE_PID)
27001.1Skamil
27011.51Skamilenum tracee_sees_its_original_parent_type {
27021.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
27031.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
27041.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
27051.51Skamil};
27061.51Skamil
27071.51Skamilstatic void
27081.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27091.1Skamil{
27101.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27111.1Skamil	const int exitval_tracee = 5;
27121.1Skamil	const int exitval_tracer = 10;
27131.1Skamil	pid_t parent, tracee, tracer, wpid;
27141.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27151.1Skamil#if defined(TWAIT_HAVE_STATUS)
27161.1Skamil	int status;
27171.1Skamil#endif
27181.51Skamil	/* sysctl(3) - kinfo_proc2 */
27191.51Skamil	int name[CTL_MAXNAME];
27201.51Skamil	struct kinfo_proc2 kp;
27211.51Skamil	size_t len = sizeof(kp);
27221.51Skamil	unsigned int namelen;
27231.51Skamil
27241.51Skamil	/* procfs - status  */
27251.51Skamil	FILE *fp;
27261.51Skamil	struct stat st;
27271.51Skamil	const char *fname = "/proc/curproc/status";
27281.51Skamil	char s_executable[MAXPATHLEN];
27291.51Skamil	int s_pid, s_ppid;
27301.51Skamil	int rv;
27311.51Skamil
27321.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27331.61Skre		SYSCALL_REQUIRE(
27341.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27351.61Skre		if (rv != 0)
27361.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27371.51Skamil	}
27381.1Skamil
27391.13Schristos	DPRINTF("Spawn tracee\n");
27401.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27411.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27421.1Skamil	tracee = atf_utils_fork();
27431.1Skamil	if (tracee == 0) {
27441.1Skamil		parent = getppid();
27451.1Skamil
27461.1Skamil		/* Emit message to the parent */
27471.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27481.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27491.1Skamil
27501.51Skamil		switch (type) {
27511.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27521.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27531.51Skamil			break;
27541.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27551.51Skamil			namelen = 0;
27561.51Skamil			name[namelen++] = CTL_KERN;
27571.51Skamil			name[namelen++] = KERN_PROC2;
27581.51Skamil			name[namelen++] = KERN_PROC_PID;
27591.51Skamil			name[namelen++] = getpid();
27601.51Skamil			name[namelen++] = len;
27611.51Skamil			name[namelen++] = 1;
27621.51Skamil
27631.61Skre			FORKEE_ASSERT_EQ(
27641.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
27651.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
27661.51Skamil			break;
27671.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
27681.51Skamil			/*
27691.51Skamil			 * Format:
27701.51Skamil			 *  EXECUTABLE PID PPID ...
27711.51Skamil			 */
27721.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
27731.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
27741.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
27751.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
27761.51Skamil			break;
27771.51Skamil		}
27781.1Skamil
27791.1Skamil		_exit(exitval_tracee);
27801.1Skamil	}
27811.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
27821.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
27831.1Skamil
27841.13Schristos	DPRINTF("Spawn debugger\n");
27851.1Skamil	tracer = atf_utils_fork();
27861.1Skamil	if (tracer == 0) {
27871.1Skamil		/* No IPC to communicate with the child */
27881.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
27891.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
27901.1Skamil
27911.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
27921.1Skamil		FORKEE_REQUIRE_SUCCESS(
27931.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
27941.1Skamil
27951.1Skamil		forkee_status_stopped(status, SIGSTOP);
27961.1Skamil
27971.1Skamil		/* Resume tracee with PT_CONTINUE */
27981.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
27991.1Skamil
28001.1Skamil		/* Inform parent that tracer has attached to tracee */
28011.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
28021.1Skamil
28031.1Skamil		/* Wait for parent to tell use that tracee should have exited */
28041.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
28051.1Skamil
28061.1Skamil		/* Wait for tracee and assert that it exited */
28071.1Skamil		FORKEE_REQUIRE_SUCCESS(
28081.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28091.1Skamil
28101.1Skamil		forkee_status_exited(status, exitval_tracee);
28111.1Skamil
28121.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28131.1Skamil		_exit(exitval_tracer);
28141.1Skamil	}
28151.1Skamil
28161.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28171.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28181.1Skamil
28191.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28201.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28211.1Skamil
28221.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28231.1Skamil	await_zombie(tracee);
28241.1Skamil
28251.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28261.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28271.1Skamil	TWAIT_REQUIRE_SUCCESS(
28281.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28291.1Skamil
28301.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28311.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28321.1Skamil
28331.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28351.1Skamil	    tracer);
28361.1Skamil
28371.1Skamil	validate_status_exited(status, exitval_tracer);
28381.1Skamil
28391.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28401.1Skamil	    TWAIT_FNAME);
28411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28421.1Skamil	    tracee);
28431.1Skamil
28441.1Skamil	validate_status_exited(status, exitval_tracee);
28451.1Skamil
28461.1Skamil	msg_close(&parent_tracer);
28471.1Skamil	msg_close(&parent_tracee);
28481.1Skamil}
28491.1Skamil
28501.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28511.61SkreATF_TC(test);								\
28521.61SkreATF_TC_HEAD(test, tc)							\
28531.61Skre{									\
28541.61Skre	atf_tc_set_md_var(tc, "descr",					\
28551.61Skre	    "Assert that tracee sees its original parent when being traced " \
28561.61Skre	    "(check " descr ")");					\
28571.61Skre}									\
28581.61Skre									\
28591.61SkreATF_TC_BODY(test, tc)							\
28601.61Skre{									\
28611.61Skre									\
28621.61Skre	tracee_sees_its_original_parent(type);				\
28631.1Skamil}
28641.1Skamil
28651.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28661.51Skamil	tracee_sees_its_original_parent_getppid,
28671.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
28681.51Skamil	"getppid(2)");
28691.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28701.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
28711.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
28721.51Skamil	"sysctl(3) and kinfo_proc2");
28731.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28741.51Skamil	tracee_sees_its_original_parent_procfs_status,
28751.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
28761.51Skamil	"the status file in procfs");
28771.1Skamil#endif
28781.1Skamil
28791.51Skamil/// ----------------------------------------------------------------------------
28801.1Skamil
28811.53Skamilstatic void
28821.53Skamileventmask_preserved(int event)
28831.1Skamil{
28841.1Skamil	const int exitval = 5;
28851.1Skamil	const int sigval = SIGSTOP;
28861.1Skamil	pid_t child, wpid;
28871.1Skamil#if defined(TWAIT_HAVE_STATUS)
28881.1Skamil	int status;
28891.1Skamil#endif
28901.1Skamil	ptrace_event_t set_event, get_event;
28911.1Skamil	const int len = sizeof(ptrace_event_t);
28921.1Skamil
28931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28951.1Skamil	if (child == 0) {
28961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28981.1Skamil
28991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29011.1Skamil
29021.13Schristos		DPRINTF("Before exiting of the child process\n");
29031.1Skamil		_exit(exitval);
29041.1Skamil	}
29051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29061.1Skamil
29071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29091.1Skamil
29101.1Skamil	validate_status_stopped(status, sigval);
29111.1Skamil
29121.53Skamil	set_event.pe_set_event = event;
29131.61Skre	SYSCALL_REQUIRE(
29141.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29151.61Skre	SYSCALL_REQUIRE(
29161.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29171.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29181.1Skamil
29191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29201.1Skamil	    "without signal to be sent\n");
29211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29221.1Skamil
29231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29251.1Skamil
29261.1Skamil	validate_status_exited(status, exitval);
29271.1Skamil
29281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29301.1Skamil}
29311.1Skamil
29321.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29331.61SkreATF_TC(test);								\
29341.61SkreATF_TC_HEAD(test, tc)							\
29351.61Skre{									\
29361.61Skre	atf_tc_set_md_var(tc, "descr",					\
29371.61Skre	    "Verify that eventmask " #event " is preserved");		\
29381.61Skre}									\
29391.61Skre									\
29401.61SkreATF_TC_BODY(test, tc)							\
29411.61Skre{									\
29421.61Skre									\
29431.61Skre	eventmask_preserved(event);					\
29441.1Skamil}
29451.1Skamil
29461.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29471.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29481.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29491.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29501.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29511.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29521.1Skamil
29531.53Skamil/// ----------------------------------------------------------------------------
29541.1Skamil
29551.28Skamilstatic void
29561.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
29571.105Skamil    bool trackvforkdone)
29581.1Skamil{
29591.1Skamil	const int exitval = 5;
29601.1Skamil	const int exitval2 = 15;
29611.1Skamil	const int sigval = SIGSTOP;
29621.31Skamil	pid_t child, child2 = 0, wpid;
29631.1Skamil#if defined(TWAIT_HAVE_STATUS)
29641.1Skamil	int status;
29651.1Skamil#endif
29661.1Skamil	ptrace_state_t state;
29671.1Skamil	const int slen = sizeof(state);
29681.1Skamil	ptrace_event_t event;
29691.1Skamil	const int elen = sizeof(event);
29701.1Skamil
29711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29731.1Skamil	if (child == 0) {
29741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29761.1Skamil
29771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29791.1Skamil
29801.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
29811.1Skamil
29821.1Skamil		if (child2 == 0)
29831.1Skamil			_exit(exitval2);
29841.1Skamil
29851.1Skamil		FORKEE_REQUIRE_SUCCESS
29861.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
29871.1Skamil
29881.1Skamil		forkee_status_exited(status, exitval2);
29891.1Skamil
29901.13Schristos		DPRINTF("Before exiting of the child process\n");
29911.1Skamil		_exit(exitval);
29921.1Skamil	}
29931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29941.1Skamil
29951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29971.1Skamil
29981.1Skamil	validate_status_stopped(status, sigval);
29991.1Skamil
30001.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
30011.61Skre	    trackfork ? "|PTRACE_FORK" : "",
30021.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
30031.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
30041.30Skamil	event.pe_set_event = 0;
30051.30Skamil	if (trackfork)
30061.30Skamil		event.pe_set_event |= PTRACE_FORK;
30071.30Skamil	if (trackvfork)
30081.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30091.30Skamil	if (trackvforkdone)
30101.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30121.1Skamil
30131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30141.1Skamil	    "without signal to be sent\n");
30151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30161.1Skamil
30171.29Skamil#if defined(TWAIT_HAVE_PID)
30181.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30191.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30201.61Skre		    child);
30211.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30221.61Skre		    child);
30231.1Skamil
30241.29Skamil		validate_status_stopped(status, SIGTRAP);
30251.1Skamil
30261.61Skre		SYSCALL_REQUIRE(
30271.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30281.31Skamil		if (trackfork && fn == fork) {
30291.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30301.30Skamil			       PTRACE_FORK);
30311.30Skamil		}
30321.31Skamil		if (trackvfork && fn == vfork) {
30331.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30341.30Skamil			       PTRACE_VFORK);
30351.30Skamil		}
30361.29Skamil
30371.29Skamil		child2 = state.pe_other_pid;
30381.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
30391.29Skamil
30401.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
30411.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
30421.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
30431.29Skamil		    child2);
30441.1Skamil
30451.29Skamil		validate_status_stopped(status, SIGTRAP);
30461.1Skamil
30471.61Skre		SYSCALL_REQUIRE(
30481.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
30491.31Skamil		if (trackfork && fn == fork) {
30501.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30511.30Skamil			       PTRACE_FORK);
30521.30Skamil		}
30531.31Skamil		if (trackvfork && fn == vfork) {
30541.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30551.30Skamil			       PTRACE_VFORK);
30561.30Skamil		}
30571.30Skamil
30581.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
30591.29Skamil
30601.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
30611.29Skamil		    "and without signal to be sent\n");
30621.61Skre		SYSCALL_REQUIRE(
30631.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
30641.29Skamil
30651.29Skamil		DPRINTF("Before resuming the child process where it left off "
30661.61Skre		    "and without signal to be sent\n");
30671.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30681.30Skamil	}
30691.30Skamil#endif
30701.30Skamil
30711.31Skamil	if (trackvforkdone && fn == vfork) {
30721.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30731.61Skre		    child);
30741.61Skre		TWAIT_REQUIRE_SUCCESS(
30751.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
30761.30Skamil
30771.30Skamil		validate_status_stopped(status, SIGTRAP);
30781.30Skamil
30791.61Skre		SYSCALL_REQUIRE(
30801.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30811.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
30821.30Skamil
30831.30Skamil		child2 = state.pe_other_pid;
30841.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
30851.61Skre		    child2);
30861.30Skamil
30871.30Skamil		DPRINTF("Before resuming the child process where it left off "
30881.61Skre		    "and without signal to be sent\n");
30891.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30901.30Skamil	}
30911.29Skamil
30921.30Skamil#if defined(TWAIT_HAVE_PID)
30931.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30941.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
30951.61Skre		    "\n", TWAIT_FNAME);
30961.61Skre		TWAIT_REQUIRE_SUCCESS(
30971.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30981.29Skamil
30991.29Skamil		validate_status_exited(status, exitval2);
31001.29Skamil
31011.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
31021.61Skre		    "process\n", TWAIT_FNAME);
31031.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
31041.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
31051.29Skamil	}
31061.29Skamil#endif
31071.1Skamil
31081.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31091.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31111.1Skamil
31121.1Skamil	validate_status_stopped(status, SIGCHLD);
31131.1Skamil
31141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31151.1Skamil	    "without signal to be sent\n");
31161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31171.1Skamil
31181.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31191.1Skamil	    TWAIT_FNAME);
31201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31211.1Skamil
31221.1Skamil	validate_status_exited(status, exitval);
31231.1Skamil
31241.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31251.1Skamil	    TWAIT_FNAME);
31261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31271.1Skamil}
31281.28Skamil
31291.105Skamil#define FORK_TEST(name,fun,tfork,tvfork,tvforkdone)			\
31301.61SkreATF_TC(name);								\
31311.61SkreATF_TC_HEAD(name, tc)							\
31321.61Skre{									\
31331.105Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
31341.105Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
31351.105Skamil	    tfork ? "|PTRACE_FORK" : "",				\
31361.105Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
31371.105Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
31381.61Skre}									\
31391.61Skre									\
31401.61SkreATF_TC_BODY(name, tc)							\
31411.61Skre{									\
31421.61Skre									\
31431.105Skamil	fork_body(fun, tfork, tvfork, tvforkdone);			\
31441.32Skamil}
31451.32Skamil
31461.105SkamilFORK_TEST(fork1, fork, false, false, false)
31471.31Skamil#if defined(TWAIT_HAVE_PID)
31481.105SkamilFORK_TEST(fork2, fork, true, false, false)
31491.105SkamilFORK_TEST(fork3, fork, false, true, false)
31501.105SkamilFORK_TEST(fork4, fork, true, true, false)
31511.31Skamil#endif
31521.105SkamilFORK_TEST(fork5, fork, false, false, true)
31531.31Skamil#if defined(TWAIT_HAVE_PID)
31541.105SkamilFORK_TEST(fork6, fork, true, false, true)
31551.105SkamilFORK_TEST(fork7, fork, false, true, true)
31561.105SkamilFORK_TEST(fork8, fork, true, true, true)
31571.31Skamil#endif
31581.1Skamil
31591.110Skamil#if TEST_VFORK_ENABLED
31601.105SkamilFORK_TEST(vfork1, vfork, false, false, false)
31611.31Skamil#if defined(TWAIT_HAVE_PID)
31621.105SkamilFORK_TEST(vfork2, vfork, true, false, false)
31631.105SkamilFORK_TEST(vfork3, vfork, false, true, false)
31641.105SkamilFORK_TEST(vfork4, vfork, true, true, false)
31651.31Skamil#endif
31661.105SkamilFORK_TEST(vfork5, vfork, false, false, true)
31671.31Skamil#if defined(TWAIT_HAVE_PID)
31681.105SkamilFORK_TEST(vfork6, vfork, true, false, true)
31691.105SkamilFORK_TEST(vfork7, vfork, false, true, true)
31701.105SkamilFORK_TEST(vfork8, vfork, true, true, true)
31711.31Skamil#endif
31721.110Skamil#endif
31731.31Skamil
31741.54Skamil/// ----------------------------------------------------------------------------
31751.31Skamil
31761.110Skamil#if TEST_VFORK_ENABLED
31771.108Skamilstatic void
31781.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void))
31791.108Skamil{
31801.108Skamil	const int exitval = 5;
31811.108Skamil	const int exitval2 = 15;
31821.108Skamil	pid_t child, child2 = 0, wpid;
31831.108Skamil#if defined(TWAIT_HAVE_STATUS)
31841.108Skamil	int status;
31851.108Skamil#endif
31861.108Skamil
31871.108Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
31881.108Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
31891.108Skamil	if (child == 0) {
31901.108Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31911.108Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31921.108Skamil
31931.108Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
31941.108Skamil
31951.108Skamil		if (child2 == 0)
31961.108Skamil			_exit(exitval2);
31971.108Skamil
31981.108Skamil		FORKEE_REQUIRE_SUCCESS
31991.108Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
32001.108Skamil
32011.108Skamil		forkee_status_exited(status, exitval2);
32021.108Skamil
32031.108Skamil		DPRINTF("Before exiting of the child process\n");
32041.108Skamil		_exit(exitval);
32051.108Skamil	}
32061.108Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32071.108Skamil
32081.108Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
32091.108Skamil	    TWAIT_FNAME);
32101.108Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32111.108Skamil
32121.108Skamil	validate_status_exited(status, exitval);
32131.108Skamil
32141.108Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
32151.108Skamil	    TWAIT_FNAME);
32161.108Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32171.108Skamil}
32181.108Skamil
32191.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun)				\
32201.108SkamilATF_TC(name);								\
32211.108SkamilATF_TC_HEAD(name, tc)							\
32221.108Skamil{									\
32231.108Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
32241.108Skamil	    "called from vfork(2)ed child");				\
32251.108Skamil}									\
32261.108Skamil									\
32271.108SkamilATF_TC_BODY(name, tc)							\
32281.108Skamil{									\
32291.108Skamil									\
32301.108Skamil	traceme_vfork_fork_body(fun);					\
32311.108Skamil}
32321.108Skamil
32331.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork)
32341.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork)
32351.110Skamil#endif
32361.108Skamil
32371.108Skamil/// ----------------------------------------------------------------------------
32381.108Skamil
32391.54Skamilenum bytes_transfer_type {
32401.54Skamil	BYTES_TRANSFER_DATA,
32411.54Skamil	BYTES_TRANSFER_DATAIO,
32421.54Skamil	BYTES_TRANSFER_TEXT,
32431.54Skamil	BYTES_TRANSFER_TEXTIO,
32441.54Skamil	BYTES_TRANSFER_AUXV
32451.54Skamil};
32461.31Skamil
32471.54Skamilstatic int __used
32481.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
32491.54Skamil{
32501.54Skamil	int e, f, g, h;
32511.1Skamil
32521.54Skamil	a *= 4;
32531.54Skamil	b += 3;
32541.54Skamil	c -= 2;
32551.54Skamil	d /= 1;
32561.1Skamil
32571.54Skamil	e = strtol("10", NULL, 10);
32581.54Skamil	f = strtol("20", NULL, 10);
32591.54Skamil	g = strtol("30", NULL, 10);
32601.54Skamil	h = strtol("40", NULL, 10);
32611.1Skamil
32621.54Skamil	return (a + b * c - d) + (e * f - g / h);
32631.1Skamil}
32641.1Skamil
32651.54Skamilstatic void
32661.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
32671.1Skamil{
32681.1Skamil	const int exitval = 5;
32691.1Skamil	const int sigval = SIGSTOP;
32701.1Skamil	pid_t child, wpid;
32711.54Skamil	bool skip = false;
32721.1Skamil
32731.54Skamil	int lookup_me = 0;
32741.54Skamil	uint8_t lookup_me8 = 0;
32751.54Skamil	uint16_t lookup_me16 = 0;
32761.54Skamil	uint32_t lookup_me32 = 0;
32771.54Skamil	uint64_t lookup_me64 = 0;
32781.1Skamil
32791.54Skamil	int magic = 0x13579246;
32801.54Skamil	uint8_t magic8 = 0xab;
32811.54Skamil	uint16_t magic16 = 0x1234;
32821.54Skamil	uint32_t magic32 = 0x98765432;
32831.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
32841.1Skamil
32851.54Skamil	struct ptrace_io_desc io;
32861.1Skamil#if defined(TWAIT_HAVE_STATUS)
32871.1Skamil	int status;
32881.1Skamil#endif
32891.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
32901.60Skre	AuxInfo ai[513], *aip;
32911.55Schristos
32921.55Schristos	ATF_REQUIRE(size < sizeof(ai));
32931.1Skamil
32941.54Skamil	/* Prepare variables for .TEXT transfers */
32951.54Skamil	switch (type) {
32961.54Skamil	case BYTES_TRANSFER_TEXT:
32971.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
32981.54Skamil		break;
32991.54Skamil	case BYTES_TRANSFER_TEXTIO:
33001.54Skamil		switch (size) {
33011.54Skamil		case 8:
33021.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
33031.54Skamil			break;
33041.54Skamil		case 16:
33051.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
33061.54Skamil			break;
33071.54Skamil		case 32:
33081.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
33091.54Skamil			break;
33101.54Skamil		case 64:
33111.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
33121.54Skamil			break;
33131.54Skamil		}
33141.54Skamil		break;
33151.54Skamil	default:
33161.54Skamil		break;
33171.54Skamil	}
33181.1Skamil
33191.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
33201.54Skamil	switch (type) {
33211.54Skamil	case BYTES_TRANSFER_TEXTIO:
33221.54Skamil	case BYTES_TRANSFER_DATAIO:
33231.54Skamil		io.piod_op = operation;
33241.54Skamil		switch (size) {
33251.54Skamil		case 8:
33261.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33271.54Skamil			               (void *)bytes_transfer_dummy :
33281.54Skamil			               &lookup_me8;
33291.54Skamil			io.piod_addr = &lookup_me8;
33301.54Skamil			io.piod_len = sizeof(lookup_me8);
33311.54Skamil			break;
33321.54Skamil		case 16:
33331.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33341.54Skamil			               (void *)bytes_transfer_dummy :
33351.54Skamil			               &lookup_me16;
33361.54Skamil			io.piod_addr = &lookup_me16;
33371.54Skamil			io.piod_len = sizeof(lookup_me16);
33381.54Skamil			break;
33391.54Skamil		case 32:
33401.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33411.54Skamil			               (void *)bytes_transfer_dummy :
33421.54Skamil			               &lookup_me32;
33431.54Skamil			io.piod_addr = &lookup_me32;
33441.54Skamil			io.piod_len = sizeof(lookup_me32);
33451.54Skamil			break;
33461.54Skamil		case 64:
33471.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33481.54Skamil			               (void *)bytes_transfer_dummy :
33491.54Skamil			               &lookup_me64;
33501.54Skamil			io.piod_addr = &lookup_me64;
33511.54Skamil			io.piod_len = sizeof(lookup_me64);
33521.54Skamil			break;
33531.54Skamil		default:
33541.54Skamil			break;
33551.54Skamil		}
33561.54Skamil		break;
33571.54Skamil	case BYTES_TRANSFER_AUXV:
33581.54Skamil		io.piod_op = operation;
33591.54Skamil		io.piod_offs = 0;
33601.54Skamil		io.piod_addr = ai;
33611.54Skamil		io.piod_len = size;
33621.54Skamil		break;
33631.54Skamil	default:
33641.54Skamil		break;
33651.1Skamil	}
33661.1Skamil
33671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33691.1Skamil	if (child == 0) {
33701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33721.1Skamil
33731.54Skamil		switch (type) {
33741.54Skamil		case BYTES_TRANSFER_DATA:
33751.54Skamil			switch (operation) {
33761.54Skamil			case PT_READ_D:
33771.54Skamil			case PT_READ_I:
33781.54Skamil				lookup_me = magic;
33791.54Skamil				break;
33801.54Skamil			default:
33811.54Skamil				break;
33821.54Skamil			}
33831.54Skamil			break;
33841.54Skamil		case BYTES_TRANSFER_DATAIO:
33851.54Skamil			switch (operation) {
33861.54Skamil			case PIOD_READ_D:
33871.54Skamil			case PIOD_READ_I:
33881.54Skamil				switch (size) {
33891.54Skamil				case 8:
33901.54Skamil					lookup_me8 = magic8;
33911.54Skamil					break;
33921.54Skamil				case 16:
33931.54Skamil					lookup_me16 = magic16;
33941.54Skamil					break;
33951.54Skamil				case 32:
33961.54Skamil					lookup_me32 = magic32;
33971.54Skamil					break;
33981.54Skamil				case 64:
33991.54Skamil					lookup_me64 = magic64;
34001.54Skamil					break;
34011.54Skamil				default:
34021.54Skamil					break;
34031.54Skamil				}
34041.54Skamil				break;
34051.54Skamil			default:
34061.54Skamil				break;
34071.54Skamil			}
34081.54Skamil		default:
34091.54Skamil			break;
34101.54Skamil		}
34111.54Skamil
34121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34141.1Skamil
34151.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
34161.54Skamil		switch (type) {
34171.54Skamil		case BYTES_TRANSFER_DATA:
34181.54Skamil			switch (operation) {
34191.54Skamil			case PT_WRITE_D:
34201.54Skamil			case PT_WRITE_I:
34211.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
34221.54Skamil				break;
34231.54Skamil			default:
34241.54Skamil				break;
34251.54Skamil			}
34261.54Skamil			break;
34271.54Skamil		case BYTES_TRANSFER_DATAIO:
34281.54Skamil			switch (operation) {
34291.54Skamil			case PIOD_WRITE_D:
34301.54Skamil			case PIOD_WRITE_I:
34311.54Skamil				switch (size) {
34321.54Skamil				case 8:
34331.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
34341.54Skamil					break;
34351.54Skamil				case 16:
34361.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
34371.54Skamil					break;
34381.54Skamil				case 32:
34391.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
34401.54Skamil					break;
34411.54Skamil				case 64:
34421.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
34431.54Skamil					break;
34441.54Skamil				default:
34451.54Skamil					break;
34461.54Skamil				}
34471.54Skamil				break;
34481.54Skamil			default:
34491.54Skamil				break;
34501.54Skamil			}
34511.54Skamil			break;
34521.54Skamil		case BYTES_TRANSFER_TEXT:
34531.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
34541.54Skamil			                     sizeof(magic)) == 0);
34551.54Skamil			break;
34561.54Skamil		case BYTES_TRANSFER_TEXTIO:
34571.54Skamil			switch (size) {
34581.54Skamil			case 8:
34591.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
34601.54Skamil				                     bytes_transfer_dummy,
34611.54Skamil				                     sizeof(magic8)) == 0);
34621.54Skamil				break;
34631.54Skamil			case 16:
34641.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
34651.54Skamil				                     bytes_transfer_dummy,
34661.54Skamil				                     sizeof(magic16)) == 0);
34671.54Skamil				break;
34681.54Skamil			case 32:
34691.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
34701.54Skamil				                     bytes_transfer_dummy,
34711.54Skamil				                     sizeof(magic32)) == 0);
34721.54Skamil				break;
34731.54Skamil			case 64:
34741.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
34751.54Skamil				                     bytes_transfer_dummy,
34761.54Skamil				                     sizeof(magic64)) == 0);
34771.54Skamil				break;
34781.54Skamil			}
34791.54Skamil			break;
34801.54Skamil		default:
34811.54Skamil			break;
34821.54Skamil		}
34831.54Skamil
34841.13Schristos		DPRINTF("Before exiting of the child process\n");
34851.1Skamil		_exit(exitval);
34861.1Skamil	}
34871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34881.1Skamil
34891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34911.1Skamil
34921.1Skamil	validate_status_stopped(status, sigval);
34931.1Skamil
34941.54Skamil	/* Check PaX MPROTECT */
34951.54Skamil	if (!can_we_write_to_text(child)) {
34961.54Skamil		switch (type) {
34971.54Skamil		case BYTES_TRANSFER_TEXTIO:
34981.54Skamil			switch (operation) {
34991.54Skamil			case PIOD_WRITE_D:
35001.54Skamil			case PIOD_WRITE_I:
35011.54Skamil				skip = true;
35021.54Skamil				break;
35031.54Skamil			default:
35041.54Skamil				break;
35051.54Skamil			}
35061.54Skamil			break;
35071.54Skamil		case BYTES_TRANSFER_TEXT:
35081.54Skamil			switch (operation) {
35091.54Skamil			case PT_WRITE_D:
35101.54Skamil			case PT_WRITE_I:
35111.54Skamil				skip = true;
35121.54Skamil				break;
35131.54Skamil			default:
35141.54Skamil				break;
35151.54Skamil			}
35161.54Skamil			break;
35171.54Skamil		default:
35181.54Skamil			break;
35191.54Skamil		}
35201.54Skamil	}
35211.1Skamil
35221.54Skamil	/* Bailout cleanly killing the child process */
35231.54Skamil	if (skip) {
35241.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
35251.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35261.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
35271.54Skamil		                      child);
35281.1Skamil
35291.54Skamil		validate_status_signaled(status, SIGKILL, 0);
35301.1Skamil
35311.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
35321.54Skamil	}
35331.1Skamil
35341.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
35351.54Skamil	       "parent=%d\n", child, getpid());
35361.1Skamil
35371.54Skamil	switch (type) {
35381.54Skamil	case BYTES_TRANSFER_TEXTIO:
35391.54Skamil	case BYTES_TRANSFER_DATAIO:
35401.54Skamil	case BYTES_TRANSFER_AUXV:
35411.54Skamil		switch (operation) {
35421.54Skamil		case PIOD_WRITE_D:
35431.54Skamil		case PIOD_WRITE_I:
35441.54Skamil			switch (size) {
35451.54Skamil			case 8:
35461.54Skamil				lookup_me8 = magic8;
35471.54Skamil				break;
35481.54Skamil			case 16:
35491.54Skamil				lookup_me16 = magic16;
35501.54Skamil				break;
35511.54Skamil			case 32:
35521.54Skamil				lookup_me32 = magic32;
35531.54Skamil				break;
35541.54Skamil			case 64:
35551.54Skamil				lookup_me64 = magic64;
35561.54Skamil				break;
35571.54Skamil			default:
35581.54Skamil				break;
35591.54Skamil			}
35601.54Skamil			break;
35611.54Skamil		default:
35621.54Skamil			break;
35631.54Skamil		}
35641.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35651.54Skamil		switch (operation) {
35661.54Skamil		case PIOD_READ_D:
35671.54Skamil		case PIOD_READ_I:
35681.54Skamil			switch (size) {
35691.54Skamil			case 8:
35701.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
35711.54Skamil				break;
35721.54Skamil			case 16:
35731.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
35741.54Skamil				break;
35751.54Skamil			case 32:
35761.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
35771.54Skamil				break;
35781.54Skamil			case 64:
35791.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
35801.54Skamil				break;
35811.54Skamil			default:
35821.54Skamil				break;
35831.54Skamil			}
35841.54Skamil			break;
35851.54Skamil		case PIOD_READ_AUXV:
35861.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
35871.54Skamil			        io.piod_len);
35881.54Skamil			ATF_REQUIRE(io.piod_len > 0);
35891.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
35901.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
35911.54Skamil				    (long long int)aip->a_type,
35921.54Skamil				    (long long int)aip->a_v);
35931.54Skamil			break;
35941.54Skamil		default:
35951.54Skamil			break;
35961.54Skamil		}
35971.54Skamil		break;
35981.54Skamil	case BYTES_TRANSFER_TEXT:
35991.54Skamil		switch (operation) {
36001.54Skamil		case PT_READ_D:
36011.54Skamil		case PT_READ_I:
36021.54Skamil			errno = 0;
36031.54Skamil			lookup_me = ptrace(operation, child,
36041.54Skamil			                   bytes_transfer_dummy, 0);
36051.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
36061.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
36071.54Skamil			break;
36081.54Skamil		case PT_WRITE_D:
36091.54Skamil		case PT_WRITE_I:
36101.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
36111.54Skamil			                       bytes_transfer_dummy, magic)
36121.54Skamil			                != -1);
36131.54Skamil			break;
36141.54Skamil		default:
36151.54Skamil			break;
36161.54Skamil		}
36171.54Skamil		break;
36181.54Skamil	case BYTES_TRANSFER_DATA:
36191.54Skamil		switch (operation) {
36201.54Skamil		case PT_READ_D:
36211.54Skamil		case PT_READ_I:
36221.54Skamil			errno = 0;
36231.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
36241.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
36251.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
36261.54Skamil			break;
36271.54Skamil		case PT_WRITE_D:
36281.54Skamil		case PT_WRITE_I:
36291.54Skamil			lookup_me = magic;
36301.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
36311.54Skamil			                       magic) != -1);
36321.54Skamil			break;
36331.54Skamil		default:
36341.54Skamil			break;
36351.54Skamil		}
36361.54Skamil		break;
36371.54Skamil	default:
36381.54Skamil		break;
36391.54Skamil	}
36401.1Skamil
36411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36421.1Skamil	    "without signal to be sent\n");
36431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36441.1Skamil
36451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36471.1Skamil
36481.1Skamil	validate_status_exited(status, exitval);
36491.1Skamil
36501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36521.1Skamil}
36531.1Skamil
36541.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
36551.61SkreATF_TC(test);								\
36561.61SkreATF_TC_HEAD(test, tc)							\
36571.61Skre{									\
36581.61Skre	atf_tc_set_md_var(tc, "descr",					\
36591.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
36601.61Skre	    " of type " #type);						\
36611.61Skre}									\
36621.61Skre									\
36631.61SkreATF_TC_BODY(test, tc)							\
36641.61Skre{									\
36651.61Skre									\
36661.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
36671.1Skamil}
36681.1Skamil
36691.54Skamil// DATA
36701.1Skamil
36711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
36721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
36731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
36741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
36751.54Skamil
36761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
36771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
36781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
36791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
36801.54Skamil
36811.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
36821.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
36831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
36841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
36851.54Skamil
36861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
36871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
36881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
36891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
36901.54Skamil
36911.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
36921.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
36931.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
36941.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
36951.54Skamil
36961.54Skamil// TEXT
36971.54Skamil
36981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
36991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
37001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
37011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
37021.54Skamil
37031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
37041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
37051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
37061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
37071.54Skamil
37081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
37091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
37101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
37111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
37121.54Skamil
37131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
37141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
37151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
37161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
37171.54Skamil
37181.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
37191.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
37201.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
37211.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
37221.1Skamil
37231.54Skamil// AUXV
37241.1Skamil
37251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
37261.1Skamil
37271.54Skamil/// ----------------------------------------------------------------------------
37281.1Skamil
37291.101Skamilstatic void
37301.101Skamilbytes_transfer_alignment(const char *operation)
37311.101Skamil{
37321.101Skamil	const int exitval = 5;
37331.101Skamil	const int sigval = SIGSTOP;
37341.101Skamil	pid_t child, wpid;
37351.101Skamil#if defined(TWAIT_HAVE_STATUS)
37361.101Skamil	int status;
37371.101Skamil#endif
37381.101Skamil	char *buffer;
37391.101Skamil	int vector;
37401.101Skamil	size_t len;
37411.101Skamil	size_t i;
37421.101Skamil	int op;
37431.101Skamil
37441.101Skamil	struct ptrace_io_desc io;
37451.101Skamil	struct ptrace_siginfo info;
37461.101Skamil
37471.101Skamil	memset(&io, 0, sizeof(io));
37481.101Skamil	memset(&info, 0, sizeof(info));
37491.101Skamil
37501.101Skamil	/* Testing misaligned byte transfer crossing page boundaries */
37511.101Skamil	len = sysconf(_SC_PAGESIZE) * 2;
37521.101Skamil	buffer = malloc(len);
37531.101Skamil	ATF_REQUIRE(buffer != NULL);
37541.101Skamil
37551.101Skamil	/* Initialize the buffer with random data */
37561.101Skamil	for (i = 0; i < len; i++)
37571.101Skamil		buffer[i] = i & 0xff;
37581.101Skamil
37591.101Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
37601.101Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
37611.101Skamil	if (child == 0) {
37621.101Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37631.101Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37641.101Skamil
37651.101Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37661.101Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37671.101Skamil
37681.101Skamil		DPRINTF("Before exiting of the child process\n");
37691.101Skamil		_exit(exitval);
37701.101Skamil	}
37711.101Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37721.101Skamil
37731.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37741.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37751.101Skamil
37761.101Skamil	validate_status_stopped(status, sigval);
37771.101Skamil
37781.101Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37791.101Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
37801.101Skamil		!= -1);
37811.101Skamil
37821.101Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37831.101Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
37841.101Skamil		"si_errno=%#x\n",
37851.101Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37861.101Skamil		info.psi_siginfo.si_errno);
37871.101Skamil
37881.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
37891.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
37901.101Skamil
37911.101Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
37921.101Skamil	    strcmp(operation, "PT_READ_D") == 0) {
37931.101Skamil		if (strcmp(operation, "PT_READ_I"))
37941.101Skamil			op = PT_READ_I;
37951.101Skamil		else
37961.101Skamil			op = PT_READ_D;
37971.101Skamil
37981.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
37991.101Skamil			errno = 0;
38001.101Skamil			vector = ptrace(op, child, buffer + i, 0);
38011.101Skamil			ATF_REQUIRE_EQ(errno, 0);
38021.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
38031.101Skamil		}
38041.101Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
38051.101Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
38061.101Skamil		if (strcmp(operation, "PT_WRITE_I"))
38071.101Skamil			op = PT_WRITE_I;
38081.101Skamil		else
38091.101Skamil			op = PT_WRITE_D;
38101.101Skamil
38111.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38121.101Skamil			memcpy(&vector, buffer + i, sizeof(int));
38131.101Skamil			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
38141.101Skamil			    != -1);
38151.101Skamil		}
38161.101Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
38171.101Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
38181.101Skamil		if (strcmp(operation, "PIOD_READ_I"))
38191.101Skamil			op = PIOD_READ_I;
38201.101Skamil		else
38211.101Skamil			op = PIOD_READ_D;
38221.101Skamil
38231.101Skamil		io.piod_op = op;
38241.101Skamil		io.piod_addr = &vector;
38251.101Skamil		io.piod_len = sizeof(int);
38261.101Skamil
38271.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38281.101Skamil			io.piod_offs = buffer + i;
38291.101Skamil
38301.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38311.101Skamil			                != -1);
38321.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
38331.101Skamil		}
38341.101Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
38351.101Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
38361.101Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
38371.101Skamil			op = PIOD_WRITE_I;
38381.101Skamil		else
38391.101Skamil			op = PIOD_WRITE_D;
38401.101Skamil
38411.101Skamil		io.piod_op = op;
38421.101Skamil		io.piod_addr = &vector;
38431.101Skamil		io.piod_len = sizeof(int);
38441.101Skamil
38451.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38461.101Skamil			io.piod_offs = buffer + i;
38471.101Skamil
38481.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38491.101Skamil			                != -1);
38501.101Skamil		}
38511.101Skamil	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
38521.101Skamil		io.piod_op = PIOD_READ_AUXV;
38531.101Skamil		io.piod_addr = &vector;
38541.101Skamil		io.piod_len = sizeof(int);
38551.101Skamil
38561.101Skamil		errno = 0;
38571.101Skamil		i = 0;
38581.101Skamil		/* Read the whole AUXV vector, it has no clear length */
38591.101Skamil		while (errno != EIO) {
38601.101Skamil			io.piod_offs = (void *)(intptr_t)i;
38611.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38621.101Skamil			                != -1 || (errno == EIO && i > 0));
38631.101Skamil			++i;
38641.101Skamil		}
38651.101Skamil	}
38661.101Skamil
38671.101Skamil	DPRINTF("Before resuming the child process where it left off "
38681.101Skamil	    "and without signal to be sent\n");
38691.101Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38701.101Skamil
38711.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38721.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
38731.101Skamil	    child);
38741.101Skamil
38751.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38761.101Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38771.101Skamil}
38781.101Skamil
38791.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
38801.101SkamilATF_TC(test);								\
38811.101SkamilATF_TC_HEAD(test, tc)							\
38821.101Skamil{									\
38831.101Skamil	atf_tc_set_md_var(tc, "descr",					\
38841.101Skamil	    "Verify bytes transfer for potentially misaligned "		\
38851.101Skamil	    "operation " operation);					\
38861.101Skamil}									\
38871.101Skamil									\
38881.101SkamilATF_TC_BODY(test, tc)							\
38891.101Skamil{									\
38901.101Skamil									\
38911.101Skamil	bytes_transfer_alignment(operation);				\
38921.101Skamil}
38931.101Skamil
38941.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
38951.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
38961.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
38971.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
38981.101Skamil
38991.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
39001.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
39011.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
39021.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
39031.101Skamil
39041.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
39051.101Skamil
39061.101Skamil/// ----------------------------------------------------------------------------
39071.101Skamil
39081.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
39091.72Skamilstatic void
39101.72Skamilaccess_regs(const char *regset, const char *aux)
39111.1Skamil{
39121.1Skamil	const int exitval = 5;
39131.1Skamil	const int sigval = SIGSTOP;
39141.1Skamil	pid_t child, wpid;
39151.1Skamil#if defined(TWAIT_HAVE_STATUS)
39161.1Skamil	int status;
39171.1Skamil#endif
39181.72Skamil#if defined(HAVE_GPREGS)
39191.72Skamil	struct reg gpr;
39201.76Sscole	register_t rgstr;
39211.1Skamil#endif
39221.72Skamil#if defined(HAVE_FPREGS)
39231.72Skamil	struct fpreg fpr;
39241.1Skamil#endif
39251.76Sscole
39261.72Skamil#if !defined(HAVE_GPREGS)
39271.72Skamil	if (strcmp(regset, "regs") == 0)
39281.72Skamil		atf_tc_fail("Impossible test scenario!");
39291.1Skamil#endif
39301.1Skamil
39311.72Skamil#if !defined(HAVE_FPREGS)
39321.72Skamil	if (strcmp(regset, "fpregs") == 0)
39331.72Skamil		atf_tc_fail("Impossible test scenario!");
39341.1Skamil#endif
39351.1Skamil
39361.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39371.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39381.1Skamil	if (child == 0) {
39391.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39401.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39411.1Skamil
39421.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39431.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39441.1Skamil
39451.13Schristos		DPRINTF("Before exiting of the child process\n");
39461.1Skamil		_exit(exitval);
39471.1Skamil	}
39481.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39491.1Skamil
39501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39521.1Skamil
39531.1Skamil	validate_status_stopped(status, sigval);
39541.1Skamil
39551.1Skamil#if defined(HAVE_GPREGS)
39561.72Skamil	if (strcmp(regset, "regs") == 0) {
39571.72Skamil		DPRINTF("Call GETREGS for the child process\n");
39581.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
39591.72Skamil
39601.72Skamil		if (strcmp(aux, "none") == 0) {
39611.72Skamil			DPRINTF("Retrieved registers\n");
39621.72Skamil		} else if (strcmp(aux, "pc") == 0) {
39631.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
39641.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39651.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
39661.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
39671.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
39681.72Skamil		} else if (strcmp(aux, "sp") == 0) {
39691.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
39701.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39711.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
39721.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
39731.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39741.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
39751.72Skamil			DPRINTF("Call SETREGS for the child process\n");
39761.72Skamil			SYSCALL_REQUIRE(
39771.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
39781.72Skamil		}
39791.72Skamil	}
39801.1Skamil#endif
39811.1Skamil
39821.72Skamil#if defined(HAVE_FPREGS)
39831.72Skamil	if (strcmp(regset, "fpregs") == 0) {
39841.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
39851.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
39861.72Skamil
39871.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
39881.72Skamil			DPRINTF("Retrieved FP registers\n");
39891.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
39901.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
39911.72Skamil			SYSCALL_REQUIRE(
39921.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
39931.72Skamil		}
39941.1Skamil	}
39951.1Skamil#endif
39961.1Skamil
39971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39981.1Skamil	    "without signal to be sent\n");
39991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40001.1Skamil
40011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40031.1Skamil
40041.1Skamil	validate_status_exited(status, exitval);
40051.1Skamil
40061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40081.1Skamil}
40091.1Skamil
40101.72Skamil#define ACCESS_REGS(test, regset, aux)					\
40111.72SkamilATF_TC(test);								\
40121.72SkamilATF_TC_HEAD(test, tc)							\
40131.72Skamil{									\
40141.72Skamil        atf_tc_set_md_var(tc, "descr",					\
40151.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
40161.72Skamil}									\
40171.72Skamil									\
40181.72SkamilATF_TC_BODY(test, tc)							\
40191.72Skamil{									\
40201.72Skamil									\
40211.72Skamil        access_regs(regset, aux);					\
40221.1Skamil}
40231.1Skamil#endif
40241.1Skamil
40251.72Skamil#if defined(HAVE_GPREGS)
40261.72SkamilACCESS_REGS(access_regs1, "regs", "none")
40271.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
40281.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
40291.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
40301.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
40311.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
40321.1Skamil#endif
40331.1Skamil#if defined(HAVE_FPREGS)
40341.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
40351.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
40361.1Skamil#endif
40371.1Skamil
40381.72Skamil/// ----------------------------------------------------------------------------
40391.1Skamil
40401.1Skamil#if defined(PT_STEP)
40411.1Skamilstatic void
40421.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
40431.1Skamil{
40441.1Skamil	const int exitval = 5;
40451.1Skamil	const int sigval = SIGSTOP;
40461.1Skamil	pid_t child, wpid;
40471.1Skamil#if defined(TWAIT_HAVE_STATUS)
40481.1Skamil	int status;
40491.1Skamil#endif
40501.1Skamil	int happy;
40511.95Skamil	struct sigaction sa;
40521.81Skamil	struct ptrace_siginfo info;
40531.95Skamil	sigset_t intmask;
40541.95Skamil	struct kinfo_proc2 kp;
40551.95Skamil	size_t len = sizeof(kp);
40561.95Skamil
40571.95Skamil	int name[6];
40581.95Skamil	const size_t namelen = __arraycount(name);
40591.95Skamil	ki_sigset_t kp_sigmask;
40601.95Skamil	ki_sigset_t kp_sigignore;
40611.1Skamil
40621.1Skamil#if defined(__arm__)
40631.1Skamil	/* PT_STEP not supported on arm 32-bit */
40641.1Skamil	atf_tc_expect_fail("PR kern/52119");
40651.1Skamil#endif
40661.1Skamil
40671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40691.1Skamil	if (child == 0) {
40701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40721.1Skamil
40731.95Skamil		if (masked) {
40741.95Skamil			sigemptyset(&intmask);
40751.95Skamil			sigaddset(&intmask, SIGTRAP);
40761.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
40771.95Skamil		}
40781.95Skamil
40791.95Skamil		if (ignored) {
40801.95Skamil			memset(&sa, 0, sizeof(sa));
40811.95Skamil			sa.sa_handler = SIG_IGN;
40821.95Skamil			sigemptyset(&sa.sa_mask);
40831.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
40841.95Skamil		}
40851.95Skamil
40861.1Skamil		happy = check_happy(999);
40871.1Skamil
40881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40901.1Skamil
40911.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
40921.1Skamil
40931.13Schristos		DPRINTF("Before exiting of the child process\n");
40941.1Skamil		_exit(exitval);
40951.1Skamil	}
40961.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40971.1Skamil
40981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41001.1Skamil
41011.1Skamil	validate_status_stopped(status, sigval);
41021.1Skamil
41031.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
41041.81Skamil	SYSCALL_REQUIRE(
41051.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41061.81Skamil
41071.81Skamil	DPRINTF("Before checking siginfo_t\n");
41081.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
41091.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
41101.81Skamil
41111.95Skamil	name[0] = CTL_KERN,
41121.95Skamil	name[1] = KERN_PROC2,
41131.95Skamil	name[2] = KERN_PROC_PID;
41141.95Skamil	name[3] = child;
41151.95Skamil	name[4] = sizeof(kp);
41161.95Skamil	name[5] = 1;
41171.95Skamil
41181.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
41191.95Skamil
41201.95Skamil	if (masked)
41211.95Skamil		kp_sigmask = kp.p_sigmask;
41221.95Skamil
41231.95Skamil	if (ignored)
41241.95Skamil		kp_sigignore = kp.p_sigignore;
41251.95Skamil
41261.1Skamil	while (N --> 0) {
41271.2Skamil		if (setstep) {
41281.13Schristos			DPRINTF("Before resuming the child process where it "
41291.2Skamil			    "left off and without signal to be sent (use "
41301.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
41311.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
41321.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
41331.2Skamil			    != -1);
41341.2Skamil		} else {
41351.13Schristos			DPRINTF("Before resuming the child process where it "
41361.2Skamil			    "left off and without signal to be sent (use "
41371.2Skamil			    "PT_STEP)\n");
41381.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
41391.2Skamil			    != -1);
41401.2Skamil		}
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),
41441.1Skamil		    child);
41451.1Skamil
41461.1Skamil		validate_status_stopped(status, SIGTRAP);
41471.2Skamil
41481.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
41491.81Skamil		SYSCALL_REQUIRE(
41501.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41511.81Skamil
41521.81Skamil		DPRINTF("Before checking siginfo_t\n");
41531.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
41541.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
41551.81Skamil
41561.2Skamil		if (setstep) {
41571.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
41581.2Skamil		}
41591.95Skamil
41601.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
41611.95Skamil
41621.95Skamil		if (masked) {
41631.95Skamil			DPRINTF("kp_sigmask="
41641.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41651.95Skamil			    PRIx32 "\n",
41661.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
41671.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
41681.95Skamil
41691.95Skamil			DPRINTF("kp.p_sigmask="
41701.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41711.95Skamil			    PRIx32 "\n",
41721.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
41731.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
41741.95Skamil
41751.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
41761.95Skamil			    sizeof(kp_sigmask)));
41771.95Skamil		}
41781.95Skamil
41791.95Skamil		if (ignored) {
41801.95Skamil			DPRINTF("kp_sigignore="
41811.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41821.95Skamil			    PRIx32 "\n",
41831.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
41841.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
41851.95Skamil
41861.95Skamil			DPRINTF("kp.p_sigignore="
41871.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41881.95Skamil			    PRIx32 "\n",
41891.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
41901.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
41911.95Skamil
41921.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
41931.95Skamil			    sizeof(kp_sigignore)));
41941.95Skamil		}
41951.1Skamil	}
41961.1Skamil
41971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41981.1Skamil	    "without signal to be sent\n");
41991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42001.1Skamil
42011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42031.1Skamil
42041.1Skamil	validate_status_exited(status, exitval);
42051.1Skamil
42061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42081.1Skamil}
42091.1Skamil
42101.73Skamil#define PTRACE_STEP(test, N, setstep)					\
42111.73SkamilATF_TC(test);								\
42121.73SkamilATF_TC_HEAD(test, tc)							\
42131.73Skamil{									\
42141.73Skamil        atf_tc_set_md_var(tc, "descr",					\
42151.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
42161.73Skamil}									\
42171.73Skamil									\
42181.73SkamilATF_TC_BODY(test, tc)							\
42191.73Skamil{									\
42201.73Skamil									\
42211.95Skamil        ptrace_step(N, setstep, false, false);				\
42221.1Skamil}
42231.1Skamil
42241.73SkamilPTRACE_STEP(step1, 1, 0)
42251.73SkamilPTRACE_STEP(step2, 2, 0)
42261.73SkamilPTRACE_STEP(step3, 3, 0)
42271.73SkamilPTRACE_STEP(step4, 4, 0)
42281.73SkamilPTRACE_STEP(setstep1, 1, 1)
42291.73SkamilPTRACE_STEP(setstep2, 2, 1)
42301.73SkamilPTRACE_STEP(setstep3, 3, 1)
42311.73SkamilPTRACE_STEP(setstep4, 4, 1)
42321.95Skamil
42331.95SkamilATF_TC(step_signalmasked);
42341.95SkamilATF_TC_HEAD(step_signalmasked, tc)
42351.95Skamil{
42361.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
42371.95Skamil}
42381.95Skamil
42391.95SkamilATF_TC_BODY(step_signalmasked, tc)
42401.95Skamil{
42411.95Skamil
42421.95Skamil	ptrace_step(1, 0, true, false);
42431.95Skamil}
42441.95Skamil
42451.95SkamilATF_TC(step_signalignored);
42461.95SkamilATF_TC_HEAD(step_signalignored, tc)
42471.95Skamil{
42481.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
42491.95Skamil}
42501.95Skamil
42511.95SkamilATF_TC_BODY(step_signalignored, tc)
42521.95Skamil{
42531.95Skamil
42541.95Skamil	ptrace_step(1, 0, false, true);
42551.95Skamil}
42561.1Skamil#endif
42571.1Skamil
42581.73Skamil/// ----------------------------------------------------------------------------
42591.1Skamil
42601.75Skamilstatic void
42611.75Skamilptrace_kill(const char *type)
42621.1Skamil{
42631.75Skamil	const int sigval = SIGSTOP;
42641.1Skamil	pid_t child, wpid;
42651.1Skamil#if defined(TWAIT_HAVE_STATUS)
42661.1Skamil	int status;
42671.1Skamil#endif
42681.1Skamil
42691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42711.1Skamil	if (child == 0) {
42721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42741.1Skamil
42751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42771.1Skamil
42781.1Skamil		/* NOTREACHED */
42791.1Skamil		FORKEE_ASSERTX(0 &&
42801.1Skamil		    "Child should be terminated by a signal from its parent");
42811.1Skamil	}
42821.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42831.1Skamil
42841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42861.1Skamil
42871.1Skamil	validate_status_stopped(status, sigval);
42881.1Skamil
42891.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
42901.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
42911.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
42921.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
42931.75Skamil		kill(child, SIGKILL);
42941.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
42951.75Skamil		setpgid(child, 0);
42961.75Skamil		killpg(getpgid(child), SIGKILL);
42971.75Skamil	}
42981.1Skamil
42991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43011.1Skamil
43021.75Skamil	validate_status_signaled(status, SIGKILL, 0);
43031.1Skamil
43041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43051.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43061.1Skamil}
43071.1Skamil
43081.75Skamil#define PTRACE_KILL(test, type)						\
43091.75SkamilATF_TC(test);								\
43101.75SkamilATF_TC_HEAD(test, tc)							\
43111.75Skamil{									\
43121.75Skamil        atf_tc_set_md_var(tc, "descr",					\
43131.75Skamil            "Verify killing the child with " type);			\
43141.75Skamil}									\
43151.75Skamil									\
43161.75SkamilATF_TC_BODY(test, tc)							\
43171.75Skamil{									\
43181.75Skamil									\
43191.75Skamil        ptrace_kill(type);						\
43201.1Skamil}
43211.1Skamil
43221.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
43231.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
43241.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
43251.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
43261.1Skamil
43271.75Skamil/// ----------------------------------------------------------------------------
43281.1Skamil
43291.77Skamilstatic void
43301.77Skamiltraceme_lwpinfo(const int threads)
43311.1Skamil{
43321.1Skamil	const int sigval = SIGSTOP;
43331.77Skamil	const int sigval2 = SIGINT;
43341.1Skamil	pid_t child, wpid;
43351.1Skamil#if defined(TWAIT_HAVE_STATUS)
43361.1Skamil	int status;
43371.1Skamil#endif
43381.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
43391.77Skamil	struct ptrace_siginfo info;
43401.77Skamil
43411.77Skamil	/* Maximum number of supported threads in this test */
43421.77Skamil	pthread_t t[3];
43431.77Skamil	int n, rv;
43441.77Skamil
43451.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
43461.1Skamil
43471.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43481.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43491.1Skamil	if (child == 0) {
43501.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43511.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43521.1Skamil
43531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43551.1Skamil
43561.77Skamil		for (n = 0; n < threads; n++) {
43571.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
43581.77Skamil			FORKEE_ASSERT(rv == 0);
43591.77Skamil		}
43601.77Skamil
43611.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
43621.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
43631.77Skamil
43641.77Skamil		/* NOTREACHED */
43651.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
43661.1Skamil	}
43671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43681.1Skamil
43691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43711.1Skamil
43721.1Skamil	validate_status_stopped(status, sigval);
43731.1Skamil
43741.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
43751.77Skamil	SYSCALL_REQUIRE(
43761.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
43771.77Skamil
43781.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
43791.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
43801.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
43811.77Skamil	    info.psi_siginfo.si_errno);
43821.77Skamil
43831.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
43841.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
43851.77Skamil
43861.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
43871.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
43881.1Skamil
43891.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
43901.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
43911.1Skamil
43921.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
43931.77Skamil	    lwp.pl_lwpid);
43941.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
43951.1Skamil
43961.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
43971.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
43981.1Skamil
43991.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
44001.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
44011.1Skamil
44021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44031.1Skamil	    "without signal to be sent\n");
44041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44051.1Skamil
44061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44081.1Skamil
44091.77Skamil	validate_status_stopped(status, sigval2);
44101.77Skamil
44111.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
44121.77Skamil	SYSCALL_REQUIRE(
44131.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
44141.77Skamil
44151.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
44161.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
44171.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
44181.77Skamil	    info.psi_siginfo.si_errno);
44191.77Skamil
44201.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
44211.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
44221.77Skamil
44231.77Skamil	memset(&lwp, 0, sizeof(lwp));
44241.77Skamil
44251.77Skamil	for (n = 0; n <= threads; n++) {
44261.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
44271.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
44281.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
44291.77Skamil
44301.77Skamil		DPRINTF("Assert that the thread exists\n");
44311.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
44321.77Skamil
44331.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
44341.77Skamil		    lwp.pl_lwpid);
44351.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
44361.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
44371.77Skamil	}
44381.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
44391.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
44401.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
44411.77Skamil
44421.77Skamil	DPRINTF("Assert that there are no more threads\n");
44431.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
44441.77Skamil
44451.77Skamil	DPRINTF("Before resuming the child process where it left off and "
44461.77Skamil	    "without signal to be sent\n");
44471.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
44481.77Skamil
44491.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44501.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44511.77Skamil
44521.77Skamil	validate_status_signaled(status, SIGKILL, 0);
44531.1Skamil
44541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44561.1Skamil}
44571.1Skamil
44581.77Skamil#define TRACEME_LWPINFO(test, threads)					\
44591.77SkamilATF_TC(test);								\
44601.77SkamilATF_TC_HEAD(test, tc)							\
44611.77Skamil{									\
44621.77Skamil	atf_tc_set_md_var(tc, "descr",					\
44631.77Skamil	    "Verify LWPINFO with the child with " #threads		\
44641.77Skamil	    " spawned extra threads");					\
44651.77Skamil}									\
44661.77Skamil									\
44671.77SkamilATF_TC_BODY(test, tc)							\
44681.77Skamil{									\
44691.77Skamil									\
44701.77Skamil	traceme_lwpinfo(threads);					\
44711.1Skamil}
44721.1Skamil
44731.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
44741.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
44751.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
44761.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
44771.77Skamil
44781.77Skamil/// ----------------------------------------------------------------------------
44791.77Skamil
44801.77Skamil#if defined(TWAIT_HAVE_PID)
44811.77Skamilstatic void
44821.77Skamilattach_lwpinfo(const int threads)
44831.1Skamil{
44841.77Skamil	const int sigval = SIGINT;
44851.1Skamil	struct msg_fds parent_tracee, parent_tracer;
44861.1Skamil	const int exitval_tracer = 10;
44871.1Skamil	pid_t tracee, tracer, wpid;
44881.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
44891.1Skamil#if defined(TWAIT_HAVE_STATUS)
44901.1Skamil	int status;
44911.1Skamil#endif
44921.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
44931.77Skamil	struct ptrace_siginfo info;
44941.77Skamil
44951.77Skamil	/* Maximum number of supported threads in this test */
44961.77Skamil	pthread_t t[3];
44971.77Skamil	int n, rv;
44981.1Skamil
44991.13Schristos	DPRINTF("Spawn tracee\n");
45001.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
45011.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
45021.1Skamil	tracee = atf_utils_fork();
45031.1Skamil	if (tracee == 0) {
45041.1Skamil		/* Wait for message from the parent */
45051.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
45061.1Skamil
45071.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
45081.77Skamil
45091.77Skamil		for (n = 0; n < threads; n++) {
45101.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
45111.77Skamil			FORKEE_ASSERT(rv == 0);
45121.77Skamil		}
45131.77Skamil
45141.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
45151.77Skamil
45161.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45171.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45181.77Skamil
45191.77Skamil		/* NOTREACHED */
45201.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
45211.1Skamil	}
45221.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
45231.1Skamil
45241.13Schristos	DPRINTF("Spawn debugger\n");
45251.1Skamil	tracer = atf_utils_fork();
45261.1Skamil	if (tracer == 0) {
45271.1Skamil		/* No IPC to communicate with the child */
45281.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
45291.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
45301.1Skamil
45311.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
45321.1Skamil		FORKEE_REQUIRE_SUCCESS(
45331.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
45341.1Skamil
45351.1Skamil		forkee_status_stopped(status, SIGSTOP);
45361.1Skamil
45371.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
45381.77Skamil		    "tracee");
45391.77Skamil		FORKEE_ASSERT(
45401.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
45411.77Skamil
45421.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45431.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
45441.77Skamil		    "si_errno=%#x\n",
45451.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45461.77Skamil		    info.psi_siginfo.si_errno);
45471.77Skamil
45481.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
45491.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
45501.77Skamil
45511.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
45521.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
45531.1Skamil		    != -1);
45541.1Skamil
45551.13Schristos		DPRINTF("Assert that there exists a thread\n");
45561.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
45571.1Skamil
45581.13Schristos		DPRINTF("Assert that lwp thread %d received event "
45591.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
45601.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
45611.1Skamil
45621.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
45631.77Skamil		    "tracee\n");
45641.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
45651.1Skamil		    != -1);
45661.1Skamil
45671.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
45681.77Skamil		    "tracee\n");
45691.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
45701.1Skamil
45711.1Skamil		/* Resume tracee with PT_CONTINUE */
45721.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
45731.1Skamil
45741.1Skamil		/* Inform parent that tracer has attached to tracee */
45751.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
45761.77Skamil
45771.1Skamil		/* Wait for parent */
45781.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
45791.1Skamil
45801.77Skamil		/* Wait for tracee and assert that it raised a signal */
45811.77Skamil		FORKEE_REQUIRE_SUCCESS(
45821.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
45831.77Skamil
45841.77Skamil		forkee_status_stopped(status, SIGINT);
45851.77Skamil
45861.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
45871.77Skamil		    "child");
45881.77Skamil		FORKEE_ASSERT(
45891.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
45901.77Skamil
45911.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45921.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
45931.77Skamil		    "si_errno=%#x\n",
45941.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45951.77Skamil		    info.psi_siginfo.si_errno);
45961.77Skamil
45971.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
45981.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
45991.77Skamil
46001.77Skamil		memset(&lwp, 0, sizeof(lwp));
46011.77Skamil
46021.77Skamil		for (n = 0; n <= threads; n++) {
46031.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
46041.77Skamil			    "child\n");
46051.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
46061.77Skamil			    sizeof(lwp)) != -1);
46071.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
46081.77Skamil
46091.77Skamil			DPRINTF("Assert that the thread exists\n");
46101.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
46111.77Skamil
46121.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
46131.77Skamil			    "event\n", lwp.pl_lwpid);
46141.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
46151.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
46161.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
46171.77Skamil		}
46181.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
46191.77Skamil		    "tracee\n");
46201.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
46211.77Skamil		    != -1);
46221.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
46231.77Skamil
46241.77Skamil		DPRINTF("Assert that there are no more threads\n");
46251.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
46261.77Skamil
46271.77Skamil		DPRINTF("Before resuming the child process where it left off "
46281.77Skamil		    "and without signal to be sent\n");
46291.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
46301.77Skamil		    != -1);
46311.77Skamil
46321.1Skamil		/* Wait for tracee and assert that it exited */
46331.1Skamil		FORKEE_REQUIRE_SUCCESS(
46341.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
46351.1Skamil
46361.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
46371.1Skamil
46381.13Schristos		DPRINTF("Before exiting of the tracer process\n");
46391.1Skamil		_exit(exitval_tracer);
46401.1Skamil	}
46411.1Skamil
46421.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
46431.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
46441.1Skamil
46451.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
46461.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
46471.77Skamil
46481.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
46491.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
46501.1Skamil
46511.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
46521.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
46531.1Skamil
46541.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
46551.1Skamil	    TWAIT_FNAME);
46561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
46571.1Skamil	    tracer);
46581.1Skamil
46591.1Skamil	validate_status_exited(status, exitval_tracer);
46601.1Skamil
46611.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
46621.1Skamil	    TWAIT_FNAME);
46631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
46641.1Skamil	    tracee);
46651.1Skamil
46661.77Skamil	validate_status_signaled(status, SIGKILL, 0);
46671.1Skamil
46681.1Skamil	msg_close(&parent_tracer);
46691.1Skamil	msg_close(&parent_tracee);
46701.1Skamil}
46711.77Skamil
46721.77Skamil#define ATTACH_LWPINFO(test, threads)					\
46731.77SkamilATF_TC(test);								\
46741.77SkamilATF_TC_HEAD(test, tc)							\
46751.77Skamil{									\
46761.77Skamil	atf_tc_set_md_var(tc, "descr",					\
46771.77Skamil	    "Verify LWPINFO with the child with " #threads		\
46781.77Skamil	    " spawned extra threads (tracer is not the original "	\
46791.77Skamil	    "parent)");							\
46801.77Skamil}									\
46811.77Skamil									\
46821.77SkamilATF_TC_BODY(test, tc)							\
46831.77Skamil{									\
46841.77Skamil									\
46851.77Skamil	attach_lwpinfo(threads);					\
46861.77Skamil}
46871.77Skamil
46881.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
46891.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
46901.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
46911.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
46921.1Skamil#endif
46931.1Skamil
46941.77Skamil/// ----------------------------------------------------------------------------
46951.77Skamil
46961.1Skamilstatic void
46971.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
46981.1Skamil{
46991.1Skamil	const int exitval = 5;
47001.1Skamil	const int sigval = SIGINT;
47011.1Skamil	const int sigfaked = SIGTRAP;
47021.1Skamil	const int sicodefaked = TRAP_BRKPT;
47031.1Skamil	pid_t child, wpid;
47041.1Skamil	struct sigaction sa;
47051.1Skamil#if defined(TWAIT_HAVE_STATUS)
47061.1Skamil	int status;
47071.1Skamil#endif
47081.1Skamil	struct ptrace_siginfo info;
47091.1Skamil	memset(&info, 0, sizeof(info));
47101.1Skamil
47111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47131.1Skamil	if (child == 0) {
47141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47161.1Skamil
47171.79Skamil		sa.sa_sigaction = sah;
47181.1Skamil		sa.sa_flags = SA_SIGINFO;
47191.1Skamil		sigemptyset(&sa.sa_mask);
47201.1Skamil
47211.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
47221.79Skamil		    != -1);
47231.1Skamil
47241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47261.1Skamil
47271.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
47281.1Skamil
47291.13Schristos		DPRINTF("Before exiting of the child process\n");
47301.1Skamil		_exit(exitval);
47311.1Skamil	}
47321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47331.1Skamil
47341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47361.1Skamil
47371.1Skamil	validate_status_stopped(status, sigval);
47381.1Skamil
47391.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
47401.61Skre	SYSCALL_REQUIRE(
47411.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
47421.1Skamil
47431.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47441.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
47451.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47461.1Skamil	    info.psi_siginfo.si_errno);
47471.1Skamil
47481.79Skamil	if (faked) {
47491.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
47501.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
47511.79Skamil		info.psi_siginfo.si_signo = sigfaked;
47521.79Skamil		info.psi_siginfo.si_code = sicodefaked;
47531.79Skamil	}
47541.1Skamil
47551.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
47561.61Skre	SYSCALL_REQUIRE(
47571.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
47581.1Skamil
47591.79Skamil	if (faked) {
47601.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
47611.79Skamil		    "child\n");
47621.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
47631.79Skamil		    sizeof(info)) != -1);
47641.1Skamil
47651.79Skamil		DPRINTF("Before checking siginfo_t\n");
47661.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
47671.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
47681.79Skamil	}
47691.1Skamil
47701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47711.1Skamil	    "without signal to be sent\n");
47721.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
47731.79Skamil	    faked ? sigfaked : sigval) != -1);
47741.1Skamil
47751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47771.1Skamil
47781.1Skamil	validate_status_exited(status, exitval);
47791.1Skamil
47801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47821.1Skamil}
47831.1Skamil
47841.79Skamil#define PTRACE_SIGINFO(test, faked)					\
47851.79SkamilATF_TC(test);								\
47861.79SkamilATF_TC_HEAD(test, tc)							\
47871.79Skamil{									\
47881.79Skamil	atf_tc_set_md_var(tc, "descr",					\
47891.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
47901.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
47911.79Skamil}									\
47921.79Skamil									\
47931.79Skamilstatic int test##_caught = 0;						\
47941.79Skamil									\
47951.79Skamilstatic void								\
47961.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
47971.79Skamil{									\
47981.79Skamil	if (faked) {							\
47991.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
48001.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
48011.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
48021.79Skamil	} else {							\
48031.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
48041.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
48051.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
48061.79Skamil	}								\
48071.79Skamil									\
48081.79Skamil	++ test##_caught;						\
48091.79Skamil}									\
48101.79Skamil									\
48111.79SkamilATF_TC_BODY(test, tc)							\
48121.79Skamil{									\
48131.79Skamil									\
48141.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
48151.79Skamil}
48161.79Skamil
48171.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
48181.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
48191.79Skamil
48201.79Skamil/// ----------------------------------------------------------------------------
48211.79Skamil
48221.97Skamilstatic void
48231.97Skamiltraceme_exec(bool masked, bool ignored)
48241.1Skamil{
48251.1Skamil	const int sigval = SIGTRAP;
48261.1Skamil	pid_t child, wpid;
48271.1Skamil#if defined(TWAIT_HAVE_STATUS)
48281.1Skamil	int status;
48291.1Skamil#endif
48301.97Skamil	struct sigaction sa;
48311.97Skamil	struct ptrace_siginfo info;
48321.97Skamil	sigset_t intmask;
48331.97Skamil	struct kinfo_proc2 kp;
48341.97Skamil	size_t len = sizeof(kp);
48351.97Skamil
48361.97Skamil	int name[6];
48371.97Skamil	const size_t namelen = __arraycount(name);
48381.97Skamil	ki_sigset_t kp_sigmask;
48391.97Skamil	ki_sigset_t kp_sigignore;
48401.1Skamil
48411.1Skamil	memset(&info, 0, sizeof(info));
48421.1Skamil
48431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48451.1Skamil	if (child == 0) {
48461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48481.1Skamil
48491.97Skamil		if (masked) {
48501.97Skamil			sigemptyset(&intmask);
48511.97Skamil			sigaddset(&intmask, sigval);
48521.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
48531.97Skamil		}
48541.97Skamil
48551.97Skamil		if (ignored) {
48561.97Skamil			memset(&sa, 0, sizeof(sa));
48571.97Skamil			sa.sa_handler = SIG_IGN;
48581.97Skamil			sigemptyset(&sa.sa_mask);
48591.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
48601.97Skamil		}
48611.97Skamil
48621.13Schristos		DPRINTF("Before calling execve(2) from child\n");
48631.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
48641.1Skamil
48651.1Skamil		FORKEE_ASSERT(0 && "Not reached");
48661.1Skamil	}
48671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48681.1Skamil
48691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48711.1Skamil
48721.1Skamil	validate_status_stopped(status, sigval);
48731.1Skamil
48741.97Skamil	name[0] = CTL_KERN,
48751.97Skamil	name[1] = KERN_PROC2,
48761.97Skamil	name[2] = KERN_PROC_PID;
48771.97Skamil	name[3] = getpid();
48781.97Skamil	name[4] = sizeof(kp);
48791.97Skamil	name[5] = 1;
48801.97Skamil
48811.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
48821.97Skamil
48831.97Skamil	if (masked)
48841.97Skamil		kp_sigmask = kp.p_sigmask;
48851.97Skamil
48861.97Skamil	if (ignored)
48871.97Skamil		kp_sigignore = kp.p_sigignore;
48881.97Skamil
48891.97Skamil	name[3] = getpid();
48901.97Skamil
48911.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
48921.97Skamil
48931.97Skamil	if (masked) {
48941.97Skamil		DPRINTF("kp_sigmask="
48951.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
48961.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
48971.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
48981.97Skamil
48991.97Skamil		DPRINTF("kp.p_sigmask="
49001.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
49011.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
49021.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
49031.97Skamil
49041.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
49051.97Skamil		    sizeof(kp_sigmask)));
49061.97Skamil	}
49071.97Skamil
49081.97Skamil	if (ignored) {
49091.97Skamil		DPRINTF("kp_sigignore="
49101.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
49111.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
49121.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
49131.97Skamil
49141.97Skamil		DPRINTF("kp.p_sigignore="
49151.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
49161.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
49171.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
49181.97Skamil
49191.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
49201.97Skamil		    sizeof(kp_sigignore)));
49211.97Skamil	}
49221.97Skamil
49231.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49241.61Skre	SYSCALL_REQUIRE(
49251.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49261.1Skamil
49271.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49281.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49291.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49301.1Skamil	    info.psi_siginfo.si_errno);
49311.1Skamil
49321.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
49331.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
49341.1Skamil
49351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49361.1Skamil	    "without signal to be sent\n");
49371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49381.1Skamil
49391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49411.1Skamil
49421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49441.1Skamil}
49451.1Skamil
49461.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
49471.97SkamilATF_TC(test);								\
49481.97SkamilATF_TC_HEAD(test, tc)							\
49491.97Skamil{									\
49501.97Skamil       atf_tc_set_md_var(tc, "descr",					\
49511.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
49521.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
49531.97Skamil           masked ? " with ignored signal" : "");			\
49541.97Skamil}									\
49551.97Skamil									\
49561.97SkamilATF_TC_BODY(test, tc)							\
49571.97Skamil{									\
49581.97Skamil									\
49591.97Skamil       traceme_exec(masked, ignored);					\
49601.97Skamil}
49611.97Skamil
49621.97SkamilTRACEME_EXEC(traceme_exec, false, false)
49631.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
49641.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
49651.97Skamil
49661.82Skamil/// ----------------------------------------------------------------------------
49671.82Skamil
49681.83Skamilstatic volatile int done;
49691.1Skamil
49701.83Skamilstatic void *
49711.83Skamiltrace_threads_cb(void *arg __unused)
49721.1Skamil{
49731.1Skamil
49741.83Skamil	done++;
49751.83Skamil
49761.83Skamil	while (done < 3)
49771.83Skamil		continue;
49781.83Skamil
49791.83Skamil	return NULL;
49801.1Skamil}
49811.1Skamil
49821.83Skamilstatic void
49831.83Skamiltrace_threads(bool trace_create, bool trace_exit)
49841.1Skamil{
49851.1Skamil	const int sigval = SIGSTOP;
49861.1Skamil	pid_t child, wpid;
49871.1Skamil#if defined(TWAIT_HAVE_STATUS)
49881.1Skamil	int status;
49891.1Skamil#endif
49901.1Skamil	ptrace_state_t state;
49911.1Skamil	const int slen = sizeof(state);
49921.1Skamil	ptrace_event_t event;
49931.1Skamil	const int elen = sizeof(event);
49941.83Skamil	struct ptrace_siginfo info;
49951.83Skamil
49961.83Skamil	pthread_t t[3];
49971.83Skamil	int rv;
49981.83Skamil	size_t n;
49991.1Skamil	lwpid_t lid;
50001.83Skamil
50011.83Skamil	/* Track created and exited threads */
50021.83Skamil	bool traced_lwps[__arraycount(t)];
50031.83Skamil
50041.83Skamil	atf_tc_skip("PR kern/51995");
50051.1Skamil
50061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50081.1Skamil	if (child == 0) {
50091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50111.1Skamil
50121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50141.1Skamil
50151.83Skamil		for (n = 0; n < __arraycount(t); n++) {
50161.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
50171.83Skamil			    NULL);
50181.83Skamil			FORKEE_ASSERT(rv == 0);
50191.83Skamil		}
50201.1Skamil
50211.83Skamil		for (n = 0; n < __arraycount(t); n++) {
50221.83Skamil			rv = pthread_join(t[n], NULL);
50231.83Skamil			FORKEE_ASSERT(rv == 0);
50241.83Skamil		}
50251.1Skamil
50261.83Skamil		/*
50271.83Skamil		 * There is race between _exit() and pthread_join() detaching
50281.83Skamil		 * a thread. For simplicity kill the process after detecting
50291.83Skamil		 * LWP events.
50301.83Skamil		 */
50311.83Skamil		while (true)
50321.83Skamil			continue;
50331.1Skamil
50341.83Skamil		FORKEE_ASSERT(0 && "Not reached");
50351.1Skamil	}
50361.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50371.1Skamil
50381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50401.1Skamil
50411.1Skamil	validate_status_stopped(status, sigval);
50421.1Skamil
50431.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50441.83Skamil	SYSCALL_REQUIRE(
50451.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50461.1Skamil
50471.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50481.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
50491.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50501.83Skamil	    info.psi_siginfo.si_errno);
50511.1Skamil
50521.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
50531.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
50541.1Skamil
50551.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
50561.83Skamil	memset(&event, 0, sizeof(event));
50571.83Skamil	if (trace_create)
50581.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
50591.83Skamil	if (trace_exit)
50601.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
50611.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50621.1Skamil
50631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50641.1Skamil	    "without signal to be sent\n");
50651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50661.1Skamil
50671.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
50681.1Skamil
50691.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
50701.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
50711.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
50721.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
50731.83Skamil		    child);
50741.1Skamil
50751.83Skamil		validate_status_stopped(status, SIGTRAP);
50761.1Skamil
50771.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
50781.83Skamil		    "child\n");
50791.83Skamil		SYSCALL_REQUIRE(
50801.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50811.1Skamil
50821.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50831.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50841.83Skamil		    "si_errno=%#x\n",
50851.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50861.83Skamil		    info.psi_siginfo.si_errno);
50871.1Skamil
50881.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
50891.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
50901.1Skamil
50911.83Skamil		SYSCALL_REQUIRE(
50921.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50931.1Skamil
50941.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
50951.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
50961.1Skamil
50971.83Skamil		lid = state.pe_lwp;
50981.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
50991.1Skamil
51001.83Skamil		traced_lwps[lid - 1] = true;
51011.1Skamil
51021.83Skamil		DPRINTF("Before resuming the child process where it left off "
51031.83Skamil		    "and without signal to be sent\n");
51041.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51051.83Skamil	}
51061.1Skamil
51071.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
51081.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
51091.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
51101.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
51111.83Skamil		    child);
51121.1Skamil
51131.83Skamil		validate_status_stopped(status, SIGTRAP);
51141.1Skamil
51151.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
51161.83Skamil		    "child\n");
51171.83Skamil		SYSCALL_REQUIRE(
51181.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51191.1Skamil
51201.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
51211.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
51221.83Skamil		    "si_errno=%#x\n",
51231.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
51241.83Skamil		    info.psi_siginfo.si_errno);
51251.1Skamil
51261.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51271.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
51281.1Skamil
51291.83Skamil		SYSCALL_REQUIRE(
51301.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51311.1Skamil
51321.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
51331.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
51341.1Skamil
51351.83Skamil		lid = state.pe_lwp;
51361.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
51371.1Skamil
51381.83Skamil		if (trace_create) {
51391.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
51401.83Skamil			traced_lwps[lid - 1] = false;
51411.83Skamil		}
51421.1Skamil
51431.83Skamil		DPRINTF("Before resuming the child process where it left off "
51441.83Skamil		    "and without signal to be sent\n");
51451.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51461.83Skamil	}
51471.1Skamil
51481.83Skamil	kill(child, SIGKILL);
51491.1Skamil
51501.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51511.1Skamil	    TWAIT_FNAME);
51521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51531.1Skamil
51541.83Skamil	validate_status_signaled(status, SIGKILL, 0);
51551.1Skamil
51561.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51571.1Skamil	    TWAIT_FNAME);
51581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51591.1Skamil}
51601.1Skamil
51611.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
51621.83SkamilATF_TC(test);								\
51631.83SkamilATF_TC_HEAD(test, tc)							\
51641.83Skamil{									\
51651.83Skamil        atf_tc_set_md_var(tc, "descr",					\
51661.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
51671.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
51681.83Skamil	    trace_exit ? "" : "out");					\
51691.83Skamil}									\
51701.83Skamil									\
51711.83SkamilATF_TC_BODY(test, tc)							\
51721.83Skamil{									\
51731.83Skamil									\
51741.83Skamil        trace_threads(trace_create, trace_exit);			\
51751.83Skamil}
51761.83Skamil
51771.83SkamilTRACE_THREADS(trace_thread1, false, false)
51781.83SkamilTRACE_THREADS(trace_thread2, false, true)
51791.83SkamilTRACE_THREADS(trace_thread3, true, false)
51801.83SkamilTRACE_THREADS(trace_thread4, true, true)
51811.83Skamil
51821.83Skamil/// ----------------------------------------------------------------------------
51831.83Skamil
51841.84SkamilATF_TC(signal_mask_unrelated);
51851.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
51861.1Skamil{
51871.1Skamil	atf_tc_set_md_var(tc, "descr",
51881.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
51891.1Skamil	    "from catching other signals");
51901.1Skamil}
51911.1Skamil
51921.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
51931.1Skamil{
51941.1Skamil	const int exitval = 5;
51951.1Skamil	const int sigval = SIGSTOP;
51961.1Skamil	const int sigmasked = SIGTRAP;
51971.1Skamil	const int signotmasked = SIGINT;
51981.1Skamil	pid_t child, wpid;
51991.1Skamil#if defined(TWAIT_HAVE_STATUS)
52001.1Skamil	int status;
52011.1Skamil#endif
52021.1Skamil	sigset_t intmask;
52031.1Skamil
52041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52061.1Skamil	if (child == 0) {
52071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52091.1Skamil
52101.1Skamil		sigemptyset(&intmask);
52111.1Skamil		sigaddset(&intmask, sigmasked);
52121.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
52131.1Skamil
52141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52161.1Skamil
52171.13Schristos		DPRINTF("Before raising %s from child\n",
52181.1Skamil		    strsignal(signotmasked));
52191.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
52201.1Skamil
52211.13Schristos		DPRINTF("Before exiting of the child process\n");
52221.1Skamil		_exit(exitval);
52231.1Skamil	}
52241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52251.1Skamil
52261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52281.1Skamil
52291.1Skamil	validate_status_stopped(status, sigval);
52301.1Skamil
52311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52321.1Skamil	    "without signal to be sent\n");
52331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52341.1Skamil
52351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52371.1Skamil
52381.1Skamil	validate_status_stopped(status, signotmasked);
52391.1Skamil
52401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52411.1Skamil	    "without signal to be sent\n");
52421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52431.1Skamil
52441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52461.1Skamil
52471.1Skamil	validate_status_exited(status, exitval);
52481.1Skamil
52491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52511.1Skamil}
52521.1Skamil
52531.84Skamil/// ----------------------------------------------------------------------------
52541.84Skamil
52551.1Skamil#if defined(TWAIT_HAVE_PID)
52561.99Skamilstatic void
52571.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked,
52581.99Skamil           bool ignored)
52591.1Skamil{
52601.1Skamil	const int exitval = 5;
52611.1Skamil	const int exitval2 = 15;
52621.1Skamil	const int sigval = SIGSTOP;
52631.99Skamil	pid_t child, child2 = 0, wpid;
52641.1Skamil#if defined(TWAIT_HAVE_STATUS)
52651.1Skamil	int status;
52661.1Skamil#endif
52671.1Skamil	ptrace_state_t state;
52681.1Skamil	const int slen = sizeof(state);
52691.1Skamil	ptrace_event_t event;
52701.1Skamil	const int elen = sizeof(event);
52711.99Skamil	pid_t (*fn)(void);
52721.99Skamil	struct sigaction sa;
52731.99Skamil	struct ptrace_siginfo info;
52741.99Skamil	sigset_t intmask;
52751.99Skamil	struct kinfo_proc2 kp;
52761.99Skamil	size_t len = sizeof(kp);
52771.99Skamil
52781.99Skamil	int name[6];
52791.99Skamil	const size_t namelen = __arraycount(name);
52801.99Skamil	ki_sigset_t kp_sigmask;
52811.99Skamil	ki_sigset_t kp_sigignore;
52821.1Skamil
52831.99Skamil	if (trackfork)
52841.99Skamil		fn = fork;
52851.99Skamil	if (trackvfork || trackvforkdone)
52861.99Skamil		fn = vfork;
52871.14Schristos
52881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52901.1Skamil	if (child == 0) {
52911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52931.1Skamil
52941.99Skamil		if (masked) {
52951.99Skamil			sigemptyset(&intmask);
52961.99Skamil			sigaddset(&intmask, SIGTRAP);
52971.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
52981.99Skamil		}
52991.99Skamil
53001.99Skamil		if (ignored) {
53011.99Skamil			memset(&sa, 0, sizeof(sa));
53021.99Skamil			sa.sa_handler = SIG_IGN;
53031.99Skamil			sigemptyset(&sa.sa_mask);
53041.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
53051.99Skamil		}
53061.1Skamil
53071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53091.1Skamil
53101.99Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
53111.1Skamil
53121.1Skamil		if (child2 == 0)
53131.1Skamil			_exit(exitval2);
53141.1Skamil
53151.1Skamil		FORKEE_REQUIRE_SUCCESS
53161.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
53171.1Skamil
53181.1Skamil		forkee_status_exited(status, exitval2);
53191.1Skamil
53201.13Schristos		DPRINTF("Before exiting of the child process\n");
53211.1Skamil		_exit(exitval);
53221.1Skamil	}
53231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53241.1Skamil
53251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53271.1Skamil
53281.1Skamil	validate_status_stopped(status, sigval);
53291.1Skamil
53301.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53311.99Skamil	SYSCALL_REQUIRE(
53321.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53331.99Skamil
53341.99Skamil	DPRINTF("Before checking siginfo_t\n");
53351.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
53361.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
53371.1Skamil
53381.99Skamil	name[0] = CTL_KERN,
53391.99Skamil	name[1] = KERN_PROC2,
53401.99Skamil	name[2] = KERN_PROC_PID;
53411.99Skamil	name[3] = child;
53421.99Skamil	name[4] = sizeof(kp);
53431.99Skamil	name[5] = 1;
53441.1Skamil
53451.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53461.1Skamil
53471.99Skamil	if (masked)
53481.99Skamil		kp_sigmask = kp.p_sigmask;
53491.1Skamil
53501.99Skamil	if (ignored)
53511.99Skamil		kp_sigignore = kp.p_sigignore;
53521.1Skamil
53531.99Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
53541.99Skamil	    trackfork ? "|PTRACE_FORK" : "",
53551.99Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
53561.99Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
53571.99Skamil	event.pe_set_event = 0;
53581.99Skamil	if (trackfork)
53591.99Skamil		event.pe_set_event |= PTRACE_FORK;
53601.99Skamil	if (trackvfork)
53611.99Skamil		event.pe_set_event |= PTRACE_VFORK;
53621.99Skamil	if (trackvforkdone)
53631.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
53641.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
53651.1Skamil
53661.99Skamil	DPRINTF("Before resuming the child process where it left off and "
53671.99Skamil	    "without signal to be sent\n");
53681.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53691.1Skamil
53701.99Skamil	if (trackfork || trackvfork) {
53711.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
53721.99Skamil		    child);
53731.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
53741.99Skamil		    child);
53751.1Skamil
53761.99Skamil		validate_status_stopped(status, SIGTRAP);
53771.1Skamil
53781.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53791.1Skamil
53801.99Skamil		if (masked) {
53811.99Skamil			DPRINTF("kp_sigmask="
53821.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53831.99Skamil			    PRIx32 "\n",
53841.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
53851.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
53861.1Skamil
53871.99Skamil			DPRINTF("kp.p_sigmask="
53881.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53891.99Skamil			    PRIx32 "\n",
53901.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
53911.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
53921.1Skamil
53931.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
53941.99Skamil			    sizeof(kp_sigmask)));
53951.99Skamil		}
53961.1Skamil
53971.99Skamil		if (ignored) {
53981.99Skamil			DPRINTF("kp_sigignore="
53991.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54001.99Skamil			    PRIx32 "\n",
54011.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
54021.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
54031.1Skamil
54041.99Skamil			DPRINTF("kp.p_sigignore="
54051.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54061.99Skamil			    PRIx32 "\n",
54071.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
54081.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
54091.1Skamil
54101.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
54111.99Skamil			    sizeof(kp_sigignore)));
54121.99Skamil		}
54131.1Skamil
54141.99Skamil		SYSCALL_REQUIRE(
54151.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54161.99Skamil		if (trackfork) {
54171.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
54181.99Skamil			       PTRACE_FORK);
54191.99Skamil		}
54201.99Skamil		if (trackvfork) {
54211.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
54221.99Skamil			       PTRACE_VFORK);
54231.99Skamil		}
54241.1Skamil
54251.99Skamil		child2 = state.pe_other_pid;
54261.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
54271.1Skamil
54281.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
54291.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
54301.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
54311.99Skamil		    child2);
54321.1Skamil
54331.99Skamil		validate_status_stopped(status, SIGTRAP);
54341.1Skamil
54351.99Skamil		name[3] = child2;
54361.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
54371.1Skamil
54381.99Skamil		if (masked) {
54391.99Skamil			DPRINTF("kp_sigmask="
54401.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54411.99Skamil			    PRIx32 "\n",
54421.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
54431.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
54441.1Skamil
54451.99Skamil			DPRINTF("kp.p_sigmask="
54461.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54471.99Skamil			    PRIx32 "\n",
54481.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
54491.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
54501.14Schristos
54511.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
54521.99Skamil			    sizeof(kp_sigmask)));
54531.99Skamil		}
54541.1Skamil
54551.99Skamil		if (ignored) {
54561.99Skamil			DPRINTF("kp_sigignore="
54571.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54581.99Skamil			    PRIx32 "\n",
54591.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
54601.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
54611.1Skamil
54621.99Skamil			DPRINTF("kp.p_sigignore="
54631.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54641.99Skamil			    PRIx32 "\n",
54651.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
54661.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
54671.1Skamil
54681.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
54691.99Skamil			    sizeof(kp_sigignore)));
54701.99Skamil		}
54711.1Skamil
54721.99Skamil		SYSCALL_REQUIRE(
54731.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
54741.99Skamil		if (trackfork) {
54751.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
54761.99Skamil			       PTRACE_FORK);
54771.99Skamil		}
54781.99Skamil		if (trackvfork) {
54791.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
54801.99Skamil			       PTRACE_VFORK);
54811.99Skamil		}
54821.1Skamil
54831.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
54841.1Skamil
54851.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
54861.99Skamil		    "and without signal to be sent\n");
54871.99Skamil		SYSCALL_REQUIRE(
54881.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
54891.1Skamil
54901.99Skamil		DPRINTF("Before resuming the child process where it left off "
54911.99Skamil		    "and without signal to be sent\n");
54921.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54931.1Skamil	}
54941.1Skamil
54951.99Skamil	if (trackvforkdone) {
54961.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
54971.99Skamil		    child);
54981.99Skamil		TWAIT_REQUIRE_SUCCESS(
54991.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
55001.1Skamil
55011.99Skamil		validate_status_stopped(status, SIGTRAP);
55021.1Skamil
55031.99Skamil		name[3] = child;
55041.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
55051.1Skamil
55061.102Skamil		/*
55071.102Skamil		 * SIGCHLD is now pending in the signal queue and
55081.102Skamil		 * the kernel presents it to userland as a masked signal.
55091.102Skamil		 */
55101.102Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
55111.102Skamil
55121.99Skamil		if (masked) {
55131.99Skamil			DPRINTF("kp_sigmask="
55141.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55151.99Skamil			    PRIx32 "\n",
55161.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
55171.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
55181.1Skamil
55191.99Skamil			DPRINTF("kp.p_sigmask="
55201.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55211.99Skamil			    PRIx32 "\n",
55221.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
55231.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
55241.1Skamil
55251.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
55261.99Skamil			    sizeof(kp_sigmask)));
55271.99Skamil		}
55281.1Skamil
55291.99Skamil		if (ignored) {
55301.99Skamil			DPRINTF("kp_sigignore="
55311.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55321.99Skamil			    PRIx32 "\n",
55331.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
55341.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
55351.1Skamil
55361.99Skamil			DPRINTF("kp.p_sigignore="
55371.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55381.99Skamil			    PRIx32 "\n",
55391.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
55401.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
55411.1Skamil
55421.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
55431.99Skamil			    sizeof(kp_sigignore)));
55441.99Skamil		}
55451.1Skamil
55461.99Skamil		SYSCALL_REQUIRE(
55471.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55481.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
55491.1Skamil
55501.99Skamil		child2 = state.pe_other_pid;
55511.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
55521.99Skamil		    child2);
55531.1Skamil
55541.99Skamil		DPRINTF("Before resuming the child process where it left off "
55551.99Skamil		    "and without signal to be sent\n");
55561.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55571.99Skamil	}
55581.1Skamil
55591.99Skamil	if (trackfork || trackvfork) {
55601.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
55611.99Skamil		    "\n", TWAIT_FNAME);
55621.99Skamil		TWAIT_REQUIRE_SUCCESS(
55631.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
55641.1Skamil
55651.99Skamil		validate_status_exited(status, exitval2);
55661.1Skamil
55671.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
55681.99Skamil		    "process\n", TWAIT_FNAME);
55691.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
55701.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
55711.99Skamil	}
55721.1Skamil
55731.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
55741.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
55751.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55761.1Skamil
55771.1Skamil	validate_status_stopped(status, SIGCHLD);
55781.1Skamil
55791.57Skamil	DPRINTF("Before resuming the child process where it left off and "
55801.1Skamil	    "without signal to be sent\n");
55811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55821.1Skamil
55831.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55841.1Skamil	    TWAIT_FNAME);
55851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55861.1Skamil
55871.1Skamil	validate_status_exited(status, exitval);
55881.1Skamil
55891.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55901.57Skamil	    TWAIT_FNAME);
55911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55921.1Skamil}
55931.1Skamil
55941.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone,		\
55951.99Skamil                   masked,ignored)					\
55961.99SkamilATF_TC(name);								\
55971.99SkamilATF_TC_HEAD(name, tc)							\
55981.99Skamil{									\
55991.99Skamil	atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught "	\
56001.99Skamil	    "regardless of signal %s%s", 				\
56011.99Skamil	    trackfork ? "PTRACE_FORK" : "",				\
56021.99Skamil	    trackvfork ? "PTRACE_VFORK" : "",				\
56031.99Skamil	    trackvforkdone ? "PTRACE_VFORK_DONE" : "",			\
56041.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
56051.99Skamil}									\
56061.99Skamil									\
56071.99SkamilATF_TC_BODY(name, tc)							\
56081.99Skamil{									\
56091.99Skamil									\
56101.99Skamil	fork2_body(trackfork, trackvfork, trackvforkdone, masked,	\
56111.99Skamil	           ignored);						\
56121.1Skamil}
56131.1Skamil
56141.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false)
56151.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true)
56161.110Skamil#if TEST_VFORK_ENABLED
56171.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false)
56181.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true)
56191.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false)
56201.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true)
56211.1Skamil#endif
56221.110Skamil#endif
56231.1Skamil
56241.99Skamil/// ----------------------------------------------------------------------------
56251.1Skamil
56261.83Skamilvolatile lwpid_t the_lwp_id = 0;
56271.83Skamil
56281.83Skamilstatic void
56291.83Skamillwp_main_func(void *arg)
56301.83Skamil{
56311.83Skamil	the_lwp_id = _lwp_self();
56321.83Skamil	_lwp_exit();
56331.83Skamil}
56341.83Skamil
56351.1SkamilATF_TC(signal9);
56361.1SkamilATF_TC_HEAD(signal9, tc)
56371.1Skamil{
56381.1Skamil	atf_tc_set_md_var(tc, "descr",
56391.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
56401.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
56411.1Skamil}
56421.1Skamil
56431.1SkamilATF_TC_BODY(signal9, tc)
56441.1Skamil{
56451.1Skamil	const int exitval = 5;
56461.1Skamil	const int sigval = SIGSTOP;
56471.1Skamil	const int sigmasked = SIGTRAP;
56481.1Skamil	pid_t child, wpid;
56491.1Skamil#if defined(TWAIT_HAVE_STATUS)
56501.1Skamil	int status;
56511.1Skamil#endif
56521.1Skamil	sigset_t intmask;
56531.1Skamil	ptrace_state_t state;
56541.1Skamil	const int slen = sizeof(state);
56551.1Skamil	ptrace_event_t event;
56561.1Skamil	const int elen = sizeof(event);
56571.1Skamil	ucontext_t uc;
56581.1Skamil	lwpid_t lid;
56591.1Skamil	static const size_t ssize = 16*1024;
56601.1Skamil	void *stack;
56611.1Skamil
56621.14Schristos	atf_tc_expect_fail("PR kern/51918");
56631.14Schristos
56641.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56651.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56661.1Skamil	if (child == 0) {
56671.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56681.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56691.1Skamil
56701.1Skamil		sigemptyset(&intmask);
56711.1Skamil		sigaddset(&intmask, sigmasked);
56721.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56731.1Skamil
56741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56761.1Skamil
56771.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
56781.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
56791.1Skamil
56801.13Schristos		DPRINTF("Before making context for new lwp in child\n");
56811.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
56821.1Skamil
56831.13Schristos		DPRINTF("Before creating new in child\n");
56841.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
56851.1Skamil
56861.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
56871.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
56881.1Skamil
56891.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
56901.1Skamil		    "are the same\n", lid, the_lwp_id);
56911.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
56921.1Skamil
56931.13Schristos		DPRINTF("Before exiting of the child process\n");
56941.1Skamil		_exit(exitval);
56951.1Skamil	}
56961.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56971.1Skamil
56981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57001.1Skamil
57011.1Skamil	validate_status_stopped(status, sigval);
57021.1Skamil
57031.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
57041.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
57051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
57061.1Skamil
57071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57081.1Skamil	    "without signal to be sent\n");
57091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57101.1Skamil
57111.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
57121.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
57131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57141.1Skamil
57151.1Skamil	validate_status_stopped(status, sigmasked);
57161.1Skamil
57171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
57181.1Skamil
57191.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
57201.1Skamil
57211.1Skamil	lid = state.pe_lwp;
57221.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
57231.1Skamil
57241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57251.1Skamil	    "without signal to be sent\n");
57261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57271.1Skamil
57281.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
57291.1Skamil	    TWAIT_FNAME);
57301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57311.1Skamil
57321.1Skamil	validate_status_exited(status, exitval);
57331.1Skamil
57341.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
57351.1Skamil	    TWAIT_FNAME);
57361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57371.1Skamil}
57381.1Skamil
57391.1SkamilATF_TC(signal10);
57401.1SkamilATF_TC_HEAD(signal10, tc)
57411.1Skamil{
57421.1Skamil	atf_tc_set_md_var(tc, "descr",
57431.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57441.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
57451.1Skamil}
57461.1Skamil
57471.1SkamilATF_TC_BODY(signal10, tc)
57481.1Skamil{
57491.1Skamil	const int exitval = 5;
57501.1Skamil	const int sigval = SIGSTOP;
57511.1Skamil	const int sigmasked = SIGTRAP;
57521.1Skamil	pid_t child, wpid;
57531.1Skamil#if defined(TWAIT_HAVE_STATUS)
57541.1Skamil	int status;
57551.1Skamil#endif
57561.1Skamil	sigset_t intmask;
57571.1Skamil	ptrace_state_t state;
57581.1Skamil	const int slen = sizeof(state);
57591.1Skamil	ptrace_event_t event;
57601.1Skamil	const int elen = sizeof(event);
57611.1Skamil	ucontext_t uc;
57621.1Skamil	lwpid_t lid;
57631.1Skamil	static const size_t ssize = 16*1024;
57641.1Skamil	void *stack;
57651.1Skamil
57661.14Schristos	atf_tc_expect_fail("PR kern/51918");
57671.14Schristos
57681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57701.1Skamil	if (child == 0) {
57711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57731.1Skamil
57741.1Skamil		sigemptyset(&intmask);
57751.1Skamil		sigaddset(&intmask, sigmasked);
57761.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57771.1Skamil
57781.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57791.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57801.1Skamil
57811.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
57821.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
57831.1Skamil
57841.13Schristos		DPRINTF("Before making context for new lwp in child\n");
57851.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
57861.1Skamil
57871.13Schristos		DPRINTF("Before creating new in child\n");
57881.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
57891.1Skamil
57901.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
57911.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
57921.1Skamil
57931.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
57941.1Skamil		    "are the same\n", lid, the_lwp_id);
57951.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
57961.1Skamil
57971.13Schristos		DPRINTF("Before exiting of the child process\n");
57981.1Skamil		_exit(exitval);
57991.1Skamil	}
58001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58011.1Skamil
58021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58041.1Skamil
58051.1Skamil	validate_status_stopped(status, sigval);
58061.1Skamil
58071.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
58081.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
58091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
58101.1Skamil
58111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58121.1Skamil	    "without signal to be sent\n");
58131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58141.1Skamil
58151.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
58161.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
58171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58181.1Skamil
58191.1Skamil	validate_status_stopped(status, sigmasked);
58201.1Skamil
58211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
58221.1Skamil
58231.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
58241.1Skamil
58251.1Skamil	lid = state.pe_lwp;
58261.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
58271.1Skamil
58281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58291.1Skamil	    "without signal to be sent\n");
58301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58311.1Skamil
58321.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
58331.1Skamil	    TWAIT_FNAME);
58341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58351.1Skamil
58361.1Skamil	validate_status_exited(status, exitval);
58371.1Skamil
58381.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
58391.1Skamil	    TWAIT_FNAME);
58401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58411.1Skamil}
58421.1Skamil
58431.1Skamilstatic void
58441.1Skamillwp_main_stop(void *arg)
58451.1Skamil{
58461.1Skamil	the_lwp_id = _lwp_self();
58471.1Skamil
58481.1Skamil	raise(SIGTRAP);
58491.1Skamil
58501.1Skamil	_lwp_exit();
58511.1Skamil}
58521.1Skamil
58531.1SkamilATF_TC(suspend1);
58541.1SkamilATF_TC_HEAD(suspend1, tc)
58551.1Skamil{
58561.1Skamil	atf_tc_set_md_var(tc, "descr",
58571.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
58581.1Skamil	    "resumed by a tracee");
58591.1Skamil}
58601.1Skamil
58611.1SkamilATF_TC_BODY(suspend1, tc)
58621.1Skamil{
58631.1Skamil	const int exitval = 5;
58641.1Skamil	const int sigval = SIGSTOP;
58651.1Skamil	pid_t child, wpid;
58661.1Skamil#if defined(TWAIT_HAVE_STATUS)
58671.1Skamil	int status;
58681.1Skamil#endif
58691.1Skamil	ucontext_t uc;
58701.1Skamil	lwpid_t lid;
58711.1Skamil	static const size_t ssize = 16*1024;
58721.1Skamil	void *stack;
58731.1Skamil	struct ptrace_lwpinfo pl;
58741.1Skamil	struct ptrace_siginfo psi;
58751.1Skamil	volatile int go = 0;
58761.1Skamil
58771.17Skamil	// Feature pending for refactoring
58781.17Skamil	atf_tc_expect_fail("PR kern/51995");
58791.17Skamil
58801.16Skamil	// Hangs with qemu
58811.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
58821.16Skamil
58831.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58841.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58851.1Skamil	if (child == 0) {
58861.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58871.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58881.1Skamil
58891.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58901.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58911.1Skamil
58921.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
58931.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
58941.1Skamil
58951.13Schristos		DPRINTF("Before making context for new lwp in child\n");
58961.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
58971.1Skamil
58981.13Schristos		DPRINTF("Before creating new in child\n");
58991.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
59001.1Skamil
59011.1Skamil		while (go == 0)
59021.1Skamil			continue;
59031.1Skamil
59041.1Skamil		raise(SIGINT);
59051.1Skamil
59061.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
59071.1Skamil
59081.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
59091.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
59101.1Skamil
59111.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
59121.1Skamil		    "are the same\n", lid, the_lwp_id);
59131.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
59141.1Skamil
59151.13Schristos		DPRINTF("Before exiting of the child process\n");
59161.1Skamil		_exit(exitval);
59171.1Skamil	}
59181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59191.1Skamil
59201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59221.1Skamil
59231.1Skamil	validate_status_stopped(status, sigval);
59241.1Skamil
59251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59261.1Skamil	    "without signal to be sent\n");
59271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59281.1Skamil
59291.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59301.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
59311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59321.1Skamil
59331.1Skamil	validate_status_stopped(status, SIGTRAP);
59341.1Skamil
59351.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
59361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
59371.1Skamil
59381.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
59391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
59401.1Skamil
59411.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
59421.1Skamil	    child, getpid());
59431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
59441.1Skamil
59451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59461.1Skamil	    "without signal to be sent\n");
59471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59481.1Skamil
59491.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59501.1Skamil	    "SIGINT\n", TWAIT_FNAME);
59511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59521.1Skamil
59531.1Skamil	validate_status_stopped(status, SIGINT);
59541.1Skamil
59551.1Skamil	pl.pl_lwpid = 0;
59561.1Skamil
59571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
59581.1Skamil	while (pl.pl_lwpid != 0) {
59591.1Skamil
59601.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
59611.1Skamil		switch (pl.pl_lwpid) {
59621.1Skamil		case 1:
59631.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
59641.1Skamil			break;
59651.1Skamil		case 2:
59661.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
59671.1Skamil			break;
59681.1Skamil		}
59691.1Skamil	}
59701.1Skamil
59711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59721.1Skamil	    "without signal to be sent\n");
59731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59741.1Skamil
59751.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59761.1Skamil	    TWAIT_FNAME);
59771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59781.1Skamil
59791.1Skamil	validate_status_exited(status, exitval);
59801.1Skamil
59811.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59821.1Skamil	    TWAIT_FNAME);
59831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59841.1Skamil}
59851.1Skamil
59861.1SkamilATF_TC(suspend2);
59871.1SkamilATF_TC_HEAD(suspend2, tc)
59881.1Skamil{
59891.1Skamil	atf_tc_set_md_var(tc, "descr",
59901.1Skamil	    "Verify that the while the only thread within a process is "
59911.1Skamil	    "suspended, the whole process cannot be unstopped");
59921.1Skamil}
59931.1Skamil
59941.1SkamilATF_TC_BODY(suspend2, tc)
59951.1Skamil{
59961.1Skamil	const int exitval = 5;
59971.1Skamil	const int sigval = SIGSTOP;
59981.1Skamil	pid_t child, wpid;
59991.1Skamil#if defined(TWAIT_HAVE_STATUS)
60001.1Skamil	int status;
60011.1Skamil#endif
60021.1Skamil	struct ptrace_siginfo psi;
60031.1Skamil
60041.17Skamil	// Feature pending for refactoring
60051.17Skamil	atf_tc_expect_fail("PR kern/51995");
60061.17Skamil
60071.16Skamil	// Hangs with qemu
60081.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
60091.16Skamil
60101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60121.1Skamil	if (child == 0) {
60131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60151.1Skamil
60161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60181.1Skamil
60191.13Schristos		DPRINTF("Before exiting of the child process\n");
60201.1Skamil		_exit(exitval);
60211.1Skamil	}
60221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60231.1Skamil
60241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60261.1Skamil
60271.1Skamil	validate_status_stopped(status, sigval);
60281.1Skamil
60291.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
60301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
60311.1Skamil
60321.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
60331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
60341.1Skamil
60351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60361.1Skamil	    "without signal to be sent\n");
60371.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
60381.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
60391.1Skamil
60401.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
60411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
60421.1Skamil
60431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60441.1Skamil	    "without signal to be sent\n");
60451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60461.1Skamil
60471.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60481.1Skamil	    TWAIT_FNAME);
60491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60501.1Skamil
60511.1Skamil	validate_status_exited(status, exitval);
60521.1Skamil
60531.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60541.1Skamil	    TWAIT_FNAME);
60551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60561.1Skamil}
60571.1Skamil
60581.1SkamilATF_TC(resume1);
60591.1SkamilATF_TC_HEAD(resume1, tc)
60601.1Skamil{
60611.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
60621.1Skamil	atf_tc_set_md_var(tc, "descr",
60631.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
60641.1Skamil	    "resumed by the debugger");
60651.1Skamil}
60661.1Skamil
60671.1SkamilATF_TC_BODY(resume1, tc)
60681.1Skamil{
60691.1Skamil	struct msg_fds fds;
60701.1Skamil	const int exitval = 5;
60711.1Skamil	const int sigval = SIGSTOP;
60721.1Skamil	pid_t child, wpid;
60731.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
60741.1Skamil#if defined(TWAIT_HAVE_STATUS)
60751.1Skamil	int status;
60761.1Skamil#endif
60771.1Skamil	ucontext_t uc;
60781.1Skamil	lwpid_t lid;
60791.1Skamil	static const size_t ssize = 16*1024;
60801.1Skamil	void *stack;
60811.1Skamil	struct ptrace_lwpinfo pl;
60821.1Skamil	struct ptrace_siginfo psi;
60831.1Skamil
60841.17Skamil	// Feature pending for refactoring
60851.17Skamil	atf_tc_expect_fail("PR kern/51995");
60861.17Skamil
60871.15Schristos	// Hangs with qemu
60881.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
60891.1Skamil
60901.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
60911.1Skamil
60921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60941.1Skamil	if (child == 0) {
60951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60971.1Skamil
60981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61001.1Skamil
61011.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
61021.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
61031.1Skamil
61041.13Schristos		DPRINTF("Before making context for new lwp in child\n");
61051.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
61061.1Skamil
61071.13Schristos		DPRINTF("Before creating new in child\n");
61081.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
61091.1Skamil
61101.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
61111.1Skamil
61121.1Skamil		raise(SIGINT);
61131.1Skamil
61141.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
61151.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
61161.1Skamil
61171.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
61181.1Skamil		    "are the same\n", lid, the_lwp_id);
61191.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
61201.1Skamil
61211.13Schristos		DPRINTF("Before exiting of the child process\n");
61221.1Skamil		_exit(exitval);
61231.1Skamil	}
61241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61251.1Skamil
61261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61281.1Skamil
61291.1Skamil	validate_status_stopped(status, sigval);
61301.1Skamil
61311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61321.1Skamil	    "without signal to be sent\n");
61331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61341.1Skamil
61351.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61361.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
61371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61381.1Skamil
61391.1Skamil	validate_status_stopped(status, SIGTRAP);
61401.1Skamil
61411.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
61421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
61431.1Skamil
61441.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
61451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
61461.1Skamil
61471.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
61481.1Skamil
61491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61501.1Skamil	    "without signal to be sent\n");
61511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61521.1Skamil
61531.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61541.1Skamil	    "SIGINT\n", TWAIT_FNAME);
61551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61561.1Skamil
61571.1Skamil	validate_status_stopped(status, SIGINT);
61581.1Skamil
61591.1Skamil	pl.pl_lwpid = 0;
61601.1Skamil
61611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
61621.1Skamil	while (pl.pl_lwpid != 0) {
61631.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
61641.1Skamil		switch (pl.pl_lwpid) {
61651.1Skamil		case 1:
61661.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
61671.1Skamil			break;
61681.1Skamil		case 2:
61691.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
61701.1Skamil			break;
61711.1Skamil		}
61721.1Skamil	}
61731.1Skamil
61741.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
61751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
61761.1Skamil
61771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61781.1Skamil	    "without signal to be sent\n");
61791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61801.1Skamil
61811.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61821.1Skamil	    TWAIT_FNAME);
61831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61841.1Skamil
61851.1Skamil	validate_status_exited(status, exitval);
61861.1Skamil
61871.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61881.1Skamil	    TWAIT_FNAME);
61891.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61901.1Skamil
61911.1Skamil	msg_close(&fds);
61921.1Skamil
61931.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
61941.1Skamil	sleep(10);
61951.1Skamil}
61961.1Skamil
61971.1SkamilATF_TC(syscall1);
61981.1SkamilATF_TC_HEAD(syscall1, tc)
61991.1Skamil{
62001.1Skamil	atf_tc_set_md_var(tc, "descr",
62011.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
62021.1Skamil}
62031.1Skamil
62041.1SkamilATF_TC_BODY(syscall1, tc)
62051.1Skamil{
62061.1Skamil	const int exitval = 5;
62071.1Skamil	const int sigval = SIGSTOP;
62081.1Skamil	pid_t child, wpid;
62091.1Skamil#if defined(TWAIT_HAVE_STATUS)
62101.1Skamil	int status;
62111.1Skamil#endif
62121.1Skamil	struct ptrace_siginfo info;
62131.1Skamil	memset(&info, 0, sizeof(info));
62141.1Skamil
62151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62171.1Skamil	if (child == 0) {
62181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62201.1Skamil
62211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62231.1Skamil
62241.1Skamil		syscall(SYS_getpid);
62251.1Skamil
62261.13Schristos		DPRINTF("Before exiting of the child process\n");
62271.1Skamil		_exit(exitval);
62281.1Skamil	}
62291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62301.1Skamil
62311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62331.1Skamil
62341.1Skamil	validate_status_stopped(status, sigval);
62351.1Skamil
62361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62371.1Skamil	    "without signal to be sent\n");
62381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
62391.1Skamil
62401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62421.1Skamil
62431.1Skamil	validate_status_stopped(status, SIGTRAP);
62441.1Skamil
62451.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
62461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
62471.1Skamil
62481.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
62491.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
62501.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
62511.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
62521.1Skamil
62531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62541.1Skamil	    "without signal to be sent\n");
62551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
62561.1Skamil
62571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62591.1Skamil
62601.1Skamil	validate_status_stopped(status, SIGTRAP);
62611.1Skamil
62621.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
62631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
62641.1Skamil
62651.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
62661.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
62671.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
62681.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
62691.1Skamil
62701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62711.1Skamil	    "without signal to be sent\n");
62721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62731.1Skamil
62741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62761.1Skamil
62771.1Skamil	validate_status_exited(status, exitval);
62781.1Skamil
62791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62811.1Skamil}
62821.1Skamil
62831.1SkamilATF_TC(syscallemu1);
62841.1SkamilATF_TC_HEAD(syscallemu1, tc)
62851.1Skamil{
62861.1Skamil	atf_tc_set_md_var(tc, "descr",
62871.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
62881.1Skamil}
62891.1Skamil
62901.1SkamilATF_TC_BODY(syscallemu1, tc)
62911.1Skamil{
62921.1Skamil	const int exitval = 5;
62931.1Skamil	const int sigval = SIGSTOP;
62941.1Skamil	pid_t child, wpid;
62951.1Skamil#if defined(TWAIT_HAVE_STATUS)
62961.1Skamil	int status;
62971.1Skamil#endif
62981.1Skamil
62991.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
63001.6Skamil	/* syscallemu does not work on sparc (32-bit) */
63011.6Skamil	atf_tc_expect_fail("PR kern/52166");
63021.6Skamil#endif
63031.6Skamil
63041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63061.1Skamil	if (child == 0) {
63071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63091.1Skamil
63101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63121.1Skamil
63131.1Skamil		syscall(SYS_exit, 100);
63141.1Skamil
63151.13Schristos		DPRINTF("Before exiting of the child process\n");
63161.1Skamil		_exit(exitval);
63171.1Skamil	}
63181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63191.1Skamil
63201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63221.1Skamil
63231.1Skamil	validate_status_stopped(status, sigval);
63241.1Skamil
63251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63261.1Skamil	    "without signal to be sent\n");
63271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
63281.1Skamil
63291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63311.1Skamil
63321.1Skamil	validate_status_stopped(status, SIGTRAP);
63331.1Skamil
63341.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
63351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
63361.1Skamil
63371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63381.1Skamil	    "without signal to be sent\n");
63391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
63401.1Skamil
63411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63431.1Skamil
63441.1Skamil	validate_status_stopped(status, SIGTRAP);
63451.1Skamil
63461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63471.1Skamil	    "without signal to be sent\n");
63481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63491.1Skamil
63501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63521.1Skamil
63531.1Skamil	validate_status_exited(status, exitval);
63541.1Skamil
63551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63561.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63571.1Skamil}
63581.1Skamil
63591.103Skamil/// ----------------------------------------------------------------------------
63601.103Skamil
63611.106Skamilstatic void
63621.106Skamilclone_body(int flags, bool trackfork, bool trackvfork,
63631.106Skamil    bool trackvforkdone)
63641.106Skamil{
63651.106Skamil	const int exitval = 5;
63661.106Skamil	const int exitval2 = 15;
63671.106Skamil	const int sigval = SIGSTOP;
63681.106Skamil	pid_t child, child2 = 0, wpid;
63691.106Skamil#if defined(TWAIT_HAVE_STATUS)
63701.106Skamil	int status;
63711.106Skamil#endif
63721.106Skamil	ptrace_state_t state;
63731.106Skamil	const int slen = sizeof(state);
63741.106Skamil	ptrace_event_t event;
63751.106Skamil	const int elen = sizeof(event);
63761.106Skamil
63771.106Skamil	const size_t stack_size = 1024 * 1024;
63781.106Skamil	void *stack, *stack_base;
63791.106Skamil
63801.106Skamil	stack = malloc(stack_size);
63811.106Skamil	ATF_REQUIRE(stack != NULL);
63821.106Skamil
63831.106Skamil#ifdef __MACHINE_STACK_GROWS_UP
63841.106Skamil	stack_base = stack;
63851.106Skamil#else
63861.106Skamil	stack_base = (char *)stack + stack_size;
63871.106Skamil#endif
63881.106Skamil
63891.106Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
63901.106Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
63911.106Skamil	if (child == 0) {
63921.106Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63931.106Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63941.106Skamil
63951.106Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63961.106Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63971.106Skamil
63981.106Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
63991.106Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
64001.106Skamil
64011.106Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
64021.106Skamil		    child2);
64031.106Skamil
64041.106Skamil		// XXX WALLSIG?
64051.106Skamil		FORKEE_REQUIRE_SUCCESS
64061.106Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
64071.106Skamil
64081.106Skamil		forkee_status_exited(status, exitval2);
64091.106Skamil
64101.106Skamil		DPRINTF("Before exiting of the child process\n");
64111.106Skamil		_exit(exitval);
64121.106Skamil	}
64131.106Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64141.106Skamil
64151.106Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64161.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64171.106Skamil
64181.106Skamil	validate_status_stopped(status, sigval);
64191.106Skamil
64201.106Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
64211.106Skamil	    trackfork ? "|PTRACE_FORK" : "",
64221.106Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
64231.106Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
64241.106Skamil	event.pe_set_event = 0;
64251.106Skamil	if (trackfork)
64261.106Skamil		event.pe_set_event |= PTRACE_FORK;
64271.106Skamil	if (trackvfork)
64281.106Skamil		event.pe_set_event |= PTRACE_VFORK;
64291.106Skamil	if (trackvforkdone)
64301.106Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
64311.106Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
64321.106Skamil
64331.106Skamil	DPRINTF("Before resuming the child process where it left off and "
64341.106Skamil	    "without signal to be sent\n");
64351.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64361.106Skamil
64371.106Skamil#if defined(TWAIT_HAVE_PID)
64381.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
64391.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
64401.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
64411.106Skamil		    child);
64421.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
64431.106Skamil		    child);
64441.106Skamil
64451.106Skamil		validate_status_stopped(status, SIGTRAP);
64461.106Skamil
64471.106Skamil		SYSCALL_REQUIRE(
64481.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
64491.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
64501.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
64511.106Skamil			       PTRACE_FORK);
64521.106Skamil		}
64531.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
64541.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
64551.106Skamil			       PTRACE_VFORK);
64561.106Skamil		}
64571.106Skamil
64581.106Skamil		child2 = state.pe_other_pid;
64591.106Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
64601.106Skamil
64611.106Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
64621.106Skamil		    "%d\n", TWAIT_FNAME, child2, child);
64631.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
64641.106Skamil		    child2);
64651.106Skamil
64661.106Skamil		validate_status_stopped(status, SIGTRAP);
64671.106Skamil
64681.106Skamil		SYSCALL_REQUIRE(
64691.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
64701.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
64711.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
64721.106Skamil			       PTRACE_FORK);
64731.106Skamil		}
64741.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
64751.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
64761.106Skamil			       PTRACE_VFORK);
64771.106Skamil		}
64781.106Skamil
64791.106Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
64801.106Skamil
64811.106Skamil		DPRINTF("Before resuming the forkee process where it left off "
64821.106Skamil		    "and without signal to be sent\n");
64831.106Skamil		SYSCALL_REQUIRE(
64841.106Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
64851.106Skamil
64861.106Skamil		DPRINTF("Before resuming the child process where it left off "
64871.106Skamil		    "and without signal to be sent\n");
64881.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64891.106Skamil	}
64901.106Skamil#endif
64911.106Skamil
64921.106Skamil	if (trackvforkdone && (flags & CLONE_VFORK)) {
64931.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
64941.106Skamil		    child);
64951.106Skamil		TWAIT_REQUIRE_SUCCESS(
64961.106Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
64971.106Skamil
64981.106Skamil		validate_status_stopped(status, SIGTRAP);
64991.106Skamil
65001.106Skamil		SYSCALL_REQUIRE(
65011.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
65021.106Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
65031.106Skamil
65041.106Skamil		child2 = state.pe_other_pid;
65051.106Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
65061.106Skamil		    child2);
65071.106Skamil
65081.106Skamil		DPRINTF("Before resuming the child process where it left off "
65091.106Skamil		    "and without signal to be sent\n");
65101.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65111.106Skamil	}
65121.106Skamil
65131.103Skamil#if defined(TWAIT_HAVE_PID)
65141.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
65151.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
65161.106Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
65171.106Skamil		    "\n", TWAIT_FNAME);
65181.106Skamil		TWAIT_REQUIRE_SUCCESS(
65191.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
65201.106Skamil
65211.106Skamil		validate_status_exited(status, exitval2);
65221.106Skamil
65231.106Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
65241.106Skamil		    "process\n", TWAIT_FNAME);
65251.106Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
65261.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
65271.106Skamil	}
65281.106Skamil#endif
65291.106Skamil
65301.106Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
65311.106Skamil	    "SIGCHLD\n", TWAIT_FNAME);
65321.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65331.106Skamil
65341.106Skamil	validate_status_stopped(status, SIGCHLD);
65351.106Skamil
65361.106Skamil	DPRINTF("Before resuming the child process where it left off and "
65371.106Skamil	    "without signal to be sent\n");
65381.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65391.106Skamil
65401.106Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
65411.106Skamil	    TWAIT_FNAME);
65421.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65431.106Skamil
65441.106Skamil	validate_status_exited(status, exitval);
65451.103Skamil
65461.106Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
65471.106Skamil	    TWAIT_FNAME);
65481.106Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65491.106Skamil}
65501.103Skamil
65511.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone)			\
65521.106SkamilATF_TC(name);								\
65531.106SkamilATF_TC_HEAD(name, tc)							\
65541.106Skamil{									\
65551.106Skamil	atf_tc_set_md_var(tc, "descr", "Verify clone(%s) "		\
65561.106Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
65571.106Skamil	    #flags,							\
65581.106Skamil	    tfork ? "|PTRACE_FORK" : "",				\
65591.106Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
65601.106Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
65611.106Skamil}									\
65621.106Skamil									\
65631.106SkamilATF_TC_BODY(name, tc)							\
65641.106Skamil{									\
65651.106Skamil									\
65661.106Skamil	clone_body(flags, tfork, tvfork, tvforkdone);			\
65671.103Skamil}
65681.103Skamil
65691.106SkamilCLONE_TEST(clone1, 0, false, false, false)
65701.106Skamil#if defined(TWAIT_HAVE_PID)
65711.106SkamilCLONE_TEST(clone2, 0, true, false, false)
65721.106SkamilCLONE_TEST(clone3, 0, false, true, false)
65731.106SkamilCLONE_TEST(clone4, 0, true, true, false)
65741.106Skamil#endif
65751.106SkamilCLONE_TEST(clone5, 0, false, false, true)
65761.106Skamil#if defined(TWAIT_HAVE_PID)
65771.106SkamilCLONE_TEST(clone6, 0, true, false, true)
65781.106SkamilCLONE_TEST(clone7, 0, false, true, true)
65791.106SkamilCLONE_TEST(clone8, 0, true, true, true)
65801.106Skamil#endif
65811.106Skamil
65821.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false)
65831.106Skamil#if defined(TWAIT_HAVE_PID)
65841.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false)
65851.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false)
65861.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false)
65871.106Skamil#endif
65881.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true)
65891.106Skamil#if defined(TWAIT_HAVE_PID)
65901.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true)
65911.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true)
65921.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true)
65931.106Skamil#endif
65941.106Skamil
65951.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false)
65961.106Skamil#if defined(TWAIT_HAVE_PID)
65971.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false)
65981.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false)
65991.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false)
66001.106Skamil#endif
66011.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true)
66021.106Skamil#if defined(TWAIT_HAVE_PID)
66031.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true)
66041.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true)
66051.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true)
66061.106Skamil#endif
66071.106Skamil
66081.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false)
66091.106Skamil#if defined(TWAIT_HAVE_PID)
66101.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false)
66111.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false)
66121.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false)
66131.106Skamil#endif
66141.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true)
66151.106Skamil#if defined(TWAIT_HAVE_PID)
66161.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true)
66171.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true)
66181.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true)
66191.106Skamil#endif
66201.106Skamil
66211.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false)
66221.106Skamil#if defined(TWAIT_HAVE_PID)
66231.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false)
66241.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false)
66251.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false)
66261.106Skamil#endif
66271.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true)
66281.106Skamil#if defined(TWAIT_HAVE_PID)
66291.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true)
66301.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true)
66311.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true)
66321.106Skamil#endif
66331.106Skamil
66341.110Skamil#if TEST_VFORK_ENABLED
66351.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false)
66361.106Skamil#if defined(TWAIT_HAVE_PID)
66371.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false)
66381.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false)
66391.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false)
66401.106Skamil#endif
66411.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true)
66421.106Skamil#if defined(TWAIT_HAVE_PID)
66431.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true)
66441.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true)
66451.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true)
66461.106Skamil#endif
66471.110Skamil#endif
66481.106Skamil
66491.106Skamil/// ----------------------------------------------------------------------------
66501.106Skamil
66511.106Skamil#if defined(TWAIT_HAVE_PID)
66521.103Skamilstatic void
66531.106Skamilclone_body2(int flags, bool masked, bool ignored)
66541.103Skamil{
66551.103Skamil	const int exitval = 5;
66561.103Skamil	const int exitval2 = 15;
66571.103Skamil	const int sigval = SIGSTOP;
66581.103Skamil	pid_t child, child2 = 0, wpid;
66591.103Skamil#if defined(TWAIT_HAVE_STATUS)
66601.103Skamil	int status;
66611.103Skamil#endif
66621.103Skamil	ptrace_state_t state;
66631.103Skamil	const int slen = sizeof(state);
66641.103Skamil	ptrace_event_t event;
66651.103Skamil	const int elen = sizeof(event);
66661.103Skamil	struct sigaction sa;
66671.103Skamil	struct ptrace_siginfo info;
66681.103Skamil	sigset_t intmask;
66691.103Skamil	struct kinfo_proc2 kp;
66701.103Skamil	size_t len = sizeof(kp);
66711.103Skamil
66721.103Skamil	int name[6];
66731.103Skamil	const size_t namelen = __arraycount(name);
66741.103Skamil	ki_sigset_t kp_sigmask;
66751.103Skamil	ki_sigset_t kp_sigignore;
66761.103Skamil
66771.103Skamil	const size_t stack_size = 1024 * 1024;
66781.103Skamil	void *stack, *stack_base;
66791.103Skamil
66801.103Skamil	stack = malloc(stack_size);
66811.103Skamil	ATF_REQUIRE(stack != NULL);
66821.103Skamil
66831.103Skamil#ifdef __MACHINE_STACK_GROWS_UP
66841.103Skamil	stack_base = stack;
66851.103Skamil#else
66861.103Skamil	stack_base = (char *)stack + stack_size;
66871.103Skamil#endif
66881.103Skamil
66891.103Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
66901.103Skamil	if (child == 0) {
66911.103Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66921.103Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66931.103Skamil
66941.103Skamil		if (masked) {
66951.103Skamil			sigemptyset(&intmask);
66961.103Skamil			sigaddset(&intmask, SIGTRAP);
66971.103Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
66981.103Skamil		}
66991.103Skamil
67001.103Skamil		if (ignored) {
67011.103Skamil			memset(&sa, 0, sizeof(sa));
67021.103Skamil			sa.sa_handler = SIG_IGN;
67031.103Skamil			sigemptyset(&sa.sa_mask);
67041.103Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
67051.103Skamil		}
67061.103Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67071.103Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67081.103Skamil
67091.103Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
67101.103Skamil		    flags);
67111.103Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
67121.103Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
67131.103Skamil
67141.103Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
67151.103Skamil		    child2);
67161.103Skamil
67171.103Skamil		// XXX WALLSIG?
67181.103Skamil		FORKEE_REQUIRE_SUCCESS
67191.103Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
67201.103Skamil
67211.103Skamil		forkee_status_exited(status, exitval2);
67221.103Skamil
67231.103Skamil		DPRINTF("Before exiting of the child process\n");
67241.103Skamil		_exit(exitval);
67251.103Skamil	}
67261.103Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67271.103Skamil
67281.103Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67291.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67301.103Skamil
67311.103Skamil	validate_status_stopped(status, sigval);
67321.103Skamil
67331.103Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
67341.103Skamil	SYSCALL_REQUIRE(
67351.103Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
67361.103Skamil
67371.103Skamil	DPRINTF("Before checking siginfo_t\n");
67381.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
67391.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
67401.103Skamil
67411.103Skamil	name[0] = CTL_KERN,
67421.103Skamil	name[1] = KERN_PROC2,
67431.103Skamil	name[2] = KERN_PROC_PID;
67441.103Skamil	name[3] = child;
67451.103Skamil	name[4] = sizeof(kp);
67461.103Skamil	name[5] = 1;
67471.103Skamil
67481.103Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
67491.103Skamil
67501.103Skamil	if (masked)
67511.103Skamil		kp_sigmask = kp.p_sigmask;
67521.103Skamil
67531.103Skamil	if (ignored)
67541.103Skamil		kp_sigignore = kp.p_sigignore;
67551.103Skamil
67561.103Skamil	DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in "
67571.103Skamil	    "EVENT_MASK for the child %d\n", child);
67581.103Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
67591.103Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
67601.103Skamil
67611.103Skamil	DPRINTF("Before resuming the child process where it left off and "
67621.103Skamil	    "without signal to be sent\n");
67631.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67641.103Skamil
67651.103Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
67661.103Skamil	    child);
67671.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
67681.103Skamil	    child);
67691.103Skamil
67701.103Skamil	validate_status_stopped(status, SIGTRAP);
67711.103Skamil
67721.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
67731.103Skamil
67741.103Skamil	if (masked) {
67751.103Skamil		DPRINTF("kp_sigmask="
67761.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
67771.103Skamil		    PRIx32 "\n",
67781.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
67791.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
67801.103Skamil
67811.103Skamil		DPRINTF("kp.p_sigmask="
67821.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
67831.103Skamil		    PRIx32 "\n",
67841.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
67851.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
67861.103Skamil
67871.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
67881.103Skamil		    sizeof(kp_sigmask)));
67891.103Skamil	}
67901.103Skamil
67911.103Skamil	if (ignored) {
67921.103Skamil		DPRINTF("kp_sigignore="
67931.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
67941.103Skamil		    PRIx32 "\n",
67951.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
67961.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
67971.103Skamil
67981.103Skamil		DPRINTF("kp.p_sigignore="
67991.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68001.103Skamil		    PRIx32 "\n",
68011.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
68021.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
68031.103Skamil
68041.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
68051.103Skamil		    sizeof(kp_sigignore)));
68061.103Skamil	}
68071.103Skamil
68081.103Skamil	SYSCALL_REQUIRE(
68091.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
68101.103Skamil	DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event,
68111.103Skamil	    child2);
68121.103Skamil	if (!(flags & CLONE_VFORK)) {
68131.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
68141.103Skamil		       PTRACE_FORK);
68151.103Skamil	} else {
68161.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
68171.103Skamil		       PTRACE_VFORK);
68181.103Skamil	}
68191.103Skamil
68201.103Skamil	child2 = state.pe_other_pid;
68211.103Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
68221.103Skamil
68231.103Skamil	DPRINTF("Before calling %s() for the forkee %d of the child "
68241.103Skamil	    "%d\n", TWAIT_FNAME, child2, child);
68251.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
68261.103Skamil	    child2);
68271.103Skamil
68281.103Skamil	validate_status_stopped(status, SIGTRAP);
68291.103Skamil
68301.103Skamil	name[3] = child2;
68311.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
68321.103Skamil
68331.103Skamil	if (masked) {
68341.103Skamil		DPRINTF("kp_sigmask="
68351.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68361.103Skamil		    PRIx32 "\n",
68371.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
68381.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
68391.103Skamil
68401.103Skamil		DPRINTF("kp.p_sigmask="
68411.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68421.103Skamil		    PRIx32 "\n",
68431.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
68441.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
68451.103Skamil
68461.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
68471.103Skamil		    sizeof(kp_sigmask)));
68481.103Skamil	}
68491.103Skamil
68501.103Skamil	if (ignored) {
68511.103Skamil		DPRINTF("kp_sigignore="
68521.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68531.103Skamil		    PRIx32 "\n",
68541.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
68551.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
68561.103Skamil
68571.103Skamil		DPRINTF("kp.p_sigignore="
68581.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68591.103Skamil		    PRIx32 "\n",
68601.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
68611.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
68621.103Skamil
68631.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
68641.103Skamil		    sizeof(kp_sigignore)));
68651.103Skamil	}
68661.103Skamil
68671.103Skamil	SYSCALL_REQUIRE(
68681.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
68691.103Skamil	if (!(flags & CLONE_VFORK)) {
68701.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
68711.103Skamil		       PTRACE_FORK);
68721.103Skamil	} else {
68731.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
68741.103Skamil		       PTRACE_VFORK);
68751.103Skamil	}
68761.103Skamil
68771.103Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
68781.103Skamil
68791.103Skamil	DPRINTF("Before resuming the forkee process where it left off "
68801.103Skamil	    "and without signal to be sent\n");
68811.103Skamil	SYSCALL_REQUIRE(
68821.103Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
68831.103Skamil
68841.103Skamil	DPRINTF("Before resuming the child process where it left off "
68851.103Skamil	    "and without signal to be sent\n");
68861.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68871.103Skamil
68881.103Skamil	if (flags & CLONE_VFORK) {
68891.103Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
68901.103Skamil		    child);
68911.103Skamil		TWAIT_REQUIRE_SUCCESS(
68921.103Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
68931.103Skamil
68941.103Skamil		validate_status_stopped(status, SIGTRAP);
68951.103Skamil
68961.103Skamil		name[3] = child;
68971.103Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
68981.103Skamil
68991.103Skamil		/*
69001.103Skamil		 * SIGCHLD is now pending in the signal queue and
69011.103Skamil		 * the kernel presents it to userland as a masked signal.
69021.103Skamil		 */
69031.103Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
69041.103Skamil
69051.103Skamil		if (masked) {
69061.103Skamil			DPRINTF("kp_sigmask="
69071.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69081.103Skamil			    PRIx32 "\n",
69091.103Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
69101.103Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
69111.103Skamil
69121.103Skamil			DPRINTF("kp.p_sigmask="
69131.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69141.103Skamil			    PRIx32 "\n",
69151.103Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
69161.103Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
69171.103Skamil
69181.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
69191.103Skamil			    sizeof(kp_sigmask)));
69201.103Skamil		}
69211.103Skamil
69221.103Skamil		if (ignored) {
69231.103Skamil			DPRINTF("kp_sigignore="
69241.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69251.103Skamil			    PRIx32 "\n",
69261.103Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
69271.103Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
69281.103Skamil
69291.103Skamil			DPRINTF("kp.p_sigignore="
69301.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69311.103Skamil			    PRIx32 "\n",
69321.103Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
69331.103Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
69341.103Skamil
69351.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
69361.103Skamil			    sizeof(kp_sigignore)));
69371.103Skamil		}
69381.103Skamil
69391.103Skamil		SYSCALL_REQUIRE(
69401.103Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
69411.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
69421.103Skamil
69431.103Skamil		child2 = state.pe_other_pid;
69441.103Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
69451.103Skamil		    child2);
69461.103Skamil
69471.103Skamil		DPRINTF("Before resuming the child process where it left off "
69481.103Skamil		    "and without signal to be sent\n");
69491.103Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69501.103Skamil	}
69511.103Skamil
69521.103Skamil	DPRINTF("Before calling %s() for the forkee - expected exited"
69531.103Skamil	    "\n", TWAIT_FNAME);
69541.103Skamil	TWAIT_REQUIRE_SUCCESS(
69551.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
69561.103Skamil
69571.103Skamil	validate_status_exited(status, exitval2);
69581.103Skamil
69591.103Skamil	DPRINTF("Before calling %s() for the forkee - expected no "
69601.103Skamil	    "process\n", TWAIT_FNAME);
69611.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
69621.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
69631.103Skamil
69641.103Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
69651.103Skamil	    "SIGCHLD\n", TWAIT_FNAME);
69661.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69671.103Skamil
69681.103Skamil	validate_status_stopped(status, SIGCHLD);
69691.103Skamil
69701.103Skamil	DPRINTF("Before resuming the child process where it left off and "
69711.103Skamil	    "without signal to be sent\n");
69721.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69731.103Skamil
69741.103Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
69751.103Skamil	    TWAIT_FNAME);
69761.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69771.103Skamil
69781.103Skamil	validate_status_exited(status, exitval);
69791.103Skamil
69801.103Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
69811.103Skamil	    TWAIT_FNAME);
69821.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69831.103Skamil}
69841.103Skamil
69851.106Skamil#define CLONE_TEST2(name,flags,masked,ignored)				\
69861.103SkamilATF_TC(name);								\
69871.103SkamilATF_TC_HEAD(name, tc)							\
69881.103Skamil{									\
69891.103Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\
69901.103Skamil	    " regardless of signal %s%s", 				\
69911.103Skamil	    #flags, masked ? "masked" : "", ignored ? "ignored" : "");	\
69921.103Skamil}									\
69931.103Skamil									\
69941.103SkamilATF_TC_BODY(name, tc)							\
69951.103Skamil{									\
69961.103Skamil									\
69971.106Skamil	clone_body2(flags, masked, ignored);				\
69981.103Skamil}
69991.103Skamil
70001.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false)
70011.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true)
70021.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false)
70031.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true)
70041.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false)
70051.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true)
70061.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false)
70071.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true)
70081.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX
70091.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true)  // XXX
70101.110Skamil#if TEST_VFORK_ENABLED
70111.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false)
70121.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true)
70131.103Skamil#endif
70141.110Skamil#endif
70151.103Skamil
70161.103Skamil/// ----------------------------------------------------------------------------
70171.103Skamil
70181.111Skamil#if TEST_VFORK_ENABLED
70191.107Skamil#if defined(TWAIT_HAVE_PID)
70201.107Skamilstatic void
70211.107Skamiltraceme_vfork_clone_body(int flags)
70221.107Skamil{
70231.107Skamil	const int exitval = 5;
70241.107Skamil	const int exitval2 = 15;
70251.107Skamil	pid_t child, child2 = 0, wpid;
70261.107Skamil#if defined(TWAIT_HAVE_STATUS)
70271.107Skamil	int status;
70281.107Skamil#endif
70291.107Skamil
70301.107Skamil	const size_t stack_size = 1024 * 1024;
70311.107Skamil	void *stack, *stack_base;
70321.107Skamil
70331.107Skamil	stack = malloc(stack_size);
70341.107Skamil	ATF_REQUIRE(stack != NULL);
70351.107Skamil
70361.107Skamil#ifdef __MACHINE_STACK_GROWS_UP
70371.107Skamil	stack_base = stack;
70381.107Skamil#else
70391.107Skamil	stack_base = (char *)stack + stack_size;
70401.107Skamil#endif
70411.107Skamil
70421.107Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
70431.107Skamil	if (child == 0) {
70441.107Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
70451.107Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
70461.107Skamil
70471.107Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
70481.107Skamil		    flags);
70491.107Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
70501.107Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
70511.107Skamil
70521.107Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
70531.107Skamil		    child2);
70541.107Skamil
70551.107Skamil		// XXX WALLSIG?
70561.107Skamil		FORKEE_REQUIRE_SUCCESS
70571.107Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
70581.107Skamil
70591.107Skamil		forkee_status_exited(status, exitval2);
70601.107Skamil
70611.107Skamil		DPRINTF("Before exiting of the child process\n");
70621.107Skamil		_exit(exitval);
70631.107Skamil	}
70641.107Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
70651.107Skamil
70661.107Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
70671.107Skamil	    TWAIT_FNAME);
70681.107Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
70691.107Skamil
70701.107Skamil	validate_status_exited(status, exitval);
70711.107Skamil
70721.107Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
70731.107Skamil	    TWAIT_FNAME);
70741.107Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
70751.107Skamil}
70761.107Skamil
70771.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags)				\
70781.107SkamilATF_TC(name);								\
70791.107SkamilATF_TC_HEAD(name, tc)							\
70801.107Skamil{									\
70811.107Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is "	\
70821.107Skamil	    "handled correctly with vfork(2)ed tracer", 		\
70831.107Skamil	    #flags);							\
70841.107Skamil}									\
70851.107Skamil									\
70861.107SkamilATF_TC_BODY(name, tc)							\
70871.107Skamil{									\
70881.107Skamil									\
70891.107Skamil	traceme_vfork_clone_body(flags);				\
70901.107Skamil}
70911.107Skamil
70921.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0)
70931.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM)
70941.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS)
70951.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES)
70961.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND)  // XXX
70971.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK)
70981.107Skamil#endif
70991.110Skamil#endif
71001.107Skamil
71011.107Skamil/// ----------------------------------------------------------------------------
71021.107Skamil
71031.1Skamil#include "t_ptrace_amd64_wait.h"
71041.1Skamil#include "t_ptrace_i386_wait.h"
71051.1Skamil#include "t_ptrace_x86_wait.h"
71061.1Skamil
71071.1SkamilATF_TP_ADD_TCS(tp)
71081.1Skamil{
71091.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
71101.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
71111.33Skamil
71121.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
71131.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
71141.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
71151.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
71161.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
71171.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
71181.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
71191.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
71201.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
71211.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
71221.33Skamil
71231.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
71241.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
71251.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
71261.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
71271.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
71281.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
71291.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
71301.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
71311.87Skamil
71321.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
71331.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
71341.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
71351.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
71361.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
71371.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
71381.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
71391.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
71401.86Skamil
71411.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
71421.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
71431.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
71441.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
71451.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
71461.59Skamil
71471.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
71481.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
71491.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
71501.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
71511.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
71521.88Skamil
71531.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
71541.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
71551.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
71561.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
71571.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
71581.88Skamil
71591.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
71601.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
71611.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
71621.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
71631.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
71641.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
71651.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
71661.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
71671.50Skamil
71681.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
71691.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
71701.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
71711.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
71721.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
71731.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
71741.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
71751.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
71761.50Skamil
71771.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
71781.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
71791.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
71801.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
71811.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
71821.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
71831.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
71841.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
71851.50Skamil
71861.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
71871.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
71881.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
71891.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
71901.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
71911.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
71921.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
71931.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
71941.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
71951.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
71961.1Skamil
71971.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
71981.37Skamil
71991.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
72001.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
72011.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
72021.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
72031.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
72041.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
72051.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
72061.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
72071.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
72081.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
72091.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
72101.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
72111.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
72121.40Skamil
72131.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
72141.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
72151.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
72161.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
72171.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
72181.41Skamil
72191.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
72201.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
72211.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
72221.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
72231.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
72241.92Skamil
72251.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
72261.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
72271.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
72281.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
72291.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
72301.92Skamil
72311.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
72321.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
72331.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
72341.43Skamil
72351.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
72361.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
72371.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
72381.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
72391.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
72401.59Skamil
72411.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72421.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
72431.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72441.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
72451.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72461.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
72471.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72481.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
72491.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72501.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
72511.94Skamil
72521.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72531.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
72541.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72551.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
72561.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72571.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
72581.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72591.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
72601.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72611.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
72621.94Skamil
72631.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
72641.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
72651.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
72661.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
72671.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
72681.51Skamil
72691.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
72701.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
72711.51Skamil
72721.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
72731.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
72741.51Skamil
72751.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72761.51Skamil		tracee_sees_its_original_parent_getppid);
72771.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72781.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
72791.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72801.51Skamil		tracee_sees_its_original_parent_procfs_status);
72811.1Skamil
72821.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
72831.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
72841.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
72851.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
72861.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
72871.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
72881.1Skamil
72891.31Skamil	ATF_TP_ADD_TC(tp, fork1);
72901.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
72911.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
72921.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
72931.31Skamil	ATF_TP_ADD_TC(tp, fork5);
72941.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
72951.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
72961.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
72971.31Skamil
72981.109Skamil#if TEST_VFORK_ENABLED
72991.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
73001.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
73011.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
73021.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
73031.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
73041.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
73051.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
73061.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
73071.1Skamil
73081.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_fork);
73091.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_vfork);
73101.109Skamil#endif
73111.108Skamil
73121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
73131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
73141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
73151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
73161.54Skamil
73171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
73181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
73191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
73201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
73211.54Skamil
73221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
73231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
73241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
73251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
73261.54Skamil
73271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
73281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
73291.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
73301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
73311.54Skamil
73321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
73331.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
73341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
73351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
73361.54Skamil
73371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
73381.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
73391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
73401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
73411.54Skamil
73421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
73431.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
73441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
73451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
73461.54Skamil
73471.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
73481.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
73491.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
73501.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
73511.54Skamil
73521.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
73531.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
73541.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
73551.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
73561.54Skamil
73571.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
73581.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
73591.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
73601.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
73611.1Skamil
73621.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
73631.1Skamil
73641.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i);
73651.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d);
73661.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i);
73671.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d);
73681.101Skamil
73691.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i);
73701.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d);
73711.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i);
73721.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d);
73731.101Skamil
73741.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv);
73751.101Skamil
73761.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
73771.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
73781.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
73791.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
73801.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
73811.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
73821.1Skamil
73831.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
73841.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
73851.1Skamil
73861.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
73871.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
73881.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
73891.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
73901.1Skamil
73911.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
73921.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
73931.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
73941.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
73951.2Skamil
73961.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
73971.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
73981.95Skamil
73991.1Skamil	ATF_TP_ADD_TC(tp, kill1);
74001.1Skamil	ATF_TP_ADD_TC(tp, kill2);
74011.75Skamil	ATF_TP_ADD_TC(tp, kill3);
74021.1Skamil
74031.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
74041.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
74051.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
74061.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
74071.77Skamil
74081.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
74091.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
74101.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
74111.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
74121.1Skamil
74131.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
74141.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
74151.79Skamil
74161.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
74171.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
74181.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
74191.1Skamil
74201.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
74211.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
74221.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
74231.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
74241.1Skamil
74251.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
74261.84Skamil
74271.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
74281.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
74291.109Skamil#if TEST_VFORK_ENABLED
74301.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
74311.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
74321.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
74331.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
74341.109Skamil#endif
74351.99Skamil
74361.1Skamil	ATF_TP_ADD_TC(tp, signal9);
74371.1Skamil	ATF_TP_ADD_TC(tp, signal10);
74381.1Skamil
74391.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
74401.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
74411.1Skamil
74421.1Skamil	ATF_TP_ADD_TC(tp, resume1);
74431.1Skamil
74441.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
74451.1Skamil
74461.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
74471.1Skamil
74481.106Skamil	ATF_TP_ADD_TC(tp, clone1);
74491.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone2);
74501.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone3);
74511.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone4);
74521.106Skamil	ATF_TP_ADD_TC(tp, clone5);
74531.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone6);
74541.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone7);
74551.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone8);
74561.106Skamil
74571.106Skamil	ATF_TP_ADD_TC(tp, clone_vm1);
74581.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2);
74591.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3);
74601.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4);
74611.106Skamil	ATF_TP_ADD_TC(tp, clone_vm5);
74621.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6);
74631.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7);
74641.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8);
74651.106Skamil
74661.106Skamil	ATF_TP_ADD_TC(tp, clone_fs1);
74671.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2);
74681.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3);
74691.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4);
74701.106Skamil	ATF_TP_ADD_TC(tp, clone_fs5);
74711.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6);
74721.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7);
74731.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8);
74741.106Skamil
74751.106Skamil	ATF_TP_ADD_TC(tp, clone_files1);
74761.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2);
74771.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3);
74781.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4);
74791.106Skamil	ATF_TP_ADD_TC(tp, clone_files5);
74801.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6);
74811.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7);
74821.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8);
74831.106Skamil
74841.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand1); // XXX
74851.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX
74861.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX
74871.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX
74881.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand5); // XXX
74891.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX
74901.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX
74911.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX
74921.106Skamil
74931.109Skamil#if TEST_VFORK_ENABLED
74941.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork1);
74951.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2);
74961.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3);
74971.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4);
74981.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork5);
74991.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6);
75001.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7);
75011.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8);
75021.109Skamil#endif
75031.106Skamil
75041.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored);
75051.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked);
75061.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored);
75071.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked);
75081.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored);
75091.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked);
75101.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored);
75111.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked);
75121.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX
75131.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX
75141.109Skamil#if TEST_VFORK_ENABLED
75151.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored);
75161.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked);
75171.109Skamil#endif
75181.103Skamil
75191.109Skamil#if TEST_VFORK_ENABLED
75201.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone);
75211.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm);
75221.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs);
75231.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files);
75241.107Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX
75251.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork);
75261.109Skamil#endif
75271.107Skamil
75281.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
75291.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
75301.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
75311.1Skamil
75321.1Skamil	return atf_no_error();
75331.1Skamil}
7534