t_ptrace_wait.c revision 1.109
11.109Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.109 2019/04/15 16:47:47 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.109Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.109 2019/04/15 16:47:47 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.109Skamil#define TEST_VFORK_ENABLED 0
911.109Skamil
921.34Skamil/// ----------------------------------------------------------------------------
931.34Skamil
941.33Skamilstatic void
951.33Skamiltraceme_raise(int sigval)
961.1Skamil{
971.1Skamil	const int exitval = 5;
981.1Skamil	pid_t child, wpid;
991.1Skamil#if defined(TWAIT_HAVE_STATUS)
1001.1Skamil	int status;
1011.1Skamil#endif
1021.1Skamil
1031.45Skamil	struct ptrace_siginfo info;
1041.45Skamil	memset(&info, 0, sizeof(info));
1051.45Skamil
1061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1081.1Skamil	if (child == 0) {
1091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1111.1Skamil
1121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1141.1Skamil
1151.36Skamil		switch (sigval) {
1161.36Skamil		case SIGKILL:
1171.36Skamil			/* NOTREACHED */
1181.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1191.70Smrg			__unreachable();
1201.36Skamil		default:
1211.36Skamil			DPRINTF("Before exiting of the child process\n");
1221.36Skamil			_exit(exitval);
1231.36Skamil		}
1241.1Skamil	}
1251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1261.1Skamil
1271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1291.1Skamil
1301.36Skamil	switch (sigval) {
1311.36Skamil	case SIGKILL:
1321.36Skamil		validate_status_signaled(status, sigval, 0);
1331.36Skamil		break;
1341.36Skamil	default:
1351.36Skamil		validate_status_stopped(status, sigval);
1361.1Skamil
1371.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1381.61Skre			"child\n");
1391.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1401.61Skre			sizeof(info)) != -1);
1411.45Skamil
1421.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1431.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1441.61Skre			"si_errno=%#x\n",
1451.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1461.61Skre			info.psi_siginfo.si_errno);
1471.45Skamil
1481.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1491.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1501.45Skamil
1511.36Skamil		DPRINTF("Before resuming the child process where it left off "
1521.36Skamil		    "and without signal to be sent\n");
1531.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1541.1Skamil
1551.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1561.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1571.61Skre		    child);
1581.36Skamil		break;
1591.36Skamil	}
1601.1Skamil
1611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1631.1Skamil}
1641.1Skamil
1651.61Skre#define TRACEME_RAISE(test, sig)					\
1661.61SkreATF_TC(test);								\
1671.61SkreATF_TC_HEAD(test, tc)							\
1681.61Skre{									\
1691.61Skre	atf_tc_set_md_var(tc, "descr",					\
1701.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1711.61Skre}									\
1721.61Skre									\
1731.61SkreATF_TC_BODY(test, tc)							\
1741.61Skre{									\
1751.61Skre									\
1761.61Skre	traceme_raise(sig);						\
1771.33Skamil}
1781.33Skamil
1791.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1801.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1811.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1821.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1831.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1841.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1851.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1861.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1871.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
1881.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
1891.33Skamil
1901.34Skamil/// ----------------------------------------------------------------------------
1911.1Skamil
1921.1Skamilstatic void
1931.87Skamiltraceme_raisesignal_ignored(int sigignored)
1941.87Skamil{
1951.87Skamil	const int exitval = 5;
1961.87Skamil	const int sigval = SIGSTOP;
1971.87Skamil	pid_t child, wpid;
1981.87Skamil	struct sigaction sa;
1991.87Skamil#if defined(TWAIT_HAVE_STATUS)
2001.87Skamil	int status;
2011.87Skamil#endif
2021.87Skamil	struct ptrace_siginfo info;
2031.87Skamil
2041.87Skamil	memset(&info, 0, sizeof(info));
2051.87Skamil
2061.87Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2071.87Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2081.87Skamil	if (child == 0) {
2091.87Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2101.87Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2111.87Skamil
2121.87Skamil		memset(&sa, 0, sizeof(sa));
2131.87Skamil		sa.sa_handler = SIG_IGN;
2141.87Skamil		sigemptyset(&sa.sa_mask);
2151.87Skamil		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2161.87Skamil
2171.87Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2181.87Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2191.87Skamil
2201.87Skamil		DPRINTF("Before raising %s from child\n",
2211.87Skamil		    strsignal(sigignored));
2221.87Skamil		FORKEE_ASSERT(raise(sigignored) == 0);
2231.87Skamil
2241.87Skamil		DPRINTF("Before exiting of the child process\n");
2251.87Skamil		_exit(exitval);
2261.87Skamil	}
2271.87Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2281.87Skamil
2291.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2301.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2311.87Skamil
2321.87Skamil	validate_status_stopped(status, sigval);
2331.87Skamil
2341.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2351.87Skamil	SYSCALL_REQUIRE(
2361.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2371.87Skamil
2381.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2391.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2401.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2411.87Skamil	    info.psi_siginfo.si_errno);
2421.87Skamil
2431.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2441.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2451.87Skamil
2461.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2471.87Skamil	    "without signal to be sent\n");
2481.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2491.87Skamil
2501.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2511.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2521.87Skamil
2531.87Skamil	validate_status_stopped(status, sigignored);
2541.87Skamil
2551.87Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2561.87Skamil	SYSCALL_REQUIRE(
2571.87Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2581.87Skamil
2591.87Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2601.87Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2611.87Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2621.87Skamil	    info.psi_siginfo.si_errno);
2631.87Skamil
2641.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2651.87Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2661.87Skamil
2671.87Skamil	DPRINTF("Before resuming the child process where it left off and "
2681.87Skamil	    "without signal to be sent\n");
2691.87Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2701.87Skamil
2711.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2721.87Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2731.87Skamil
2741.87Skamil	validate_status_exited(status, exitval);
2751.87Skamil
2761.87Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2771.87Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2781.87Skamil}
2791.87Skamil
2801.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2811.87SkamilATF_TC(test);								\
2821.87SkamilATF_TC_HEAD(test, tc)							\
2831.87Skamil{									\
2841.87Skamil	atf_tc_set_md_var(tc, "descr",					\
2851.87Skamil	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
2861.87Skamil	    "does not stop tracer from catching this raised signal");	\
2871.87Skamil}									\
2881.87Skamil									\
2891.87SkamilATF_TC_BODY(test, tc)							\
2901.87Skamil{									\
2911.87Skamil									\
2921.87Skamil	traceme_raisesignal_ignored(sig);				\
2931.87Skamil}
2941.87Skamil
2951.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
2961.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
2971.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
2981.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
2991.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
3001.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
3011.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3021.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3031.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3041.87Skamil
3051.87Skamil/// ----------------------------------------------------------------------------
3061.87Skamil
3071.87Skamilstatic void
3081.86Skamiltraceme_raisesignal_masked(int sigmasked)
3091.86Skamil{
3101.86Skamil	const int exitval = 5;
3111.86Skamil	const int sigval = SIGSTOP;
3121.86Skamil	pid_t child, wpid;
3131.86Skamil#if defined(TWAIT_HAVE_STATUS)
3141.86Skamil	int status;
3151.86Skamil#endif
3161.86Skamil	sigset_t intmask;
3171.86Skamil	struct ptrace_siginfo info;
3181.86Skamil
3191.86Skamil	memset(&info, 0, sizeof(info));
3201.86Skamil
3211.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3221.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3231.86Skamil	if (child == 0) {
3241.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3251.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3261.86Skamil
3271.86Skamil		sigemptyset(&intmask);
3281.86Skamil		sigaddset(&intmask, sigmasked);
3291.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
3301.86Skamil
3311.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3321.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3331.86Skamil
3341.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
3351.86Skamil		    strsignal(sigmasked));
3361.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
3371.86Skamil
3381.86Skamil		DPRINTF("Before exiting of the child process\n");
3391.86Skamil		_exit(exitval);
3401.86Skamil	}
3411.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3421.86Skamil
3431.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3441.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3451.86Skamil
3461.86Skamil	validate_status_stopped(status, sigval);
3471.86Skamil
3481.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3491.86Skamil	SYSCALL_REQUIRE(
3501.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3511.86Skamil
3521.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3531.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3541.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3551.86Skamil	    info.psi_siginfo.si_errno);
3561.86Skamil
3571.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3581.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3591.86Skamil
3601.86Skamil	DPRINTF("Before resuming the child process where it left off and "
3611.86Skamil	    "without signal to be sent\n");
3621.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3631.86Skamil
3641.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3651.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3661.86Skamil
3671.86Skamil	validate_status_exited(status, exitval);
3681.86Skamil
3691.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3701.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3711.86Skamil}
3721.86Skamil
3731.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3741.86SkamilATF_TC(test);								\
3751.86SkamilATF_TC_HEAD(test, tc)							\
3761.86Skamil{									\
3771.86Skamil	atf_tc_set_md_var(tc, "descr",					\
3781.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3791.86Skamil	    "stops tracer from catching this raised signal");		\
3801.86Skamil}									\
3811.86Skamil									\
3821.86SkamilATF_TC_BODY(test, tc)							\
3831.86Skamil{									\
3841.86Skamil									\
3851.86Skamil	traceme_raisesignal_masked(sig);				\
3861.86Skamil}
3871.86Skamil
3881.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
3891.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
3901.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
3911.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
3921.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
3931.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
3941.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
3951.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
3961.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
3971.86Skamil
3981.86Skamil/// ----------------------------------------------------------------------------
3991.86Skamil
4001.86Skamilstatic void
4011.59Skamiltraceme_crash(int sig)
4021.59Skamil{
4031.59Skamil	pid_t child, wpid;
4041.59Skamil#if defined(TWAIT_HAVE_STATUS)
4051.59Skamil	int status;
4061.59Skamil#endif
4071.59Skamil	struct ptrace_siginfo info;
4081.61Skre
4091.71Skamil#ifndef PTRACE_ILLEGAL_ASM
4101.71Skamil	if (sig == SIGILL)
4111.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4121.71Skamil#endif
4131.71Skamil
4141.59Skamil	memset(&info, 0, sizeof(info));
4151.59Skamil
4161.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4171.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4181.59Skamil	if (child == 0) {
4191.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4201.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4211.59Skamil
4221.59Skamil		DPRINTF("Before executing a trap\n");
4231.59Skamil		switch (sig) {
4241.59Skamil		case SIGTRAP:
4251.59Skamil			trigger_trap();
4261.59Skamil			break;
4271.59Skamil		case SIGSEGV:
4281.59Skamil			trigger_segv();
4291.59Skamil			break;
4301.59Skamil		case SIGILL:
4311.59Skamil			trigger_ill();
4321.59Skamil			break;
4331.59Skamil		case SIGFPE:
4341.59Skamil			trigger_fpe();
4351.59Skamil			break;
4361.59Skamil		case SIGBUS:
4371.59Skamil			trigger_bus();
4381.59Skamil			break;
4391.59Skamil		default:
4401.59Skamil			/* NOTREACHED */
4411.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4421.59Skamil		}
4431.59Skamil
4441.59Skamil		/* NOTREACHED */
4451.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4461.59Skamil	}
4471.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4481.59Skamil
4491.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4501.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4511.59Skamil
4521.59Skamil	validate_status_stopped(status, sig);
4531.59Skamil
4541.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4551.61Skre	SYSCALL_REQUIRE(
4561.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4571.59Skamil
4581.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4591.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4601.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4611.61Skre	    info.psi_siginfo.si_errno);
4621.59Skamil
4631.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4641.59Skamil	switch (sig) {
4651.59Skamil	case SIGTRAP:
4661.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4671.59Skamil		break;
4681.59Skamil	case SIGSEGV:
4691.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4701.59Skamil		break;
4711.71Skamil	case SIGILL:
4721.71Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
4731.71Skamil		break;
4741.59Skamil	case SIGFPE:
4751.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4761.59Skamil		break;
4771.59Skamil	case SIGBUS:
4781.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
4791.59Skamil		break;
4801.59Skamil	}
4811.59Skamil
4821.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
4831.59Skamil
4841.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4851.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4861.59Skamil
4871.59Skamil	validate_status_signaled(status, SIGKILL, 0);
4881.59Skamil
4891.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4901.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4911.59Skamil}
4921.59Skamil
4931.61Skre#define TRACEME_CRASH(test, sig)					\
4941.61SkreATF_TC(test);								\
4951.61SkreATF_TC_HEAD(test, tc)							\
4961.61Skre{									\
4971.61Skre	atf_tc_set_md_var(tc, "descr",					\
4981.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
4991.61Skre}									\
5001.61Skre									\
5011.61SkreATF_TC_BODY(test, tc)							\
5021.61Skre{									\
5031.61Skre									\
5041.61Skre	traceme_crash(sig);						\
5051.59Skamil}
5061.59Skamil
5071.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5081.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5091.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
5101.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5111.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5121.59Skamil
5131.59Skamil/// ----------------------------------------------------------------------------
5141.59Skamil
5151.59Skamilstatic void
5161.88Skamiltraceme_signalmasked_crash(int sig)
5171.88Skamil{
5181.89Skamil	const int sigval = SIGSTOP;
5191.88Skamil	pid_t child, wpid;
5201.88Skamil#if defined(TWAIT_HAVE_STATUS)
5211.88Skamil	int status;
5221.88Skamil#endif
5231.88Skamil	struct ptrace_siginfo info;
5241.88Skamil	sigset_t intmask;
5251.89Skamil	struct kinfo_proc2 kp;
5261.89Skamil	size_t len = sizeof(kp);
5271.89Skamil
5281.89Skamil	int name[6];
5291.89Skamil	const size_t namelen = __arraycount(name);
5301.89Skamil	ki_sigset_t kp_sigmask;
5311.88Skamil
5321.88Skamil#ifndef PTRACE_ILLEGAL_ASM
5331.88Skamil	if (sig == SIGILL)
5341.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
5351.88Skamil#endif
5361.88Skamil
5371.88Skamil	memset(&info, 0, sizeof(info));
5381.88Skamil
5391.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5401.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5411.88Skamil	if (child == 0) {
5421.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5431.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5441.88Skamil
5451.88Skamil		sigemptyset(&intmask);
5461.88Skamil		sigaddset(&intmask, sig);
5471.88Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
5481.88Skamil
5491.89Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5501.89Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5511.89Skamil
5521.88Skamil		DPRINTF("Before executing a trap\n");
5531.88Skamil		switch (sig) {
5541.88Skamil		case SIGTRAP:
5551.88Skamil			trigger_trap();
5561.88Skamil			break;
5571.88Skamil		case SIGSEGV:
5581.88Skamil			trigger_segv();
5591.88Skamil			break;
5601.88Skamil		case SIGILL:
5611.88Skamil			trigger_ill();
5621.88Skamil			break;
5631.88Skamil		case SIGFPE:
5641.88Skamil			trigger_fpe();
5651.88Skamil			break;
5661.88Skamil		case SIGBUS:
5671.88Skamil			trigger_bus();
5681.88Skamil			break;
5691.88Skamil		default:
5701.88Skamil			/* NOTREACHED */
5711.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5721.88Skamil		}
5731.88Skamil
5741.88Skamil		/* NOTREACHED */
5751.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5761.88Skamil	}
5771.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5781.88Skamil
5791.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5801.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5811.88Skamil
5821.89Skamil	validate_status_stopped(status, sigval);
5831.89Skamil
5841.89Skamil	name[0] = CTL_KERN,
5851.89Skamil	name[1] = KERN_PROC2,
5861.89Skamil	name[2] = KERN_PROC_PID;
5871.89Skamil	name[3] = child;
5881.89Skamil	name[4] = sizeof(kp);
5891.89Skamil	name[5] = 1;
5901.89Skamil
5911.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
5921.89Skamil
5931.89Skamil	kp_sigmask = kp.p_sigmask;
5941.89Skamil
5951.89Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5961.89Skamil	SYSCALL_REQUIRE(
5971.89Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5981.89Skamil
5991.89Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6001.89Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6011.89Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6021.89Skamil	    info.psi_siginfo.si_errno);
6031.89Skamil
6041.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6051.89Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6061.89Skamil
6071.89Skamil	DPRINTF("Before resuming the child process where it left off and "
6081.89Skamil	    "without signal to be sent\n");
6091.89Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6101.89Skamil
6111.89Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6121.89Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6131.89Skamil
6141.88Skamil	validate_status_stopped(status, sig);
6151.88Skamil
6161.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
6171.88Skamil	SYSCALL_REQUIRE(
6181.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6191.88Skamil
6201.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6211.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6221.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6231.88Skamil	    info.psi_siginfo.si_errno);
6241.88Skamil
6251.89Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
6261.89Skamil
6271.89Skamil	DPRINTF("kp_sigmask="
6281.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6291.89Skamil	    kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2],
6301.89Skamil	    kp_sigmask.__bits[3]);
6311.89Skamil
6321.89Skamil	DPRINTF("kp.p_sigmask="
6331.89Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
6341.89Skamil	    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
6351.89Skamil	    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
6361.89Skamil
6371.89Skamil	ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask)));
6381.89Skamil
6391.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
6401.88Skamil	switch (sig) {
6411.88Skamil	case SIGTRAP:
6421.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
6431.88Skamil		break;
6441.88Skamil	case SIGSEGV:
6451.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
6461.88Skamil		break;
6471.88Skamil	case SIGILL:
6481.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
6491.88Skamil		break;
6501.88Skamil	case SIGFPE:
6511.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
6521.88Skamil		break;
6531.88Skamil	case SIGBUS:
6541.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
6551.88Skamil		break;
6561.88Skamil	}
6571.88Skamil
6581.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6591.88Skamil
6601.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6611.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6621.88Skamil
6631.88Skamil	validate_status_signaled(status, SIGKILL, 0);
6641.88Skamil
6651.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6661.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6671.88Skamil}
6681.88Skamil
6691.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig)				\
6701.88SkamilATF_TC(test);								\
6711.88SkamilATF_TC_HEAD(test, tc)							\
6721.88Skamil{									\
6731.88Skamil	atf_tc_set_md_var(tc, "descr",					\
6741.88Skamil	    "Verify masked crash signal " #sig " in a child after "	\
6751.88Skamil	    "PT_TRACE_ME is delivered to its tracer");			\
6761.88Skamil}									\
6771.88Skamil									\
6781.88SkamilATF_TC_BODY(test, tc)							\
6791.88Skamil{									\
6801.88Skamil									\
6811.88Skamil	traceme_signalmasked_crash(sig);				\
6821.88Skamil}
6831.88Skamil
6841.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP)
6851.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV)
6861.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL)
6871.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE)
6881.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS)
6891.88Skamil
6901.88Skamil/// ----------------------------------------------------------------------------
6911.88Skamil
6921.88Skamilstatic void
6931.88Skamiltraceme_signalignored_crash(int sig)
6941.88Skamil{
6951.90Skamil	const int sigval = SIGSTOP;
6961.88Skamil	pid_t child, wpid;
6971.88Skamil#if defined(TWAIT_HAVE_STATUS)
6981.88Skamil	int status;
6991.88Skamil#endif
7001.88Skamil	struct sigaction sa;
7011.88Skamil	struct ptrace_siginfo info;
7021.90Skamil	struct kinfo_proc2 kp;
7031.90Skamil	size_t len = sizeof(kp);
7041.90Skamil
7051.90Skamil	int name[6];
7061.90Skamil	const size_t namelen = __arraycount(name);
7071.90Skamil	ki_sigset_t kp_sigignore;
7081.88Skamil
7091.88Skamil#ifndef PTRACE_ILLEGAL_ASM
7101.88Skamil	if (sig == SIGILL)
7111.88Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
7121.88Skamil#endif
7131.88Skamil
7141.88Skamil	memset(&info, 0, sizeof(info));
7151.88Skamil
7161.88Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7171.88Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
7181.88Skamil	if (child == 0) {
7191.88Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7201.88Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7211.88Skamil
7221.88Skamil		memset(&sa, 0, sizeof(sa));
7231.88Skamil		sa.sa_handler = SIG_IGN;
7241.88Skamil		sigemptyset(&sa.sa_mask);
7251.88Skamil
7261.88Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
7271.88Skamil
7281.90Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7291.90Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7301.90Skamil
7311.88Skamil		DPRINTF("Before executing a trap\n");
7321.88Skamil		switch (sig) {
7331.88Skamil		case SIGTRAP:
7341.88Skamil			trigger_trap();
7351.88Skamil			break;
7361.88Skamil		case SIGSEGV:
7371.88Skamil			trigger_segv();
7381.88Skamil			break;
7391.88Skamil		case SIGILL:
7401.88Skamil			trigger_ill();
7411.88Skamil			break;
7421.88Skamil		case SIGFPE:
7431.88Skamil			trigger_fpe();
7441.88Skamil			break;
7451.88Skamil		case SIGBUS:
7461.88Skamil			trigger_bus();
7471.88Skamil			break;
7481.88Skamil		default:
7491.88Skamil			/* NOTREACHED */
7501.88Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7511.88Skamil		}
7521.88Skamil
7531.88Skamil		/* NOTREACHED */
7541.88Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7551.88Skamil	}
7561.88Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7571.88Skamil
7581.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7591.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7601.88Skamil
7611.90Skamil	validate_status_stopped(status, sigval);
7621.90Skamil
7631.90Skamil	name[0] = CTL_KERN,
7641.90Skamil	name[1] = KERN_PROC2,
7651.90Skamil	name[2] = KERN_PROC_PID;
7661.90Skamil	name[3] = child;
7671.90Skamil	name[4] = sizeof(kp);
7681.90Skamil	name[5] = 1;
7691.90Skamil
7701.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
7711.90Skamil
7721.90Skamil	kp_sigignore = kp.p_sigignore;
7731.90Skamil
7741.90Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7751.90Skamil	SYSCALL_REQUIRE(
7761.90Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7771.90Skamil
7781.90Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7791.90Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7801.90Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7811.90Skamil	    info.psi_siginfo.si_errno);
7821.90Skamil
7831.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
7841.90Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
7851.90Skamil
7861.90Skamil	DPRINTF("Before resuming the child process where it left off and "
7871.90Skamil	    "without signal to be sent\n");
7881.90Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
7891.90Skamil
7901.90Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7911.90Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7921.90Skamil
7931.88Skamil	validate_status_stopped(status, sig);
7941.88Skamil
7951.88Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
7961.88Skamil	SYSCALL_REQUIRE(
7971.88Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7981.88Skamil
7991.88Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8001.88Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8011.88Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8021.88Skamil	    info.psi_siginfo.si_errno);
8031.88Skamil
8041.90Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
8051.90Skamil
8061.90Skamil	DPRINTF("kp_sigignore="
8071.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8081.90Skamil	    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
8091.90Skamil	    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
8101.90Skamil
8111.90Skamil	DPRINTF("kp.p_sigignore="
8121.90Skamil	    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
8131.90Skamil	    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
8141.90Skamil	    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
8151.90Skamil
8161.90Skamil	ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore)));
8171.90Skamil
8181.88Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
8191.88Skamil	switch (sig) {
8201.88Skamil	case SIGTRAP:
8211.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
8221.88Skamil		break;
8231.88Skamil	case SIGSEGV:
8241.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
8251.88Skamil		break;
8261.88Skamil	case SIGILL:
8271.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
8281.88Skamil		break;
8291.88Skamil	case SIGFPE:
8301.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
8311.88Skamil		break;
8321.88Skamil	case SIGBUS:
8331.88Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
8341.88Skamil		break;
8351.88Skamil	}
8361.88Skamil
8371.88Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
8381.88Skamil
8391.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8401.88Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8411.88Skamil
8421.88Skamil	validate_status_signaled(status, SIGKILL, 0);
8431.88Skamil
8441.88Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8451.88Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8461.88Skamil}
8471.88Skamil
8481.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig)				\
8491.88SkamilATF_TC(test);								\
8501.88SkamilATF_TC_HEAD(test, tc)							\
8511.88Skamil{									\
8521.88Skamil	atf_tc_set_md_var(tc, "descr",					\
8531.88Skamil	    "Verify ignored crash signal " #sig " in a child after "	\
8541.88Skamil	    "PT_TRACE_ME is delivered to its tracer"); 			\
8551.88Skamil}									\
8561.88Skamil									\
8571.88SkamilATF_TC_BODY(test, tc)							\
8581.88Skamil{									\
8591.88Skamil									\
8601.88Skamil	traceme_signalignored_crash(sig);				\
8611.88Skamil}
8621.88Skamil
8631.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP)
8641.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV)
8651.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL)
8661.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE)
8671.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS)
8681.88Skamil
8691.88Skamil/// ----------------------------------------------------------------------------
8701.88Skamil
8711.88Skamilstatic void
8721.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
8731.1Skamil{
8741.1Skamil	const int exitval = 5;
8751.34Skamil	const int sigval = SIGSTOP;
8761.1Skamil	pid_t child, wpid;
8771.1Skamil	struct sigaction sa;
8781.1Skamil#if defined(TWAIT_HAVE_STATUS)
8791.1Skamil	int status;
8801.1Skamil#endif
8811.61Skre	struct ptrace_siginfo info;
8821.1Skamil
8831.45Skamil	memset(&info, 0, sizeof(info));
8841.45Skamil
8851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
8861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
8871.1Skamil	if (child == 0) {
8881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8901.1Skamil
8911.34Skamil		sa.sa_handler = sah;
8921.1Skamil		sa.sa_flags = SA_SIGINFO;
8931.1Skamil		sigemptyset(&sa.sa_mask);
8941.1Skamil
8951.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
8961.1Skamil
8971.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
8981.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
8991.1Skamil
9001.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
9011.1Skamil
9021.13Schristos		DPRINTF("Before exiting of the child process\n");
9031.1Skamil		_exit(exitval);
9041.1Skamil	}
9051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9061.1Skamil
9071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9091.1Skamil
9101.1Skamil	validate_status_stopped(status, sigval);
9111.1Skamil
9121.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9131.61Skre	SYSCALL_REQUIRE(
9141.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9151.45Skamil
9161.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9171.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9181.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9191.45Skamil	    info.psi_siginfo.si_errno);
9201.45Skamil
9211.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9221.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9231.45Skamil
9241.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
9251.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
9261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
9271.1Skamil
9281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9301.1Skamil
9311.1Skamil	validate_status_exited(status, exitval);
9321.1Skamil
9331.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9351.1Skamil}
9361.1Skamil
9371.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
9381.61SkreATF_TC(test);								\
9391.61SkreATF_TC_HEAD(test, tc)							\
9401.61Skre{									\
9411.61Skre	atf_tc_set_md_var(tc, "descr",					\
9421.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9431.61Skre	    "handled correctly and caught by a signal handler");	\
9441.61Skre}									\
9451.61Skre									\
9461.61Skrestatic int test##_caught = 0;						\
9471.61Skre									\
9481.61Skrestatic void								\
9491.61Skretest##_sighandler(int arg)						\
9501.61Skre{									\
9511.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
9521.61Skre									\
9531.61Skre	++ test##_caught;						\
9541.61Skre}									\
9551.61Skre									\
9561.61SkreATF_TC_BODY(test, tc)							\
9571.61Skre{									\
9581.61Skre									\
9591.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
9601.34Skamil}
9611.34Skamil
9621.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
9631.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
9641.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
9651.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
9661.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
9671.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
9681.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
9691.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
9701.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
9711.34Skamil
9721.34Skamil/// ----------------------------------------------------------------------------
9731.34Skamil
9741.35Skamilstatic void
9751.50Skamiltraceme_sendsignal_masked(int sigsent)
9761.50Skamil{
9771.50Skamil	const int exitval = 5;
9781.50Skamil	const int sigval = SIGSTOP;
9791.50Skamil	pid_t child, wpid;
9801.50Skamil	sigset_t set;
9811.50Skamil#if defined(TWAIT_HAVE_STATUS)
9821.50Skamil	int status;
9831.50Skamil#endif
9841.61Skre	struct ptrace_siginfo info;
9851.50Skamil
9861.50Skamil	memset(&info, 0, sizeof(info));
9871.50Skamil
9881.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9891.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
9901.50Skamil	if (child == 0) {
9911.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9921.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9931.50Skamil
9941.50Skamil		sigemptyset(&set);
9951.50Skamil		sigaddset(&set, sigsent);
9961.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
9971.50Skamil
9981.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9991.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10001.50Skamil
10011.50Skamil		_exit(exitval);
10021.50Skamil	}
10031.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10041.50Skamil
10051.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10061.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10071.50Skamil
10081.50Skamil	validate_status_stopped(status, sigval);
10091.50Skamil
10101.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10111.61Skre	SYSCALL_REQUIRE(
10121.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10131.50Skamil
10141.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10151.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10161.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10171.50Skamil	    info.psi_siginfo.si_errno);
10181.50Skamil
10191.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10201.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
10211.50Skamil
10221.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
10231.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
10241.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
10251.50Skamil
10261.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10271.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10281.50Skamil
10291.50Skamil	validate_status_exited(status, exitval);
10301.50Skamil
10311.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
10321.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10331.50Skamil}
10341.50Skamil
10351.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
10361.61SkreATF_TC(test);								\
10371.61SkreATF_TC_HEAD(test, tc)							\
10381.61Skre{									\
10391.61Skre	atf_tc_set_md_var(tc, "descr",					\
10401.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
10411.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
10421.61Skre}									\
10431.61Skre									\
10441.61SkreATF_TC_BODY(test, tc)							\
10451.61Skre{									\
10461.61Skre									\
10471.61Skre	traceme_sendsignal_masked(sig);					\
10481.50Skamil}
10491.50Skamil
10501.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
10511.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
10521.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
10531.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
10541.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
10551.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
10561.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
10571.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
10581.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
10591.50Skamil
10601.50Skamil/// ----------------------------------------------------------------------------
10611.50Skamil
10621.50Skamilstatic void
10631.50Skamiltraceme_sendsignal_ignored(int sigsent)
10641.50Skamil{
10651.50Skamil	const int exitval = 5;
10661.50Skamil	const int sigval = SIGSTOP;
10671.50Skamil	pid_t child, wpid;
10681.50Skamil	struct sigaction sa;
10691.50Skamil#if defined(TWAIT_HAVE_STATUS)
10701.50Skamil	int status;
10711.50Skamil#endif
10721.61Skre	struct ptrace_siginfo info;
10731.50Skamil
10741.50Skamil	memset(&info, 0, sizeof(info));
10751.50Skamil
10761.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10771.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
10781.50Skamil	if (child == 0) {
10791.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10801.61Skre
10811.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10821.50Skamil
10831.50Skamil		memset(&sa, 0, sizeof(sa));
10841.50Skamil		sa.sa_handler = SIG_IGN;
10851.50Skamil		sigemptyset(&sa.sa_mask);
10861.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
10871.50Skamil
10881.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10891.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10901.50Skamil
10911.50Skamil		_exit(exitval);
10921.50Skamil	}
10931.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10941.50Skamil
10951.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10961.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10971.50Skamil
10981.50Skamil	validate_status_stopped(status, sigval);
10991.50Skamil
11001.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11011.61Skre	SYSCALL_REQUIRE(
11021.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11031.50Skamil
11041.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11051.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11061.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11071.50Skamil	    info.psi_siginfo.si_errno);
11081.50Skamil
11091.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11101.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
11111.50Skamil
11121.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
11131.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
11141.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
11151.50Skamil
11161.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11171.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11181.50Skamil
11191.50Skamil	validate_status_exited(status, exitval);
11201.50Skamil
11211.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
11221.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11231.50Skamil}
11241.50Skamil
11251.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
11261.61SkreATF_TC(test);								\
11271.61SkreATF_TC_HEAD(test, tc)							\
11281.61Skre{									\
11291.61Skre	atf_tc_set_md_var(tc, "descr",					\
11301.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
11311.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
11321.61Skre}									\
11331.61Skre									\
11341.61SkreATF_TC_BODY(test, tc)							\
11351.61Skre{									\
11361.61Skre									\
11371.61Skre	traceme_sendsignal_ignored(sig);				\
11381.50Skamil}
11391.50Skamil
11401.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
11411.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
11421.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
11431.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
11441.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
11451.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
11461.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
11471.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
11481.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
11491.50Skamil
11501.50Skamil/// ----------------------------------------------------------------------------
11511.50Skamil
11521.50Skamilstatic void
11531.50Skamiltraceme_sendsignal_simple(int sigsent)
11541.1Skamil{
11551.35Skamil	const int sigval = SIGSTOP;
11561.35Skamil	int exitval = 0;
11571.1Skamil	pid_t child, wpid;
11581.1Skamil#if defined(TWAIT_HAVE_STATUS)
11591.1Skamil	int status;
11601.85Skamil	int expect_core;
11611.85Skamil
11621.85Skamil	switch (sigsent) {
11631.85Skamil	case SIGABRT:
11641.85Skamil	case SIGTRAP:
11651.85Skamil	case SIGBUS:
11661.85Skamil	case SIGILL:
11671.85Skamil	case SIGFPE:
11681.85Skamil	case SIGSEGV:
11691.85Skamil		expect_core = 1;
11701.85Skamil		break;
11711.85Skamil	default:
11721.85Skamil		expect_core = 0;
11731.85Skamil		break;
11741.85Skamil	}
11751.1Skamil#endif
11761.61Skre	struct ptrace_siginfo info;
11771.1Skamil
11781.45Skamil	memset(&info, 0, sizeof(info));
11791.45Skamil
11801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
11811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
11821.1Skamil	if (child == 0) {
11831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11851.1Skamil
11861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11881.1Skamil
11891.35Skamil		switch (sigsent) {
11901.35Skamil		case SIGCONT:
11911.48Skamil		case SIGSTOP:
11921.35Skamil			_exit(exitval);
11931.35Skamil		default:
11941.35Skamil			/* NOTREACHED */
11951.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
11961.35Skamil		}
11971.1Skamil	}
11981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11991.1Skamil
12001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12021.1Skamil
12031.1Skamil	validate_status_stopped(status, sigval);
12041.1Skamil
12051.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12061.61Skre	SYSCALL_REQUIRE(
12071.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12081.45Skamil
12091.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12101.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12111.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12121.45Skamil	    info.psi_siginfo.si_errno);
12131.45Skamil
12141.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12151.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12161.45Skamil
12171.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
12181.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
12191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
12201.1Skamil
12211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12231.1Skamil
12241.35Skamil	switch (sigsent) {
12251.48Skamil	case SIGSTOP:
12261.48Skamil		validate_status_stopped(status, sigsent);
12271.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
12281.61Skre		    "child\n");
12291.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
12301.61Skre		    sizeof(info)) != -1);
12311.48Skamil
12321.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12331.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12341.61Skre		    "si_errno=%#x\n",
12351.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12361.61Skre		    info.psi_siginfo.si_errno);
12371.48Skamil
12381.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12391.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
12401.48Skamil
12411.48Skamil		DPRINTF("Before resuming the child process where it left off "
12421.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
12431.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12441.48Skamil
12451.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12461.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
12471.61Skre		    child);
12481.48Skamil		/* FALLTHROUGH */
12491.35Skamil	case SIGCONT:
12501.35Skamil		validate_status_exited(status, exitval);
12511.35Skamil		break;
12521.35Skamil	default:
12531.35Skamil		validate_status_signaled(status, sigsent, expect_core);
12541.35Skamil		break;
12551.35Skamil	}
12561.1Skamil
12571.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
12581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12591.1Skamil}
12601.1Skamil
12611.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
12621.61SkreATF_TC(test);								\
12631.61SkreATF_TC_HEAD(test, tc)							\
12641.61Skre{									\
12651.61Skre	atf_tc_set_md_var(tc, "descr",					\
12661.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
12671.61Skre	    "handled correctly in a child without a signal handler");	\
12681.61Skre}									\
12691.61Skre									\
12701.61SkreATF_TC_BODY(test, tc)							\
12711.61Skre{									\
12721.61Skre									\
12731.61Skre	traceme_sendsignal_simple(sig);					\
12741.35Skamil}
12751.35Skamil
12761.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
12771.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
12781.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
12791.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
12801.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
12811.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
12821.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
12831.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
12841.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
12851.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
12861.35Skamil
12871.35Skamil/// ----------------------------------------------------------------------------
12881.35Skamil
12891.37SkamilATF_TC(traceme_pid1_parent);
12901.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
12911.37Skamil{
12921.37Skamil	atf_tc_set_md_var(tc, "descr",
12931.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
12941.37Skamil}
12951.37Skamil
12961.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
12971.37Skamil{
12981.37Skamil	struct msg_fds parent_child;
12991.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
13001.37Skamil	pid_t child1, child2, wpid;
13011.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13021.37Skamil#if defined(TWAIT_HAVE_STATUS)
13031.37Skamil	int status;
13041.37Skamil#endif
13051.37Skamil
13061.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
13071.37Skamil
13081.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
13091.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
13101.37Skamil	if (child1 == 0) {
13111.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
13121.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
13131.37Skamil		if (child2 != 0) {
13141.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
13151.61Skre			    getpid(), child2);
13161.37Skamil			_exit(exitval_child1);
13171.37Skamil		}
13181.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
13191.37Skamil
13201.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
13211.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
13221.37Skamil
13231.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13241.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
13251.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
13261.37Skamil
13271.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
13281.37Skamil
13291.37Skamil		_exit(exitval_child2);
13301.37Skamil	}
13311.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
13321.37Skamil
13331.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13341.61Skre	TWAIT_REQUIRE_SUCCESS(
13351.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
13361.37Skamil
13371.37Skamil	validate_status_exited(status, exitval_child1);
13381.37Skamil
13391.37Skamil	DPRINTF("Notify that child1 is dead\n");
13401.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
13411.37Skamil
13421.37Skamil	DPRINTF("Wait for exiting of child2\n");
13431.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
13441.37Skamil}
13451.37Skamil
13461.37Skamil/// ----------------------------------------------------------------------------
13471.37Skamil
13481.40Skamilstatic void
13491.40Skamiltraceme_vfork_raise(int sigval)
13501.40Skamil{
13511.46Skamil	const int exitval = 5, exitval_watcher = 10;
13521.46Skamil	pid_t child, parent, watcher, wpid;
13531.46Skamil	int rv;
13541.40Skamil#if defined(TWAIT_HAVE_STATUS)
13551.40Skamil	int status;
13561.85Skamil
13571.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
13581.85Skamil	volatile int expect_core;
13591.85Skamil
13601.85Skamil	switch (sigval) {
13611.85Skamil	case SIGABRT:
13621.85Skamil	case SIGTRAP:
13631.85Skamil	case SIGBUS:
13641.85Skamil	case SIGILL:
13651.85Skamil	case SIGFPE:
13661.85Skamil	case SIGSEGV:
13671.85Skamil		expect_core = 1;
13681.85Skamil		break;
13691.85Skamil	default:
13701.85Skamil		expect_core = 0;
13711.85Skamil		break;
13721.85Skamil	}
13731.40Skamil#endif
13741.40Skamil
13751.46Skamil	/*
13761.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
13771.46Skamil	 * the SIGKILL signal to it.
13781.46Skamil	 *
13791.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
13801.46Skamil	 * simpler to reparent this process to initproc and forget about it.
13811.46Skamil	 */
13821.46Skamil	if (sigval == SIGSTOP) {
13831.46Skamil		parent = getpid();
13841.46Skamil
13851.46Skamil		watcher = fork();
13861.46Skamil		ATF_REQUIRE(watcher != 1);
13871.46Skamil		if (watcher == 0) {
13881.46Skamil			/* Double fork(2) trick to reparent to initproc */
13891.46Skamil			watcher = fork();
13901.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
13911.46Skamil			if (watcher != 0)
13921.46Skamil				_exit(exitval_watcher);
13931.46Skamil
13941.46Skamil			child = await_stopped_child(parent);
13951.46Skamil
13961.46Skamil			errno = 0;
13971.46Skamil			rv = kill(child, SIGKILL);
13981.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
13991.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
14001.46Skamil
14011.46Skamil			/* This exit value will be collected by initproc */
14021.46Skamil			_exit(0);
14031.46Skamil		}
14041.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14051.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
14061.61Skre		    watcher);
14071.46Skamil
14081.46Skamil		validate_status_exited(status, exitval_watcher);
14091.46Skamil
14101.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14111.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
14121.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
14131.46Skamil	}
14141.46Skamil
14151.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
14161.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
14171.40Skamil	if (child == 0) {
14181.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14191.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14201.40Skamil
14211.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14221.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14231.40Skamil
14241.40Skamil		switch (sigval) {
14251.46Skamil		case SIGSTOP:
14261.40Skamil		case SIGKILL:
14271.40Skamil		case SIGABRT:
14281.40Skamil		case SIGHUP:
14291.85Skamil		case SIGTRAP:
14301.85Skamil		case SIGBUS:
14311.85Skamil		case SIGILL:
14321.85Skamil		case SIGFPE:
14331.85Skamil		case SIGSEGV:
14341.40Skamil			/* NOTREACHED */
14351.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
14361.70Smrg			__unreachable();
14371.40Skamil		default:
14381.40Skamil			DPRINTF("Before exiting of the child process\n");
14391.40Skamil			_exit(exitval);
14401.40Skamil		}
14411.40Skamil	}
14421.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14431.40Skamil
14441.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14451.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14461.40Skamil
14471.40Skamil	switch (sigval) {
14481.40Skamil	case SIGKILL:
14491.40Skamil	case SIGABRT:
14501.40Skamil	case SIGHUP:
14511.85Skamil	case SIGTRAP:
14521.85Skamil	case SIGBUS:
14531.85Skamil	case SIGILL:
14541.85Skamil	case SIGFPE:
14551.85Skamil	case SIGSEGV:
14561.40Skamil		validate_status_signaled(status, sigval, expect_core);
14571.40Skamil		break;
14581.40Skamil	case SIGSTOP:
14591.46Skamil		validate_status_signaled(status, SIGKILL, 0);
14601.46Skamil		break;
14611.40Skamil	case SIGCONT:
14621.47Skamil	case SIGTSTP:
14631.47Skamil	case SIGTTIN:
14641.47Skamil	case SIGTTOU:
14651.40Skamil		validate_status_exited(status, exitval);
14661.40Skamil		break;
14671.40Skamil	default:
14681.40Skamil		/* NOTREACHED */
14691.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
14701.40Skamil		break;
14711.40Skamil	}
14721.40Skamil
14731.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14741.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14751.40Skamil}
14761.40Skamil
14771.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
14781.61SkreATF_TC(test);								\
14791.61SkreATF_TC_HEAD(test, tc)							\
14801.61Skre{									\
14811.61Skre	atf_tc_set_md_var(tc, "descr",					\
14821.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
14831.61Skre	    "vfork(2)ed child");					\
14841.61Skre}									\
14851.61Skre									\
14861.61SkreATF_TC_BODY(test, tc)							\
14871.61Skre{									\
14881.61Skre									\
14891.61Skre	traceme_vfork_raise(sig);					\
14901.40Skamil}
14911.40Skamil
14921.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
14931.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
14941.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
14951.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
14961.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
14971.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
14981.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
14991.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
15001.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
15011.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
15021.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
15031.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
15041.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
15051.40Skamil
15061.40Skamil/// ----------------------------------------------------------------------------
15071.40Skamil
15081.52Skamilstatic void
15091.52Skamiltraceme_vfork_crash(int sig)
15101.41Skamil{
15111.41Skamil	pid_t child, wpid;
15121.41Skamil#if defined(TWAIT_HAVE_STATUS)
15131.41Skamil	int status;
15141.41Skamil#endif
15151.41Skamil
15161.71Skamil#ifndef PTRACE_ILLEGAL_ASM
15171.71Skamil	if (sig == SIGILL)
15181.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15191.71Skamil#endif
15201.71Skamil
15211.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
15221.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
15231.41Skamil	if (child == 0) {
15241.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15251.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15261.41Skamil
15271.52Skamil		DPRINTF("Before executing a trap\n");
15281.52Skamil		switch (sig) {
15291.52Skamil		case SIGTRAP:
15301.52Skamil			trigger_trap();
15311.52Skamil			break;
15321.52Skamil		case SIGSEGV:
15331.52Skamil			trigger_segv();
15341.52Skamil			break;
15351.52Skamil		case SIGILL:
15361.52Skamil			trigger_ill();
15371.52Skamil			break;
15381.52Skamil		case SIGFPE:
15391.52Skamil			trigger_fpe();
15401.52Skamil			break;
15411.52Skamil		case SIGBUS:
15421.52Skamil			trigger_bus();
15431.52Skamil			break;
15441.52Skamil		default:
15451.52Skamil			/* NOTREACHED */
15461.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
15471.52Skamil		}
15481.41Skamil
15491.41Skamil		/* NOTREACHED */
15501.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
15511.41Skamil	}
15521.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15531.41Skamil
15541.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15551.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15561.41Skamil
15571.52Skamil	validate_status_signaled(status, sig, 1);
15581.41Skamil
15591.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15601.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15611.41Skamil}
15621.41Skamil
15631.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
15641.61SkreATF_TC(test);								\
15651.61SkreATF_TC_HEAD(test, tc)							\
15661.61Skre{									\
15671.61Skre	atf_tc_set_md_var(tc, "descr",					\
15681.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
15691.61Skre	    "vfork(2)ed child");					\
15701.61Skre}									\
15711.61Skre									\
15721.61SkreATF_TC_BODY(test, tc)							\
15731.61Skre{									\
15741.61Skre									\
15751.61Skre	traceme_vfork_crash(sig);					\
15761.52Skamil}
15771.52Skamil
15781.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
15791.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
15801.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
15811.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
15821.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
15831.52Skamil
15841.41Skamil/// ----------------------------------------------------------------------------
15851.41Skamil
15861.92Skamilstatic void
15871.92Skamiltraceme_vfork_signalmasked_crash(int sig)
15881.92Skamil{
15891.92Skamil	pid_t child, wpid;
15901.92Skamil#if defined(TWAIT_HAVE_STATUS)
15911.92Skamil	int status;
15921.92Skamil#endif
15931.92Skamil	sigset_t intmask;
15941.92Skamil
15951.92Skamil#ifndef PTRACE_ILLEGAL_ASM
15961.92Skamil	if (sig == SIGILL)
15971.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
15981.92Skamil#endif
15991.92Skamil
16001.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16011.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16021.92Skamil	if (child == 0) {
16031.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16041.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16051.92Skamil
16061.92Skamil		sigemptyset(&intmask);
16071.92Skamil		sigaddset(&intmask, sig);
16081.92Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
16091.92Skamil
16101.92Skamil		DPRINTF("Before executing a trap\n");
16111.92Skamil		switch (sig) {
16121.92Skamil		case SIGTRAP:
16131.92Skamil			trigger_trap();
16141.92Skamil			break;
16151.92Skamil		case SIGSEGV:
16161.92Skamil			trigger_segv();
16171.92Skamil			break;
16181.92Skamil		case SIGILL:
16191.92Skamil			trigger_ill();
16201.92Skamil			break;
16211.92Skamil		case SIGFPE:
16221.92Skamil			trigger_fpe();
16231.92Skamil			break;
16241.92Skamil		case SIGBUS:
16251.92Skamil			trigger_bus();
16261.92Skamil			break;
16271.92Skamil		default:
16281.92Skamil			/* NOTREACHED */
16291.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
16301.92Skamil		}
16311.92Skamil
16321.92Skamil		/* NOTREACHED */
16331.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
16341.92Skamil	}
16351.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16361.92Skamil
16371.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16381.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16391.92Skamil
16401.92Skamil	validate_status_signaled(status, sig, 1);
16411.92Skamil
16421.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16431.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16441.92Skamil}
16451.92Skamil
16461.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig)			\
16471.92SkamilATF_TC(test);								\
16481.92SkamilATF_TC_HEAD(test, tc)							\
16491.92Skamil{									\
16501.92Skamil	atf_tc_set_md_var(tc, "descr",					\
16511.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
16521.92Skamil	    "vfork(2)ed child with a masked signal");			\
16531.92Skamil}									\
16541.92Skamil									\
16551.92SkamilATF_TC_BODY(test, tc)							\
16561.92Skamil{									\
16571.92Skamil									\
16581.92Skamil	traceme_vfork_signalmasked_crash(sig);				\
16591.92Skamil}
16601.92Skamil
16611.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP)
16621.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV)
16631.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL)
16641.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE)
16651.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS)
16661.92Skamil
16671.92Skamil/// ----------------------------------------------------------------------------
16681.92Skamil
16691.92Skamilstatic void
16701.92Skamiltraceme_vfork_signalignored_crash(int sig)
16711.92Skamil{
16721.92Skamil	pid_t child, wpid;
16731.92Skamil#if defined(TWAIT_HAVE_STATUS)
16741.92Skamil	int status;
16751.92Skamil#endif
16761.92Skamil	struct sigaction sa;
16771.92Skamil
16781.92Skamil#ifndef PTRACE_ILLEGAL_ASM
16791.92Skamil	if (sig == SIGILL)
16801.92Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
16811.92Skamil#endif
16821.92Skamil
16831.92Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
16841.92Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
16851.92Skamil	if (child == 0) {
16861.92Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16871.92Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16881.92Skamil
16891.92Skamil		memset(&sa, 0, sizeof(sa));
16901.92Skamil		sa.sa_handler = SIG_IGN;
16911.92Skamil		sigemptyset(&sa.sa_mask);
16921.92Skamil
16931.92Skamil		FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
16941.92Skamil
16951.92Skamil		DPRINTF("Before executing a trap\n");
16961.92Skamil		switch (sig) {
16971.92Skamil		case SIGTRAP:
16981.92Skamil			trigger_trap();
16991.92Skamil			break;
17001.92Skamil		case SIGSEGV:
17011.92Skamil			trigger_segv();
17021.92Skamil			break;
17031.92Skamil		case SIGILL:
17041.92Skamil			trigger_ill();
17051.92Skamil			break;
17061.92Skamil		case SIGFPE:
17071.92Skamil			trigger_fpe();
17081.92Skamil			break;
17091.92Skamil		case SIGBUS:
17101.92Skamil			trigger_bus();
17111.92Skamil			break;
17121.92Skamil		default:
17131.92Skamil			/* NOTREACHED */
17141.92Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
17151.92Skamil		}
17161.92Skamil
17171.92Skamil		/* NOTREACHED */
17181.92Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
17191.92Skamil	}
17201.92Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17211.92Skamil
17221.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17231.92Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17241.92Skamil
17251.92Skamil	validate_status_signaled(status, sig, 1);
17261.92Skamil
17271.92Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17281.92Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17291.92Skamil}
17301.92Skamil
17311.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig)			\
17321.92SkamilATF_TC(test);								\
17331.92SkamilATF_TC_HEAD(test, tc)							\
17341.92Skamil{									\
17351.92Skamil	atf_tc_set_md_var(tc, "descr",					\
17361.92Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
17371.92Skamil	    "vfork(2)ed child with ignored signal");			\
17381.92Skamil}									\
17391.92Skamil									\
17401.92SkamilATF_TC_BODY(test, tc)							\
17411.92Skamil{									\
17421.92Skamil									\
17431.92Skamil	traceme_vfork_signalignored_crash(sig);				\
17441.92Skamil}
17451.92Skamil
17461.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap,
17471.92Skamil    SIGTRAP)
17481.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv,
17491.92Skamil    SIGSEGV)
17501.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill,
17511.92Skamil    SIGILL)
17521.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe,
17531.92Skamil    SIGFPE)
17541.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus,
17551.92Skamil    SIGBUS)
17561.92Skamil
17571.92Skamil/// ----------------------------------------------------------------------------
17581.92Skamil
17591.96Skamilstatic void
17601.96Skamiltraceme_vfork_exec(bool masked, bool ignored)
17611.43Skamil{
17621.43Skamil	const int sigval = SIGTRAP;
17631.43Skamil	pid_t child, wpid;
17641.43Skamil#if defined(TWAIT_HAVE_STATUS)
17651.43Skamil	int status;
17661.43Skamil#endif
17671.96Skamil	struct sigaction sa;
17681.61Skre	struct ptrace_siginfo info;
17691.96Skamil	sigset_t intmask;
17701.96Skamil	struct kinfo_proc2 kp;
17711.96Skamil	size_t len = sizeof(kp);
17721.96Skamil
17731.96Skamil	int name[6];
17741.96Skamil	const size_t namelen = __arraycount(name);
17751.96Skamil	ki_sigset_t kp_sigmask;
17761.96Skamil	ki_sigset_t kp_sigignore;
17771.43Skamil
17781.43Skamil	memset(&info, 0, sizeof(info));
17791.43Skamil
17801.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
17811.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
17821.43Skamil	if (child == 0) {
17831.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17841.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17851.43Skamil
17861.96Skamil		if (masked) {
17871.96Skamil			sigemptyset(&intmask);
17881.96Skamil			sigaddset(&intmask, sigval);
17891.96Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
17901.96Skamil		}
17911.96Skamil
17921.96Skamil		if (ignored) {
17931.96Skamil			memset(&sa, 0, sizeof(sa));
17941.96Skamil			sa.sa_handler = SIG_IGN;
17951.96Skamil			sigemptyset(&sa.sa_mask);
17961.96Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
17971.96Skamil		}
17981.96Skamil
17991.43Skamil		DPRINTF("Before calling execve(2) from child\n");
18001.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
18011.43Skamil
18021.43Skamil		/* NOTREACHED */
18031.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
18041.43Skamil	}
18051.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18061.43Skamil
18071.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18081.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18091.43Skamil
18101.43Skamil	validate_status_stopped(status, sigval);
18111.43Skamil
18121.96Skamil	name[0] = CTL_KERN,
18131.96Skamil	name[1] = KERN_PROC2,
18141.96Skamil	name[2] = KERN_PROC_PID;
18151.96Skamil	name[3] = getpid();
18161.96Skamil	name[4] = sizeof(kp);
18171.96Skamil	name[5] = 1;
18181.96Skamil
18191.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18201.96Skamil
18211.96Skamil	if (masked)
18221.96Skamil		kp_sigmask = kp.p_sigmask;
18231.96Skamil
18241.96Skamil	if (ignored)
18251.96Skamil		kp_sigignore = kp.p_sigignore;
18261.96Skamil
18271.96Skamil	name[3] = getpid();
18281.96Skamil
18291.96Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18301.96Skamil
18311.96Skamil	if (masked) {
18321.96Skamil		DPRINTF("kp_sigmask="
18331.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18341.96Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
18351.96Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
18361.96Skamil
18371.96Skamil	        DPRINTF("kp.p_sigmask="
18381.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18391.96Skamil	            kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
18401.96Skamil	            kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
18411.96Skamil
18421.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
18431.96Skamil		    sizeof(kp_sigmask)));
18441.96Skamil	}
18451.96Skamil
18461.96Skamil	if (ignored) {
18471.96Skamil		DPRINTF("kp_sigignore="
18481.96Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18491.96Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
18501.96Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
18511.96Skamil
18521.96Skamil	        DPRINTF("kp.p_sigignore="
18531.96Skamil	            "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
18541.96Skamil	            kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
18551.96Skamil	            kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
18561.96Skamil
18571.96Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
18581.96Skamil		    sizeof(kp_sigignore)));
18591.96Skamil	}
18601.96Skamil
18611.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
18621.61Skre	SYSCALL_REQUIRE(
18631.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
18641.43Skamil
18651.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
18661.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
18671.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
18681.43Skamil	    info.psi_siginfo.si_errno);
18691.43Skamil
18701.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
18711.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
18721.43Skamil
18731.43Skamil	DPRINTF("Before resuming the child process where it left off and "
18741.43Skamil	    "without signal to be sent\n");
18751.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18761.43Skamil
18771.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18781.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18791.43Skamil
18801.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18811.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18821.43Skamil}
18831.43Skamil
18841.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored)			\
18851.96SkamilATF_TC(test);								\
18861.96SkamilATF_TC_HEAD(test, tc)							\
18871.96Skamil{									\
18881.96Skamil	atf_tc_set_md_var(tc, "descr",					\
18891.96Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed "	\
18901.96Skamil	    "child%s%s", masked ? " with masked signal" : "",		\
18911.96Skamil	    masked ? " with ignored signal" : "");			\
18921.96Skamil}									\
18931.96Skamil									\
18941.96SkamilATF_TC_BODY(test, tc)							\
18951.96Skamil{									\
18961.96Skamil									\
18971.96Skamil	traceme_vfork_exec(masked, ignored);				\
18981.96Skamil}
18991.96Skamil
19001.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false)
19011.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false)
19021.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true)
19031.96Skamil
19041.43Skamil/// ----------------------------------------------------------------------------
19051.43Skamil
19061.1Skamil#if defined(TWAIT_HAVE_PID)
19071.51Skamilstatic void
19081.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored)
19091.59Skamil{
19101.94Skamil	const int sigval = SIGSTOP;
19111.59Skamil	struct msg_fds parent_tracee, parent_tracer;
19121.59Skamil	const int exitval = 10;
19131.59Skamil	pid_t tracee, tracer, wpid;
19141.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19151.59Skamil#if defined(TWAIT_HAVE_STATUS)
19161.59Skamil	int status;
19171.59Skamil#endif
19181.94Skamil	struct sigaction sa;
19191.59Skamil	struct ptrace_siginfo info;
19201.94Skamil	sigset_t intmask;
19211.94Skamil	struct kinfo_proc2 kp;
19221.94Skamil	size_t len = sizeof(kp);
19231.94Skamil
19241.94Skamil	int name[6];
19251.94Skamil	const size_t namelen = __arraycount(name);
19261.94Skamil	ki_sigset_t kp_sigmask;
19271.94Skamil	ki_sigset_t kp_sigignore;
19281.61Skre
19291.71Skamil#ifndef PTRACE_ILLEGAL_ASM
19301.71Skamil	if (sig == SIGILL)
19311.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
19321.71Skamil#endif
19331.71Skamil
19341.59Skamil	memset(&info, 0, sizeof(info));
19351.59Skamil
19361.59Skamil	DPRINTF("Spawn tracee\n");
19371.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19381.59Skamil	tracee = atf_utils_fork();
19391.59Skamil	if (tracee == 0) {
19401.59Skamil		// Wait for parent to let us crash
19411.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19421.61Skre
19431.94Skamil		if (masked) {
19441.94Skamil			sigemptyset(&intmask);
19451.94Skamil			sigaddset(&intmask, sig);
19461.94Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
19471.94Skamil		}
19481.94Skamil
19491.94Skamil		if (ignored) {
19501.94Skamil			memset(&sa, 0, sizeof(sa));
19511.94Skamil			sa.sa_handler = SIG_IGN;
19521.94Skamil			sigemptyset(&sa.sa_mask);
19531.94Skamil			FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1);
19541.94Skamil		}
19551.94Skamil
19561.94Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19571.94Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19581.94Skamil
19591.59Skamil		DPRINTF("Before executing a trap\n");
19601.59Skamil		switch (sig) {
19611.59Skamil		case SIGTRAP:
19621.59Skamil			trigger_trap();
19631.59Skamil			break;
19641.59Skamil		case SIGSEGV:
19651.59Skamil			trigger_segv();
19661.59Skamil			break;
19671.59Skamil		case SIGILL:
19681.59Skamil			trigger_ill();
19691.59Skamil			break;
19701.59Skamil		case SIGFPE:
19711.59Skamil			trigger_fpe();
19721.59Skamil			break;
19731.59Skamil		case SIGBUS:
19741.59Skamil			trigger_bus();
19751.59Skamil			break;
19761.59Skamil		default:
19771.59Skamil			/* NOTREACHED */
19781.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
19791.59Skamil		}
19801.59Skamil
19811.59Skamil		/* NOTREACHED */
19821.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
19831.59Skamil	}
19841.59Skamil
19851.59Skamil	DPRINTF("Spawn debugger\n");
19861.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
19871.59Skamil	tracer = atf_utils_fork();
19881.59Skamil	if (tracer == 0) {
19891.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
19901.59Skamil		tracer = atf_utils_fork();
19911.59Skamil		if (tracer != 0)
19921.61Skre			_exit(exitval);
19931.59Skamil
19941.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
19951.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
19961.59Skamil
19971.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
19981.59Skamil		FORKEE_REQUIRE_SUCCESS(
19991.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20001.59Skamil
20011.59Skamil		forkee_status_stopped(status, SIGSTOP);
20021.59Skamil
20031.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20041.94Skamil		    "traced process\n");
20051.94Skamil		SYSCALL_REQUIRE(
20061.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20071.94Skamil
20081.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20091.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20101.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20111.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20121.94Skamil
20131.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
20141.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
20151.94Skamil
20161.59Skamil		/* Resume tracee with PT_CONTINUE */
20171.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20181.59Skamil
20191.59Skamil		/* Inform parent that tracer has attached to tracee */
20201.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
20211.59Skamil
20221.59Skamil		/* Wait for parent to tell use that tracee should have exited */
20231.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
20241.59Skamil
20251.59Skamil		/* Wait for tracee and assert that it exited */
20261.59Skamil		FORKEE_REQUIRE_SUCCESS(
20271.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20281.59Skamil
20291.94Skamil		forkee_status_stopped(status, sigval);
20301.94Skamil
20311.94Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20321.94Skamil		    "traced process\n");
20331.94Skamil		SYSCALL_REQUIRE(
20341.94Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20351.94Skamil
20361.94Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20371.94Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20381.94Skamil		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20391.94Skamil		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20401.94Skamil
20411.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
20421.94Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
20431.94Skamil
20441.94Skamil		name[0] = CTL_KERN,
20451.94Skamil		name[1] = KERN_PROC2,
20461.94Skamil		name[2] = KERN_PROC_PID;
20471.94Skamil		name[3] = tracee;
20481.94Skamil		name[4] = sizeof(kp);
20491.94Skamil		name[5] = 1;
20501.94Skamil
20511.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20521.94Skamil
20531.94Skamil		if (masked)
20541.94Skamil			kp_sigmask = kp.p_sigmask;
20551.94Skamil
20561.94Skamil		if (ignored)
20571.94Skamil			kp_sigignore = kp.p_sigignore;
20581.94Skamil
20591.94Skamil		/* Resume tracee with PT_CONTINUE */
20601.94Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
20611.94Skamil
20621.94Skamil		/* Wait for tracee and assert that it exited */
20631.94Skamil		FORKEE_REQUIRE_SUCCESS(
20641.94Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
20651.94Skamil
20661.93Skamil		forkee_status_stopped(status, sig);
20671.59Skamil
20681.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
20691.61Skre		    "traced process\n");
20701.61Skre		SYSCALL_REQUIRE(
20711.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
20721.59Skamil
20731.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
20741.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
20751.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
20761.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
20771.59Skamil
20781.93Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig);
20791.94Skamil
20801.94Skamil		FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
20811.94Skamil
20821.94Skamil		if (masked) {
20831.94Skamil			DPRINTF("kp_sigmask="
20841.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
20851.94Skamil			    PRIx32 "\n",
20861.94Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
20871.94Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
20881.94Skamil
20891.94Skamil			DPRINTF("kp.p_sigmask="
20901.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
20911.94Skamil			    PRIx32 "\n",
20921.94Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
20931.94Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
20941.94Skamil
20951.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask,
20961.94Skamil			    sizeof(kp_sigmask)));
20971.94Skamil		}
20981.94Skamil
20991.94Skamil		if (ignored) {
21001.94Skamil			DPRINTF("kp_sigignore="
21011.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21021.94Skamil			    PRIx32 "\n",
21031.94Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
21041.94Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
21051.94Skamil
21061.94Skamil			DPRINTF("kp.p_sigignore="
21071.94Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
21081.94Skamil			    PRIx32 "\n",
21091.94Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
21101.94Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
21111.94Skamil
21121.94Skamil			FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore,
21131.94Skamil			    sizeof(kp_sigignore)));
21141.94Skamil		}
21151.94Skamil
21161.59Skamil		switch (sig) {
21171.59Skamil		case SIGTRAP:
21181.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
21191.59Skamil			break;
21201.59Skamil		case SIGSEGV:
21211.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
21221.59Skamil			break;
21231.71Skamil		case SIGILL:
21241.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
21251.71Skamil			break;
21261.59Skamil		case SIGFPE:
21271.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
21281.59Skamil			break;
21291.59Skamil		case SIGBUS:
21301.93Skamil			FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
21311.59Skamil			break;
21321.59Skamil		}
21331.59Skamil
21341.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
21351.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
21361.93Skamil		FORKEE_REQUIRE_SUCCESS(
21371.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21381.59Skamil
21391.93Skamil		forkee_status_signaled(status, SIGKILL, 0);
21401.59Skamil
21411.71Skamil		/* Inform parent that tracer is exiting normally */
21421.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
21431.71Skamil
21441.59Skamil		DPRINTF("Before exiting of the tracer process\n");
21451.59Skamil		_exit(0 /* collect by initproc */);
21461.59Skamil	}
21471.59Skamil
21481.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
21491.59Skamil	    "calling %s()\n", TWAIT_FNAME);
21501.59Skamil	TWAIT_REQUIRE_SUCCESS(
21511.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
21521.59Skamil
21531.59Skamil	validate_status_exited(status, exitval);
21541.59Skamil
21551.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
21561.59Skamil	    TWAIT_FNAME);
21571.59Skamil	TWAIT_REQUIRE_SUCCESS(
21581.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
21591.59Skamil
21601.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
21611.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
21621.59Skamil
21631.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
21641.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
21651.59Skamil
21661.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
21671.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
21681.59Skamil
21691.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
21701.59Skamil	    TWAIT_FNAME);
21711.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
21721.59Skamil
21731.59Skamil	validate_status_signaled(status, SIGKILL, 0);
21741.59Skamil
21751.71Skamil	DPRINTF("Await normal exit of tracer\n");
21761.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
21771.71Skamil
21781.59Skamil	msg_close(&parent_tracer);
21791.59Skamil	msg_close(&parent_tracee);
21801.59Skamil}
21811.59Skamil
21821.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
21831.61SkreATF_TC(test);								\
21841.61SkreATF_TC_HEAD(test, tc)							\
21851.61Skre{									\
21861.61Skre	atf_tc_set_md_var(tc, "descr",					\
21871.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
21881.94Skamil	    "the debuggee");						\
21891.61Skre}									\
21901.61Skre									\
21911.61SkreATF_TC_BODY(test, tc)							\
21921.61Skre{									\
21931.61Skre									\
21941.94Skamil	unrelated_tracer_sees_crash(sig, false, false);			\
21951.59Skamil}
21961.59Skamil
21971.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
21981.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
21991.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
22001.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
22011.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
22021.94Skamil
22031.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig)		\
22041.94SkamilATF_TC(test);								\
22051.94SkamilATF_TC_HEAD(test, tc)							\
22061.94Skamil{									\
22071.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22081.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22091.94Skamil	    "the debuggee with masked signal");				\
22101.94Skamil}									\
22111.94Skamil									\
22121.94SkamilATF_TC_BODY(test, tc)							\
22131.94Skamil{									\
22141.94Skamil									\
22151.94Skamil	unrelated_tracer_sees_crash(sig, true, false);			\
22161.94Skamil}
22171.94Skamil
22181.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22191.94Skamil    unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP)
22201.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22211.94Skamil    unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV)
22221.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22231.94Skamil    unrelated_tracer_sees_signalmasked_crash_ill, SIGILL)
22241.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22251.94Skamil    unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE)
22261.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(
22271.94Skamil    unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS)
22281.94Skamil
22291.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig)		\
22301.94SkamilATF_TC(test);								\
22311.94SkamilATF_TC_HEAD(test, tc)							\
22321.94Skamil{									\
22331.94Skamil	atf_tc_set_md_var(tc, "descr",					\
22341.94Skamil	    "Assert that an unrelated tracer sees crash signal from "	\
22351.94Skamil	    "the debuggee with signal ignored");			\
22361.94Skamil}									\
22371.94Skamil									\
22381.94SkamilATF_TC_BODY(test, tc)							\
22391.94Skamil{									\
22401.94Skamil									\
22411.94Skamil	unrelated_tracer_sees_crash(sig, false, true);			\
22421.94Skamil}
22431.94Skamil
22441.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22451.94Skamil    unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP)
22461.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22471.94Skamil    unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV)
22481.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22491.94Skamil    unrelated_tracer_sees_signalignored_crash_ill, SIGILL)
22501.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22511.94Skamil    unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE)
22521.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(
22531.94Skamil    unrelated_tracer_sees_signalignored_crash_bus, SIGBUS)
22541.59Skamil#endif
22551.59Skamil
22561.59Skamil/// ----------------------------------------------------------------------------
22571.59Skamil
22581.59Skamil#if defined(TWAIT_HAVE_PID)
22591.59Skamilstatic void
22601.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
22611.67Skamil                                             bool stopped)
22621.1Skamil{
22631.51Skamil	/*
22641.51Skamil	 * notimeout - disable timeout in await zombie function
22651.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
22661.67Skamil	 * stopped - attach to a stopped process
22671.51Skamil	 */
22681.1Skamil
22691.1Skamil	struct msg_fds parent_tracee, parent_tracer;
22701.1Skamil	const int exitval_tracee = 5;
22711.1Skamil	const int exitval_tracer = 10;
22721.1Skamil	pid_t tracee, tracer, wpid;
22731.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
22741.1Skamil#if defined(TWAIT_HAVE_STATUS)
22751.1Skamil	int status;
22761.1Skamil#endif
22771.1Skamil
22781.67Skamil	/*
22791.67Skamil	 * Only a subset of options are supported.
22801.67Skamil	 */
22811.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
22821.67Skamil	            (!notimeout && unrelated && !stopped) ||
22831.67Skamil	            (notimeout && !unrelated && !stopped) ||
22841.67Skamil	            (!notimeout && unrelated && stopped));
22851.67Skamil
22861.13Schristos	DPRINTF("Spawn tracee\n");
22871.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
22881.1Skamil	tracee = atf_utils_fork();
22891.1Skamil	if (tracee == 0) {
22901.67Skamil		if (stopped) {
22911.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
22921.67Skamil			raise(SIGSTOP);
22931.67Skamil		}
22941.67Skamil
22951.1Skamil		// Wait for parent to let us exit
22961.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
22971.1Skamil		_exit(exitval_tracee);
22981.1Skamil	}
22991.1Skamil
23001.13Schristos	DPRINTF("Spawn debugger\n");
23011.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
23021.1Skamil	tracer = atf_utils_fork();
23031.1Skamil	if (tracer == 0) {
23041.51Skamil		if(unrelated) {
23051.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
23061.51Skamil			tracer = atf_utils_fork();
23071.51Skamil			if (tracer != 0)
23081.51Skamil				_exit(exitval_tracer);
23091.51Skamil		}
23101.51Skamil
23111.67Skamil		if (stopped) {
23121.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
23131.67Skamil			await_stopped(tracee);
23141.67Skamil		}
23151.67Skamil
23161.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
23171.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
23181.1Skamil
23191.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
23201.1Skamil		FORKEE_REQUIRE_SUCCESS(
23211.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23221.1Skamil
23231.1Skamil		forkee_status_stopped(status, SIGSTOP);
23241.1Skamil
23251.1Skamil		/* Resume tracee with PT_CONTINUE */
23261.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
23271.1Skamil
23281.1Skamil		/* Inform parent that tracer has attached to tracee */
23291.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
23301.1Skamil
23311.1Skamil		/* Wait for parent to tell use that tracee should have exited */
23321.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
23331.1Skamil
23341.1Skamil		/* Wait for tracee and assert that it exited */
23351.1Skamil		FORKEE_REQUIRE_SUCCESS(
23361.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23371.1Skamil
23381.1Skamil		forkee_status_exited(status, exitval_tracee);
23391.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
23401.1Skamil
23411.13Schristos		DPRINTF("Before exiting of the tracer process\n");
23421.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
23431.51Skamil	}
23441.51Skamil
23451.51Skamil	if (unrelated) {
23461.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
23471.51Skamil		    "calling %s()\n", TWAIT_FNAME);
23481.51Skamil		TWAIT_REQUIRE_SUCCESS(
23491.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
23501.51Skamil
23511.51Skamil		validate_status_exited(status, exitval_tracer);
23521.51Skamil
23531.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
23541.51Skamil		    TWAIT_FNAME);
23551.51Skamil		TWAIT_REQUIRE_SUCCESS(
23561.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
23571.1Skamil	}
23581.1Skamil
23591.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
23601.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
23611.1Skamil
23621.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
23631.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
23641.1Skamil
23651.13Schristos	DPRINTF("Detect that tracee is zombie\n");
23661.51Skamil	if (notimeout)
23671.26Skamil		await_zombie_raw(tracee, 0);
23681.26Skamil	else
23691.26Skamil		await_zombie(tracee);
23701.1Skamil
23711.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
23721.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
23731.1Skamil	    TWAIT_FNAME);
23741.1Skamil	TWAIT_REQUIRE_SUCCESS(
23751.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
23761.1Skamil
23771.51Skamil	if (unrelated) {
23781.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
23791.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
23801.51Skamil	} else {
23811.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
23821.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
23831.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
23841.59Skamil			"%s()\n", TWAIT_FNAME);
23851.51Skamil
23861.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
23871.59Skamil			"tracee\n");
23881.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
23891.51Skamil		    tracer);
23901.1Skamil
23911.51Skamil		validate_status_exited(status, exitval_tracer);
23921.51Skamil	}
23931.1Skamil
23941.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
23951.1Skamil	    TWAIT_FNAME);
23961.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
23971.1Skamil
23981.1Skamil	validate_status_exited(status, exitval_tracee);
23991.1Skamil
24001.1Skamil	msg_close(&parent_tracer);
24011.1Skamil	msg_close(&parent_tracee);
24021.1Skamil}
24031.26Skamil
24041.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
24051.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
24061.51Skamil{
24071.51Skamil	atf_tc_set_md_var(tc, "descr",
24081.51Skamil	    "Assert that tracer sees process termination before the parent");
24091.51Skamil}
24101.51Skamil
24111.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
24121.26Skamil{
24131.26Skamil
24141.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
24151.26Skamil}
24161.26Skamil
24171.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
24181.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
24191.1Skamil{
24201.1Skamil	atf_tc_set_md_var(tc, "descr",
24211.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
24221.51Skamil	    "process and no other error is reported");
24231.1Skamil}
24241.1Skamil
24251.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
24261.1Skamil{
24271.51Skamil	time_t start, end;
24281.51Skamil	double diff;
24291.51Skamil	unsigned long N = 0;
24301.1Skamil
24311.51Skamil	/*
24321.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
24331.51Skamil	 * This test body isn't specific to this race, however it's just good
24341.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
24351.51Skamil	 */
24361.1Skamil
24371.51Skamil	start = time(NULL);
24381.51Skamil	while (true) {
24391.51Skamil		DPRINTF("Step: %lu\n", N);
24401.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
24411.67Skamil		                                             false);
24421.51Skamil		end = time(NULL);
24431.51Skamil		diff = difftime(end, start);
24441.51Skamil		if (diff >= 5.0)
24451.51Skamil			break;
24461.51Skamil		++N;
24471.1Skamil	}
24481.51Skamil	DPRINTF("Iterations: %lu\n", N);
24491.51Skamil}
24501.1Skamil
24511.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
24521.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24531.51Skamil{
24541.51Skamil	atf_tc_set_md_var(tc, "descr",
24551.51Skamil	    "Assert that tracer sees process termination before the parent");
24561.51Skamil}
24571.1Skamil
24581.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
24591.51Skamil{
24601.1Skamil
24611.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
24621.67Skamil}
24631.67Skamil
24641.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
24651.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
24661.67Skamil{
24671.67Skamil	atf_tc_set_md_var(tc, "descr",
24681.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
24691.67Skamil}
24701.67Skamil
24711.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
24721.67Skamil{
24731.67Skamil
24741.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
24751.1Skamil}
24761.1Skamil#endif
24771.1Skamil
24781.51Skamil/// ----------------------------------------------------------------------------
24791.51Skamil
24801.66Skamilstatic void
24811.66Skamilparent_attach_to_its_child(bool stopped)
24821.1Skamil{
24831.1Skamil	struct msg_fds parent_tracee;
24841.1Skamil	const int exitval_tracee = 5;
24851.1Skamil	pid_t tracee, wpid;
24861.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
24871.1Skamil#if defined(TWAIT_HAVE_STATUS)
24881.1Skamil	int status;
24891.1Skamil#endif
24901.1Skamil
24911.13Schristos	DPRINTF("Spawn tracee\n");
24921.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
24931.1Skamil	tracee = atf_utils_fork();
24941.1Skamil	if (tracee == 0) {
24951.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
24961.13Schristos		DPRINTF("Parent should now attach to tracee\n");
24971.1Skamil
24981.66Skamil		if (stopped) {
24991.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
25001.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
25011.66Skamil		}
25021.66Skamil
25031.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
25041.1Skamil		/* Wait for message from the parent */
25051.1Skamil		_exit(exitval_tracee);
25061.1Skamil	}
25071.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
25081.57Skamil
25091.66Skamil	if (stopped) {
25101.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
25111.66Skamil		await_stopped(tracee);
25121.66Skamil	}
25131.66Skamil
25141.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
25151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
25161.1Skamil
25171.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
25181.1Skamil	    TWAIT_FNAME);
25191.1Skamil	TWAIT_REQUIRE_SUCCESS(
25201.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25211.1Skamil
25221.1Skamil	validate_status_stopped(status, SIGSTOP);
25231.1Skamil
25241.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
25251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
25261.1Skamil
25271.13Schristos	DPRINTF("Let the tracee exit now\n");
25281.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
25291.1Skamil
25301.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
25311.1Skamil	TWAIT_REQUIRE_SUCCESS(
25321.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
25331.1Skamil
25341.1Skamil	validate_status_exited(status, exitval_tracee);
25351.1Skamil
25361.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
25371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
25381.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
25391.1Skamil
25401.1Skamil	msg_close(&parent_tracee);
25411.1Skamil}
25421.1Skamil
25431.66SkamilATF_TC(parent_attach_to_its_child);
25441.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
25451.66Skamil{
25461.66Skamil	atf_tc_set_md_var(tc, "descr",
25471.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
25481.66Skamil}
25491.66Skamil
25501.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
25511.66Skamil{
25521.66Skamil
25531.66Skamil	parent_attach_to_its_child(false);
25541.66Skamil}
25551.66Skamil
25561.66SkamilATF_TC(parent_attach_to_its_stopped_child);
25571.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
25581.66Skamil{
25591.66Skamil	atf_tc_set_md_var(tc, "descr",
25601.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
25611.66Skamil}
25621.66Skamil
25631.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
25641.66Skamil{
25651.66Skamil
25661.66Skamil	parent_attach_to_its_child(true);
25671.66Skamil}
25681.66Skamil
25691.51Skamil/// ----------------------------------------------------------------------------
25701.51Skamil
25711.65Skamilstatic void
25721.65Skamilchild_attach_to_its_parent(bool stopped)
25731.1Skamil{
25741.1Skamil	struct msg_fds parent_tracee;
25751.1Skamil	const int exitval_tracer = 5;
25761.1Skamil	pid_t tracer, wpid;
25771.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
25781.1Skamil#if defined(TWAIT_HAVE_STATUS)
25791.1Skamil	int status;
25801.1Skamil#endif
25811.1Skamil
25821.13Schristos	DPRINTF("Spawn tracer\n");
25831.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
25841.1Skamil	tracer = atf_utils_fork();
25851.1Skamil	if (tracer == 0) {
25861.1Skamil		/* Wait for message from the parent */
25871.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
25881.1Skamil
25891.65Skamil		if (stopped) {
25901.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
25911.65Skamil			        getppid());
25921.65Skamil			await_stopped(getppid());
25931.65Skamil		}
25941.65Skamil
25951.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
25961.1Skamil		    getppid());
25971.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
25981.1Skamil
25991.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
26001.1Skamil		    TWAIT_FNAME);
26011.1Skamil		FORKEE_REQUIRE_SUCCESS(
26021.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
26031.1Skamil
26041.1Skamil		forkee_status_stopped(status, SIGSTOP);
26051.1Skamil
26061.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
26071.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
26081.1Skamil		    != -1);
26091.1Skamil
26101.1Skamil		/* Tell parent we are ready */
26111.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
26121.1Skamil
26131.1Skamil		_exit(exitval_tracer);
26141.1Skamil	}
26151.1Skamil
26161.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
26171.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
26181.65Skamil
26191.65Skamil	if (stopped) {
26201.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
26211.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
26221.65Skamil	}
26231.65Skamil
26241.13Schristos	DPRINTF("Allow the tracer to exit now\n");
26251.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
26261.1Skamil
26271.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
26281.1Skamil	TWAIT_REQUIRE_SUCCESS(
26291.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
26301.1Skamil
26311.1Skamil	validate_status_exited(status, exitval_tracer);
26321.1Skamil
26331.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
26341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
26351.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
26361.1Skamil
26371.1Skamil	msg_close(&parent_tracee);
26381.1Skamil}
26391.1Skamil
26401.65SkamilATF_TC(child_attach_to_its_parent);
26411.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
26421.65Skamil{
26431.65Skamil	atf_tc_set_md_var(tc, "descr",
26441.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
26451.65Skamil}
26461.65Skamil
26471.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
26481.65Skamil{
26491.65Skamil
26501.65Skamil	child_attach_to_its_parent(false);
26511.65Skamil}
26521.65Skamil
26531.65SkamilATF_TC(child_attach_to_its_stopped_parent);
26541.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
26551.65Skamil{
26561.65Skamil	atf_tc_set_md_var(tc, "descr",
26571.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
26581.65Skamil}
26591.65Skamil
26601.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
26611.65Skamil{
26621.65Skamil	/*
26631.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
26641.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
26651.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
26661.65Skamil	 *
26671.65Skamil	 * As a workaround spawn this test as a subprocess.
26681.65Skamil	 */
26691.65Skamil
26701.65Skamil	const int exitval = 15;
26711.65Skamil	pid_t child, wpid;
26721.65Skamil#if defined(TWAIT_HAVE_STATUS)
26731.65Skamil	int status;
26741.65Skamil#endif
26751.65Skamil
26761.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
26771.65Skamil	if (child == 0) {
26781.65Skamil		child_attach_to_its_parent(true);
26791.65Skamil		_exit(exitval);
26801.65Skamil	} else {
26811.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26821.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26831.65Skamil
26841.65Skamil		validate_status_exited(status, exitval);
26851.65Skamil
26861.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
26871.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26881.65Skamil	}
26891.65Skamil}
26901.65Skamil
26911.51Skamil/// ----------------------------------------------------------------------------
26921.51Skamil
26931.1Skamil#if defined(TWAIT_HAVE_PID)
26941.1Skamil
26951.51Skamilenum tracee_sees_its_original_parent_type {
26961.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
26971.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
26981.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
26991.51Skamil};
27001.51Skamil
27011.51Skamilstatic void
27021.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
27031.1Skamil{
27041.1Skamil	struct msg_fds parent_tracer, parent_tracee;
27051.1Skamil	const int exitval_tracee = 5;
27061.1Skamil	const int exitval_tracer = 10;
27071.1Skamil	pid_t parent, tracee, tracer, wpid;
27081.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
27091.1Skamil#if defined(TWAIT_HAVE_STATUS)
27101.1Skamil	int status;
27111.1Skamil#endif
27121.51Skamil	/* sysctl(3) - kinfo_proc2 */
27131.51Skamil	int name[CTL_MAXNAME];
27141.51Skamil	struct kinfo_proc2 kp;
27151.51Skamil	size_t len = sizeof(kp);
27161.51Skamil	unsigned int namelen;
27171.51Skamil
27181.51Skamil	/* procfs - status  */
27191.51Skamil	FILE *fp;
27201.51Skamil	struct stat st;
27211.51Skamil	const char *fname = "/proc/curproc/status";
27221.51Skamil	char s_executable[MAXPATHLEN];
27231.51Skamil	int s_pid, s_ppid;
27241.51Skamil	int rv;
27251.51Skamil
27261.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
27271.61Skre		SYSCALL_REQUIRE(
27281.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
27291.61Skre		if (rv != 0)
27301.51Skamil			atf_tc_skip("/proc/curproc/status not found");
27311.51Skamil	}
27321.1Skamil
27331.13Schristos	DPRINTF("Spawn tracee\n");
27341.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
27351.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
27361.1Skamil	tracee = atf_utils_fork();
27371.1Skamil	if (tracee == 0) {
27381.1Skamil		parent = getppid();
27391.1Skamil
27401.1Skamil		/* Emit message to the parent */
27411.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
27421.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
27431.1Skamil
27441.51Skamil		switch (type) {
27451.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
27461.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
27471.51Skamil			break;
27481.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
27491.51Skamil			namelen = 0;
27501.51Skamil			name[namelen++] = CTL_KERN;
27511.51Skamil			name[namelen++] = KERN_PROC2;
27521.51Skamil			name[namelen++] = KERN_PROC_PID;
27531.51Skamil			name[namelen++] = getpid();
27541.51Skamil			name[namelen++] = len;
27551.51Skamil			name[namelen++] = 1;
27561.51Skamil
27571.61Skre			FORKEE_ASSERT_EQ(
27581.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
27591.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
27601.51Skamil			break;
27611.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
27621.51Skamil			/*
27631.51Skamil			 * Format:
27641.51Skamil			 *  EXECUTABLE PID PPID ...
27651.51Skamil			 */
27661.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
27671.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
27681.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
27691.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
27701.51Skamil			break;
27711.51Skamil		}
27721.1Skamil
27731.1Skamil		_exit(exitval_tracee);
27741.1Skamil	}
27751.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
27761.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
27771.1Skamil
27781.13Schristos	DPRINTF("Spawn debugger\n");
27791.1Skamil	tracer = atf_utils_fork();
27801.1Skamil	if (tracer == 0) {
27811.1Skamil		/* No IPC to communicate with the child */
27821.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
27831.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
27841.1Skamil
27851.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
27861.1Skamil		FORKEE_REQUIRE_SUCCESS(
27871.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
27881.1Skamil
27891.1Skamil		forkee_status_stopped(status, SIGSTOP);
27901.1Skamil
27911.1Skamil		/* Resume tracee with PT_CONTINUE */
27921.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
27931.1Skamil
27941.1Skamil		/* Inform parent that tracer has attached to tracee */
27951.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
27961.1Skamil
27971.1Skamil		/* Wait for parent to tell use that tracee should have exited */
27981.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
27991.1Skamil
28001.1Skamil		/* Wait for tracee and assert that it exited */
28011.1Skamil		FORKEE_REQUIRE_SUCCESS(
28021.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
28031.1Skamil
28041.1Skamil		forkee_status_exited(status, exitval_tracee);
28051.1Skamil
28061.13Schristos		DPRINTF("Before exiting of the tracer process\n");
28071.1Skamil		_exit(exitval_tracer);
28081.1Skamil	}
28091.1Skamil
28101.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
28111.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
28121.1Skamil
28131.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
28141.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
28151.1Skamil
28161.13Schristos	DPRINTF("Detect that tracee is zombie\n");
28171.1Skamil	await_zombie(tracee);
28181.1Skamil
28191.13Schristos	DPRINTF("Assert that there is no status about tracee - "
28201.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
28211.1Skamil	TWAIT_REQUIRE_SUCCESS(
28221.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
28231.1Skamil
28241.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
28251.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
28261.1Skamil
28271.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
28281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
28291.1Skamil	    tracer);
28301.1Skamil
28311.1Skamil	validate_status_exited(status, exitval_tracer);
28321.1Skamil
28331.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
28341.1Skamil	    TWAIT_FNAME);
28351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
28361.1Skamil	    tracee);
28371.1Skamil
28381.1Skamil	validate_status_exited(status, exitval_tracee);
28391.1Skamil
28401.1Skamil	msg_close(&parent_tracer);
28411.1Skamil	msg_close(&parent_tracee);
28421.1Skamil}
28431.1Skamil
28441.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
28451.61SkreATF_TC(test);								\
28461.61SkreATF_TC_HEAD(test, tc)							\
28471.61Skre{									\
28481.61Skre	atf_tc_set_md_var(tc, "descr",					\
28491.61Skre	    "Assert that tracee sees its original parent when being traced " \
28501.61Skre	    "(check " descr ")");					\
28511.61Skre}									\
28521.61Skre									\
28531.61SkreATF_TC_BODY(test, tc)							\
28541.61Skre{									\
28551.61Skre									\
28561.61Skre	tracee_sees_its_original_parent(type);				\
28571.1Skamil}
28581.1Skamil
28591.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28601.51Skamil	tracee_sees_its_original_parent_getppid,
28611.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
28621.51Skamil	"getppid(2)");
28631.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28641.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
28651.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
28661.51Skamil	"sysctl(3) and kinfo_proc2");
28671.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
28681.51Skamil	tracee_sees_its_original_parent_procfs_status,
28691.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
28701.51Skamil	"the status file in procfs");
28711.1Skamil#endif
28721.1Skamil
28731.51Skamil/// ----------------------------------------------------------------------------
28741.1Skamil
28751.53Skamilstatic void
28761.53Skamileventmask_preserved(int event)
28771.1Skamil{
28781.1Skamil	const int exitval = 5;
28791.1Skamil	const int sigval = SIGSTOP;
28801.1Skamil	pid_t child, wpid;
28811.1Skamil#if defined(TWAIT_HAVE_STATUS)
28821.1Skamil	int status;
28831.1Skamil#endif
28841.1Skamil	ptrace_event_t set_event, get_event;
28851.1Skamil	const int len = sizeof(ptrace_event_t);
28861.1Skamil
28871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28891.1Skamil	if (child == 0) {
28901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28921.1Skamil
28931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28951.1Skamil
28961.13Schristos		DPRINTF("Before exiting of the child process\n");
28971.1Skamil		_exit(exitval);
28981.1Skamil	}
28991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29001.1Skamil
29011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29031.1Skamil
29041.1Skamil	validate_status_stopped(status, sigval);
29051.1Skamil
29061.53Skamil	set_event.pe_set_event = event;
29071.61Skre	SYSCALL_REQUIRE(
29081.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
29091.61Skre	SYSCALL_REQUIRE(
29101.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
29111.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
29121.1Skamil
29131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29141.1Skamil	    "without signal to be sent\n");
29151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29161.1Skamil
29171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29191.1Skamil
29201.1Skamil	validate_status_exited(status, exitval);
29211.1Skamil
29221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29241.1Skamil}
29251.1Skamil
29261.61Skre#define EVENTMASK_PRESERVED(test, event)				\
29271.61SkreATF_TC(test);								\
29281.61SkreATF_TC_HEAD(test, tc)							\
29291.61Skre{									\
29301.61Skre	atf_tc_set_md_var(tc, "descr",					\
29311.61Skre	    "Verify that eventmask " #event " is preserved");		\
29321.61Skre}									\
29331.61Skre									\
29341.61SkreATF_TC_BODY(test, tc)							\
29351.61Skre{									\
29361.61Skre									\
29371.61Skre	eventmask_preserved(event);					\
29381.1Skamil}
29391.1Skamil
29401.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
29411.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
29421.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
29431.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
29441.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
29451.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
29461.1Skamil
29471.53Skamil/// ----------------------------------------------------------------------------
29481.1Skamil
29491.28Skamilstatic void
29501.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
29511.105Skamil    bool trackvforkdone)
29521.1Skamil{
29531.1Skamil	const int exitval = 5;
29541.1Skamil	const int exitval2 = 15;
29551.1Skamil	const int sigval = SIGSTOP;
29561.31Skamil	pid_t child, child2 = 0, wpid;
29571.1Skamil#if defined(TWAIT_HAVE_STATUS)
29581.1Skamil	int status;
29591.1Skamil#endif
29601.1Skamil	ptrace_state_t state;
29611.1Skamil	const int slen = sizeof(state);
29621.1Skamil	ptrace_event_t event;
29631.1Skamil	const int elen = sizeof(event);
29641.1Skamil
29651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29671.1Skamil	if (child == 0) {
29681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29701.1Skamil
29711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29731.1Skamil
29741.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
29751.1Skamil
29761.1Skamil		if (child2 == 0)
29771.1Skamil			_exit(exitval2);
29781.1Skamil
29791.1Skamil		FORKEE_REQUIRE_SUCCESS
29801.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
29811.1Skamil
29821.1Skamil		forkee_status_exited(status, exitval2);
29831.1Skamil
29841.13Schristos		DPRINTF("Before exiting of the child process\n");
29851.1Skamil		_exit(exitval);
29861.1Skamil	}
29871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29881.1Skamil
29891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29911.1Skamil
29921.1Skamil	validate_status_stopped(status, sigval);
29931.1Skamil
29941.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
29951.61Skre	    trackfork ? "|PTRACE_FORK" : "",
29961.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
29971.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
29981.30Skamil	event.pe_set_event = 0;
29991.30Skamil	if (trackfork)
30001.30Skamil		event.pe_set_event |= PTRACE_FORK;
30011.30Skamil	if (trackvfork)
30021.30Skamil		event.pe_set_event |= PTRACE_VFORK;
30031.30Skamil	if (trackvforkdone)
30041.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
30051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
30061.1Skamil
30071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30081.1Skamil	    "without signal to be sent\n");
30091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30101.1Skamil
30111.29Skamil#if defined(TWAIT_HAVE_PID)
30121.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30131.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30141.61Skre		    child);
30151.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30161.61Skre		    child);
30171.1Skamil
30181.29Skamil		validate_status_stopped(status, SIGTRAP);
30191.1Skamil
30201.61Skre		SYSCALL_REQUIRE(
30211.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30221.31Skamil		if (trackfork && fn == fork) {
30231.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30241.30Skamil			       PTRACE_FORK);
30251.30Skamil		}
30261.31Skamil		if (trackvfork && fn == vfork) {
30271.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30281.30Skamil			       PTRACE_VFORK);
30291.30Skamil		}
30301.29Skamil
30311.29Skamil		child2 = state.pe_other_pid;
30321.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
30331.29Skamil
30341.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
30351.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
30361.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
30371.29Skamil		    child2);
30381.1Skamil
30391.29Skamil		validate_status_stopped(status, SIGTRAP);
30401.1Skamil
30411.61Skre		SYSCALL_REQUIRE(
30421.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
30431.31Skamil		if (trackfork && fn == fork) {
30441.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
30451.30Skamil			       PTRACE_FORK);
30461.30Skamil		}
30471.31Skamil		if (trackvfork && fn == vfork) {
30481.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
30491.30Skamil			       PTRACE_VFORK);
30501.30Skamil		}
30511.30Skamil
30521.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
30531.29Skamil
30541.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
30551.29Skamil		    "and without signal to be sent\n");
30561.61Skre		SYSCALL_REQUIRE(
30571.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
30581.29Skamil
30591.29Skamil		DPRINTF("Before resuming the child process where it left off "
30601.61Skre		    "and without signal to be sent\n");
30611.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30621.30Skamil	}
30631.30Skamil#endif
30641.30Skamil
30651.31Skamil	if (trackvforkdone && fn == vfork) {
30661.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
30671.61Skre		    child);
30681.61Skre		TWAIT_REQUIRE_SUCCESS(
30691.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
30701.30Skamil
30711.30Skamil		validate_status_stopped(status, SIGTRAP);
30721.30Skamil
30731.61Skre		SYSCALL_REQUIRE(
30741.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
30751.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
30761.30Skamil
30771.30Skamil		child2 = state.pe_other_pid;
30781.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
30791.61Skre		    child2);
30801.30Skamil
30811.30Skamil		DPRINTF("Before resuming the child process where it left off "
30821.61Skre		    "and without signal to be sent\n");
30831.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30841.30Skamil	}
30851.29Skamil
30861.30Skamil#if defined(TWAIT_HAVE_PID)
30871.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
30881.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
30891.61Skre		    "\n", TWAIT_FNAME);
30901.61Skre		TWAIT_REQUIRE_SUCCESS(
30911.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
30921.29Skamil
30931.29Skamil		validate_status_exited(status, exitval2);
30941.29Skamil
30951.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
30961.61Skre		    "process\n", TWAIT_FNAME);
30971.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
30981.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
30991.29Skamil	}
31001.29Skamil#endif
31011.1Skamil
31021.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
31031.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
31041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31051.1Skamil
31061.1Skamil	validate_status_stopped(status, SIGCHLD);
31071.1Skamil
31081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31091.1Skamil	    "without signal to be sent\n");
31101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31111.1Skamil
31121.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
31131.1Skamil	    TWAIT_FNAME);
31141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31151.1Skamil
31161.1Skamil	validate_status_exited(status, exitval);
31171.1Skamil
31181.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
31191.1Skamil	    TWAIT_FNAME);
31201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31211.1Skamil}
31221.28Skamil
31231.105Skamil#define FORK_TEST(name,fun,tfork,tvfork,tvforkdone)			\
31241.61SkreATF_TC(name);								\
31251.61SkreATF_TC_HEAD(name, tc)							\
31261.61Skre{									\
31271.105Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
31281.105Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
31291.105Skamil	    tfork ? "|PTRACE_FORK" : "",				\
31301.105Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
31311.105Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
31321.61Skre}									\
31331.61Skre									\
31341.61SkreATF_TC_BODY(name, tc)							\
31351.61Skre{									\
31361.61Skre									\
31371.105Skamil	fork_body(fun, tfork, tvfork, tvforkdone);			\
31381.32Skamil}
31391.32Skamil
31401.105SkamilFORK_TEST(fork1, fork, false, false, false)
31411.31Skamil#if defined(TWAIT_HAVE_PID)
31421.105SkamilFORK_TEST(fork2, fork, true, false, false)
31431.105SkamilFORK_TEST(fork3, fork, false, true, false)
31441.105SkamilFORK_TEST(fork4, fork, true, true, false)
31451.31Skamil#endif
31461.105SkamilFORK_TEST(fork5, fork, false, false, true)
31471.31Skamil#if defined(TWAIT_HAVE_PID)
31481.105SkamilFORK_TEST(fork6, fork, true, false, true)
31491.105SkamilFORK_TEST(fork7, fork, false, true, true)
31501.105SkamilFORK_TEST(fork8, fork, true, true, true)
31511.31Skamil#endif
31521.1Skamil
31531.105SkamilFORK_TEST(vfork1, vfork, false, false, false)
31541.31Skamil#if defined(TWAIT_HAVE_PID)
31551.105SkamilFORK_TEST(vfork2, vfork, true, false, false)
31561.105SkamilFORK_TEST(vfork3, vfork, false, true, false)
31571.105SkamilFORK_TEST(vfork4, vfork, true, true, false)
31581.31Skamil#endif
31591.105SkamilFORK_TEST(vfork5, vfork, false, false, true)
31601.31Skamil#if defined(TWAIT_HAVE_PID)
31611.105SkamilFORK_TEST(vfork6, vfork, true, false, true)
31621.105SkamilFORK_TEST(vfork7, vfork, false, true, true)
31631.105SkamilFORK_TEST(vfork8, vfork, true, true, true)
31641.31Skamil#endif
31651.31Skamil
31661.54Skamil/// ----------------------------------------------------------------------------
31671.31Skamil
31681.108Skamilstatic void
31691.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void))
31701.108Skamil{
31711.108Skamil	const int exitval = 5;
31721.108Skamil	const int exitval2 = 15;
31731.108Skamil	pid_t child, child2 = 0, wpid;
31741.108Skamil#if defined(TWAIT_HAVE_STATUS)
31751.108Skamil	int status;
31761.108Skamil#endif
31771.108Skamil
31781.108Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
31791.108Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
31801.108Skamil	if (child == 0) {
31811.108Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31821.108Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31831.108Skamil
31841.108Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
31851.108Skamil
31861.108Skamil		if (child2 == 0)
31871.108Skamil			_exit(exitval2);
31881.108Skamil
31891.108Skamil		FORKEE_REQUIRE_SUCCESS
31901.108Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
31911.108Skamil
31921.108Skamil		forkee_status_exited(status, exitval2);
31931.108Skamil
31941.108Skamil		DPRINTF("Before exiting of the child process\n");
31951.108Skamil		_exit(exitval);
31961.108Skamil	}
31971.108Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31981.108Skamil
31991.108Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
32001.108Skamil	    TWAIT_FNAME);
32011.108Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32021.108Skamil
32031.108Skamil	validate_status_exited(status, exitval);
32041.108Skamil
32051.108Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
32061.108Skamil	    TWAIT_FNAME);
32071.108Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32081.108Skamil}
32091.108Skamil
32101.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun)				\
32111.108SkamilATF_TC(name);								\
32121.108SkamilATF_TC_HEAD(name, tc)							\
32131.108Skamil{									\
32141.108Skamil	atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) "		\
32151.108Skamil	    "called from vfork(2)ed child");				\
32161.108Skamil}									\
32171.108Skamil									\
32181.108SkamilATF_TC_BODY(name, tc)							\
32191.108Skamil{									\
32201.108Skamil									\
32211.108Skamil	traceme_vfork_fork_body(fun);					\
32221.108Skamil}
32231.108Skamil
32241.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork)
32251.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork)
32261.108Skamil
32271.108Skamil/// ----------------------------------------------------------------------------
32281.108Skamil
32291.54Skamilenum bytes_transfer_type {
32301.54Skamil	BYTES_TRANSFER_DATA,
32311.54Skamil	BYTES_TRANSFER_DATAIO,
32321.54Skamil	BYTES_TRANSFER_TEXT,
32331.54Skamil	BYTES_TRANSFER_TEXTIO,
32341.54Skamil	BYTES_TRANSFER_AUXV
32351.54Skamil};
32361.31Skamil
32371.54Skamilstatic int __used
32381.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
32391.54Skamil{
32401.54Skamil	int e, f, g, h;
32411.1Skamil
32421.54Skamil	a *= 4;
32431.54Skamil	b += 3;
32441.54Skamil	c -= 2;
32451.54Skamil	d /= 1;
32461.1Skamil
32471.54Skamil	e = strtol("10", NULL, 10);
32481.54Skamil	f = strtol("20", NULL, 10);
32491.54Skamil	g = strtol("30", NULL, 10);
32501.54Skamil	h = strtol("40", NULL, 10);
32511.1Skamil
32521.54Skamil	return (a + b * c - d) + (e * f - g / h);
32531.1Skamil}
32541.1Skamil
32551.54Skamilstatic void
32561.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
32571.1Skamil{
32581.1Skamil	const int exitval = 5;
32591.1Skamil	const int sigval = SIGSTOP;
32601.1Skamil	pid_t child, wpid;
32611.54Skamil	bool skip = false;
32621.1Skamil
32631.54Skamil	int lookup_me = 0;
32641.54Skamil	uint8_t lookup_me8 = 0;
32651.54Skamil	uint16_t lookup_me16 = 0;
32661.54Skamil	uint32_t lookup_me32 = 0;
32671.54Skamil	uint64_t lookup_me64 = 0;
32681.1Skamil
32691.54Skamil	int magic = 0x13579246;
32701.54Skamil	uint8_t magic8 = 0xab;
32711.54Skamil	uint16_t magic16 = 0x1234;
32721.54Skamil	uint32_t magic32 = 0x98765432;
32731.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
32741.1Skamil
32751.54Skamil	struct ptrace_io_desc io;
32761.1Skamil#if defined(TWAIT_HAVE_STATUS)
32771.1Skamil	int status;
32781.1Skamil#endif
32791.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
32801.60Skre	AuxInfo ai[513], *aip;
32811.55Schristos
32821.55Schristos	ATF_REQUIRE(size < sizeof(ai));
32831.1Skamil
32841.54Skamil	/* Prepare variables for .TEXT transfers */
32851.54Skamil	switch (type) {
32861.54Skamil	case BYTES_TRANSFER_TEXT:
32871.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
32881.54Skamil		break;
32891.54Skamil	case BYTES_TRANSFER_TEXTIO:
32901.54Skamil		switch (size) {
32911.54Skamil		case 8:
32921.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
32931.54Skamil			break;
32941.54Skamil		case 16:
32951.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
32961.54Skamil			break;
32971.54Skamil		case 32:
32981.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
32991.54Skamil			break;
33001.54Skamil		case 64:
33011.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
33021.54Skamil			break;
33031.54Skamil		}
33041.54Skamil		break;
33051.54Skamil	default:
33061.54Skamil		break;
33071.54Skamil	}
33081.1Skamil
33091.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
33101.54Skamil	switch (type) {
33111.54Skamil	case BYTES_TRANSFER_TEXTIO:
33121.54Skamil	case BYTES_TRANSFER_DATAIO:
33131.54Skamil		io.piod_op = operation;
33141.54Skamil		switch (size) {
33151.54Skamil		case 8:
33161.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33171.54Skamil			               (void *)bytes_transfer_dummy :
33181.54Skamil			               &lookup_me8;
33191.54Skamil			io.piod_addr = &lookup_me8;
33201.54Skamil			io.piod_len = sizeof(lookup_me8);
33211.54Skamil			break;
33221.54Skamil		case 16:
33231.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33241.54Skamil			               (void *)bytes_transfer_dummy :
33251.54Skamil			               &lookup_me16;
33261.54Skamil			io.piod_addr = &lookup_me16;
33271.54Skamil			io.piod_len = sizeof(lookup_me16);
33281.54Skamil			break;
33291.54Skamil		case 32:
33301.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33311.54Skamil			               (void *)bytes_transfer_dummy :
33321.54Skamil			               &lookup_me32;
33331.54Skamil			io.piod_addr = &lookup_me32;
33341.54Skamil			io.piod_len = sizeof(lookup_me32);
33351.54Skamil			break;
33361.54Skamil		case 64:
33371.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
33381.54Skamil			               (void *)bytes_transfer_dummy :
33391.54Skamil			               &lookup_me64;
33401.54Skamil			io.piod_addr = &lookup_me64;
33411.54Skamil			io.piod_len = sizeof(lookup_me64);
33421.54Skamil			break;
33431.54Skamil		default:
33441.54Skamil			break;
33451.54Skamil		}
33461.54Skamil		break;
33471.54Skamil	case BYTES_TRANSFER_AUXV:
33481.54Skamil		io.piod_op = operation;
33491.54Skamil		io.piod_offs = 0;
33501.54Skamil		io.piod_addr = ai;
33511.54Skamil		io.piod_len = size;
33521.54Skamil		break;
33531.54Skamil	default:
33541.54Skamil		break;
33551.1Skamil	}
33561.1Skamil
33571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33591.1Skamil	if (child == 0) {
33601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33621.1Skamil
33631.54Skamil		switch (type) {
33641.54Skamil		case BYTES_TRANSFER_DATA:
33651.54Skamil			switch (operation) {
33661.54Skamil			case PT_READ_D:
33671.54Skamil			case PT_READ_I:
33681.54Skamil				lookup_me = magic;
33691.54Skamil				break;
33701.54Skamil			default:
33711.54Skamil				break;
33721.54Skamil			}
33731.54Skamil			break;
33741.54Skamil		case BYTES_TRANSFER_DATAIO:
33751.54Skamil			switch (operation) {
33761.54Skamil			case PIOD_READ_D:
33771.54Skamil			case PIOD_READ_I:
33781.54Skamil				switch (size) {
33791.54Skamil				case 8:
33801.54Skamil					lookup_me8 = magic8;
33811.54Skamil					break;
33821.54Skamil				case 16:
33831.54Skamil					lookup_me16 = magic16;
33841.54Skamil					break;
33851.54Skamil				case 32:
33861.54Skamil					lookup_me32 = magic32;
33871.54Skamil					break;
33881.54Skamil				case 64:
33891.54Skamil					lookup_me64 = magic64;
33901.54Skamil					break;
33911.54Skamil				default:
33921.54Skamil					break;
33931.54Skamil				}
33941.54Skamil				break;
33951.54Skamil			default:
33961.54Skamil				break;
33971.54Skamil			}
33981.54Skamil		default:
33991.54Skamil			break;
34001.54Skamil		}
34011.54Skamil
34021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34041.1Skamil
34051.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
34061.54Skamil		switch (type) {
34071.54Skamil		case BYTES_TRANSFER_DATA:
34081.54Skamil			switch (operation) {
34091.54Skamil			case PT_WRITE_D:
34101.54Skamil			case PT_WRITE_I:
34111.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
34121.54Skamil				break;
34131.54Skamil			default:
34141.54Skamil				break;
34151.54Skamil			}
34161.54Skamil			break;
34171.54Skamil		case BYTES_TRANSFER_DATAIO:
34181.54Skamil			switch (operation) {
34191.54Skamil			case PIOD_WRITE_D:
34201.54Skamil			case PIOD_WRITE_I:
34211.54Skamil				switch (size) {
34221.54Skamil				case 8:
34231.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
34241.54Skamil					break;
34251.54Skamil				case 16:
34261.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
34271.54Skamil					break;
34281.54Skamil				case 32:
34291.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
34301.54Skamil					break;
34311.54Skamil				case 64:
34321.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
34331.54Skamil					break;
34341.54Skamil				default:
34351.54Skamil					break;
34361.54Skamil				}
34371.54Skamil				break;
34381.54Skamil			default:
34391.54Skamil				break;
34401.54Skamil			}
34411.54Skamil			break;
34421.54Skamil		case BYTES_TRANSFER_TEXT:
34431.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
34441.54Skamil			                     sizeof(magic)) == 0);
34451.54Skamil			break;
34461.54Skamil		case BYTES_TRANSFER_TEXTIO:
34471.54Skamil			switch (size) {
34481.54Skamil			case 8:
34491.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
34501.54Skamil				                     bytes_transfer_dummy,
34511.54Skamil				                     sizeof(magic8)) == 0);
34521.54Skamil				break;
34531.54Skamil			case 16:
34541.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
34551.54Skamil				                     bytes_transfer_dummy,
34561.54Skamil				                     sizeof(magic16)) == 0);
34571.54Skamil				break;
34581.54Skamil			case 32:
34591.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
34601.54Skamil				                     bytes_transfer_dummy,
34611.54Skamil				                     sizeof(magic32)) == 0);
34621.54Skamil				break;
34631.54Skamil			case 64:
34641.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
34651.54Skamil				                     bytes_transfer_dummy,
34661.54Skamil				                     sizeof(magic64)) == 0);
34671.54Skamil				break;
34681.54Skamil			}
34691.54Skamil			break;
34701.54Skamil		default:
34711.54Skamil			break;
34721.54Skamil		}
34731.54Skamil
34741.13Schristos		DPRINTF("Before exiting of the child process\n");
34751.1Skamil		_exit(exitval);
34761.1Skamil	}
34771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34781.1Skamil
34791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34811.1Skamil
34821.1Skamil	validate_status_stopped(status, sigval);
34831.1Skamil
34841.54Skamil	/* Check PaX MPROTECT */
34851.54Skamil	if (!can_we_write_to_text(child)) {
34861.54Skamil		switch (type) {
34871.54Skamil		case BYTES_TRANSFER_TEXTIO:
34881.54Skamil			switch (operation) {
34891.54Skamil			case PIOD_WRITE_D:
34901.54Skamil			case PIOD_WRITE_I:
34911.54Skamil				skip = true;
34921.54Skamil				break;
34931.54Skamil			default:
34941.54Skamil				break;
34951.54Skamil			}
34961.54Skamil			break;
34971.54Skamil		case BYTES_TRANSFER_TEXT:
34981.54Skamil			switch (operation) {
34991.54Skamil			case PT_WRITE_D:
35001.54Skamil			case PT_WRITE_I:
35011.54Skamil				skip = true;
35021.54Skamil				break;
35031.54Skamil			default:
35041.54Skamil				break;
35051.54Skamil			}
35061.54Skamil			break;
35071.54Skamil		default:
35081.54Skamil			break;
35091.54Skamil		}
35101.54Skamil	}
35111.1Skamil
35121.54Skamil	/* Bailout cleanly killing the child process */
35131.54Skamil	if (skip) {
35141.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
35151.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35161.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
35171.54Skamil		                      child);
35181.1Skamil
35191.54Skamil		validate_status_signaled(status, SIGKILL, 0);
35201.1Skamil
35211.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
35221.54Skamil	}
35231.1Skamil
35241.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
35251.54Skamil	       "parent=%d\n", child, getpid());
35261.1Skamil
35271.54Skamil	switch (type) {
35281.54Skamil	case BYTES_TRANSFER_TEXTIO:
35291.54Skamil	case BYTES_TRANSFER_DATAIO:
35301.54Skamil	case BYTES_TRANSFER_AUXV:
35311.54Skamil		switch (operation) {
35321.54Skamil		case PIOD_WRITE_D:
35331.54Skamil		case PIOD_WRITE_I:
35341.54Skamil			switch (size) {
35351.54Skamil			case 8:
35361.54Skamil				lookup_me8 = magic8;
35371.54Skamil				break;
35381.54Skamil			case 16:
35391.54Skamil				lookup_me16 = magic16;
35401.54Skamil				break;
35411.54Skamil			case 32:
35421.54Skamil				lookup_me32 = magic32;
35431.54Skamil				break;
35441.54Skamil			case 64:
35451.54Skamil				lookup_me64 = magic64;
35461.54Skamil				break;
35471.54Skamil			default:
35481.54Skamil				break;
35491.54Skamil			}
35501.54Skamil			break;
35511.54Skamil		default:
35521.54Skamil			break;
35531.54Skamil		}
35541.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35551.54Skamil		switch (operation) {
35561.54Skamil		case PIOD_READ_D:
35571.54Skamil		case PIOD_READ_I:
35581.54Skamil			switch (size) {
35591.54Skamil			case 8:
35601.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
35611.54Skamil				break;
35621.54Skamil			case 16:
35631.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
35641.54Skamil				break;
35651.54Skamil			case 32:
35661.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
35671.54Skamil				break;
35681.54Skamil			case 64:
35691.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
35701.54Skamil				break;
35711.54Skamil			default:
35721.54Skamil				break;
35731.54Skamil			}
35741.54Skamil			break;
35751.54Skamil		case PIOD_READ_AUXV:
35761.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
35771.54Skamil			        io.piod_len);
35781.54Skamil			ATF_REQUIRE(io.piod_len > 0);
35791.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
35801.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
35811.54Skamil				    (long long int)aip->a_type,
35821.54Skamil				    (long long int)aip->a_v);
35831.54Skamil			break;
35841.54Skamil		default:
35851.54Skamil			break;
35861.54Skamil		}
35871.54Skamil		break;
35881.54Skamil	case BYTES_TRANSFER_TEXT:
35891.54Skamil		switch (operation) {
35901.54Skamil		case PT_READ_D:
35911.54Skamil		case PT_READ_I:
35921.54Skamil			errno = 0;
35931.54Skamil			lookup_me = ptrace(operation, child,
35941.54Skamil			                   bytes_transfer_dummy, 0);
35951.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
35961.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
35971.54Skamil			break;
35981.54Skamil		case PT_WRITE_D:
35991.54Skamil		case PT_WRITE_I:
36001.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
36011.54Skamil			                       bytes_transfer_dummy, magic)
36021.54Skamil			                != -1);
36031.54Skamil			break;
36041.54Skamil		default:
36051.54Skamil			break;
36061.54Skamil		}
36071.54Skamil		break;
36081.54Skamil	case BYTES_TRANSFER_DATA:
36091.54Skamil		switch (operation) {
36101.54Skamil		case PT_READ_D:
36111.54Skamil		case PT_READ_I:
36121.54Skamil			errno = 0;
36131.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
36141.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
36151.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
36161.54Skamil			break;
36171.54Skamil		case PT_WRITE_D:
36181.54Skamil		case PT_WRITE_I:
36191.54Skamil			lookup_me = magic;
36201.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
36211.54Skamil			                       magic) != -1);
36221.54Skamil			break;
36231.54Skamil		default:
36241.54Skamil			break;
36251.54Skamil		}
36261.54Skamil		break;
36271.54Skamil	default:
36281.54Skamil		break;
36291.54Skamil	}
36301.1Skamil
36311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36321.1Skamil	    "without signal to be sent\n");
36331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36341.1Skamil
36351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36371.1Skamil
36381.1Skamil	validate_status_exited(status, exitval);
36391.1Skamil
36401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36421.1Skamil}
36431.1Skamil
36441.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
36451.61SkreATF_TC(test);								\
36461.61SkreATF_TC_HEAD(test, tc)							\
36471.61Skre{									\
36481.61Skre	atf_tc_set_md_var(tc, "descr",					\
36491.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
36501.61Skre	    " of type " #type);						\
36511.61Skre}									\
36521.61Skre									\
36531.61SkreATF_TC_BODY(test, tc)							\
36541.61Skre{									\
36551.61Skre									\
36561.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
36571.1Skamil}
36581.1Skamil
36591.54Skamil// DATA
36601.1Skamil
36611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
36621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
36631.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
36641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
36651.54Skamil
36661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
36671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
36681.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
36691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
36701.54Skamil
36711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
36721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
36731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
36741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
36751.54Skamil
36761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
36771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
36781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
36791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
36801.54Skamil
36811.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
36821.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
36831.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
36841.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
36851.54Skamil
36861.54Skamil// TEXT
36871.54Skamil
36881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
36891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
36901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
36911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
36921.54Skamil
36931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
36941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
36951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
36961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
36971.54Skamil
36981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
36991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
37001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
37011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
37021.54Skamil
37031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
37041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
37051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
37061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
37071.54Skamil
37081.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
37091.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
37101.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
37111.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
37121.1Skamil
37131.54Skamil// AUXV
37141.1Skamil
37151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
37161.1Skamil
37171.54Skamil/// ----------------------------------------------------------------------------
37181.1Skamil
37191.101Skamilstatic void
37201.101Skamilbytes_transfer_alignment(const char *operation)
37211.101Skamil{
37221.101Skamil	const int exitval = 5;
37231.101Skamil	const int sigval = SIGSTOP;
37241.101Skamil	pid_t child, wpid;
37251.101Skamil#if defined(TWAIT_HAVE_STATUS)
37261.101Skamil	int status;
37271.101Skamil#endif
37281.101Skamil	char *buffer;
37291.101Skamil	int vector;
37301.101Skamil	size_t len;
37311.101Skamil	size_t i;
37321.101Skamil	int op;
37331.101Skamil
37341.101Skamil	struct ptrace_io_desc io;
37351.101Skamil	struct ptrace_siginfo info;
37361.101Skamil
37371.101Skamil	memset(&io, 0, sizeof(io));
37381.101Skamil	memset(&info, 0, sizeof(info));
37391.101Skamil
37401.101Skamil	/* Testing misaligned byte transfer crossing page boundaries */
37411.101Skamil	len = sysconf(_SC_PAGESIZE) * 2;
37421.101Skamil	buffer = malloc(len);
37431.101Skamil	ATF_REQUIRE(buffer != NULL);
37441.101Skamil
37451.101Skamil	/* Initialize the buffer with random data */
37461.101Skamil	for (i = 0; i < len; i++)
37471.101Skamil		buffer[i] = i & 0xff;
37481.101Skamil
37491.101Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
37501.101Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
37511.101Skamil	if (child == 0) {
37521.101Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37531.101Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37541.101Skamil
37551.101Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37561.101Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37571.101Skamil
37581.101Skamil		DPRINTF("Before exiting of the child process\n");
37591.101Skamil		_exit(exitval);
37601.101Skamil	}
37611.101Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37621.101Skamil
37631.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37641.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37651.101Skamil
37661.101Skamil	validate_status_stopped(status, sigval);
37671.101Skamil
37681.101Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37691.101Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
37701.101Skamil		!= -1);
37711.101Skamil
37721.101Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37731.101Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
37741.101Skamil		"si_errno=%#x\n",
37751.101Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37761.101Skamil		info.psi_siginfo.si_errno);
37771.101Skamil
37781.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
37791.101Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
37801.101Skamil
37811.101Skamil	if (strcmp(operation, "PT_READ_I") == 0 ||
37821.101Skamil	    strcmp(operation, "PT_READ_D") == 0) {
37831.101Skamil		if (strcmp(operation, "PT_READ_I"))
37841.101Skamil			op = PT_READ_I;
37851.101Skamil		else
37861.101Skamil			op = PT_READ_D;
37871.101Skamil
37881.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
37891.101Skamil			errno = 0;
37901.101Skamil			vector = ptrace(op, child, buffer + i, 0);
37911.101Skamil			ATF_REQUIRE_EQ(errno, 0);
37921.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
37931.101Skamil		}
37941.101Skamil	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
37951.101Skamil	           strcmp(operation, "PT_WRITE_D") == 0) {
37961.101Skamil		if (strcmp(operation, "PT_WRITE_I"))
37971.101Skamil			op = PT_WRITE_I;
37981.101Skamil		else
37991.101Skamil			op = PT_WRITE_D;
38001.101Skamil
38011.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38021.101Skamil			memcpy(&vector, buffer + i, sizeof(int));
38031.101Skamil			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
38041.101Skamil			    != -1);
38051.101Skamil		}
38061.101Skamil	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
38071.101Skamil	           strcmp(operation, "PIOD_READ_D") == 0) {
38081.101Skamil		if (strcmp(operation, "PIOD_READ_I"))
38091.101Skamil			op = PIOD_READ_I;
38101.101Skamil		else
38111.101Skamil			op = PIOD_READ_D;
38121.101Skamil
38131.101Skamil		io.piod_op = op;
38141.101Skamil		io.piod_addr = &vector;
38151.101Skamil		io.piod_len = sizeof(int);
38161.101Skamil
38171.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38181.101Skamil			io.piod_offs = buffer + i;
38191.101Skamil
38201.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38211.101Skamil			                != -1);
38221.101Skamil			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
38231.101Skamil		}
38241.101Skamil	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
38251.101Skamil	           strcmp(operation, "PIOD_WRITE_D") == 0) {
38261.101Skamil		if (strcmp(operation, "PIOD_WRITE_I"))
38271.101Skamil			op = PIOD_WRITE_I;
38281.101Skamil		else
38291.101Skamil			op = PIOD_WRITE_D;
38301.101Skamil
38311.101Skamil		io.piod_op = op;
38321.101Skamil		io.piod_addr = &vector;
38331.101Skamil		io.piod_len = sizeof(int);
38341.101Skamil
38351.101Skamil		for (i = 0; i <= (len - sizeof(int)); i++) {
38361.101Skamil			io.piod_offs = buffer + i;
38371.101Skamil
38381.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38391.101Skamil			                != -1);
38401.101Skamil		}
38411.101Skamil	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
38421.101Skamil		io.piod_op = PIOD_READ_AUXV;
38431.101Skamil		io.piod_addr = &vector;
38441.101Skamil		io.piod_len = sizeof(int);
38451.101Skamil
38461.101Skamil		errno = 0;
38471.101Skamil		i = 0;
38481.101Skamil		/* Read the whole AUXV vector, it has no clear length */
38491.101Skamil		while (errno != EIO) {
38501.101Skamil			io.piod_offs = (void *)(intptr_t)i;
38511.101Skamil			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
38521.101Skamil			                != -1 || (errno == EIO && i > 0));
38531.101Skamil			++i;
38541.101Skamil		}
38551.101Skamil	}
38561.101Skamil
38571.101Skamil	DPRINTF("Before resuming the child process where it left off "
38581.101Skamil	    "and without signal to be sent\n");
38591.101Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38601.101Skamil
38611.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38621.101Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
38631.101Skamil	    child);
38641.101Skamil
38651.101Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38661.101Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38671.101Skamil}
38681.101Skamil
38691.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
38701.101SkamilATF_TC(test);								\
38711.101SkamilATF_TC_HEAD(test, tc)							\
38721.101Skamil{									\
38731.101Skamil	atf_tc_set_md_var(tc, "descr",					\
38741.101Skamil	    "Verify bytes transfer for potentially misaligned "		\
38751.101Skamil	    "operation " operation);					\
38761.101Skamil}									\
38771.101Skamil									\
38781.101SkamilATF_TC_BODY(test, tc)							\
38791.101Skamil{									\
38801.101Skamil									\
38811.101Skamil	bytes_transfer_alignment(operation);				\
38821.101Skamil}
38831.101Skamil
38841.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
38851.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
38861.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
38871.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
38881.101Skamil
38891.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
38901.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
38911.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
38921.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
38931.101Skamil
38941.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
38951.101Skamil
38961.101Skamil/// ----------------------------------------------------------------------------
38971.101Skamil
38981.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
38991.72Skamilstatic void
39001.72Skamilaccess_regs(const char *regset, const char *aux)
39011.1Skamil{
39021.1Skamil	const int exitval = 5;
39031.1Skamil	const int sigval = SIGSTOP;
39041.1Skamil	pid_t child, wpid;
39051.1Skamil#if defined(TWAIT_HAVE_STATUS)
39061.1Skamil	int status;
39071.1Skamil#endif
39081.72Skamil#if defined(HAVE_GPREGS)
39091.72Skamil	struct reg gpr;
39101.76Sscole	register_t rgstr;
39111.1Skamil#endif
39121.72Skamil#if defined(HAVE_FPREGS)
39131.72Skamil	struct fpreg fpr;
39141.1Skamil#endif
39151.76Sscole
39161.72Skamil#if !defined(HAVE_GPREGS)
39171.72Skamil	if (strcmp(regset, "regs") == 0)
39181.72Skamil		atf_tc_fail("Impossible test scenario!");
39191.1Skamil#endif
39201.1Skamil
39211.72Skamil#if !defined(HAVE_FPREGS)
39221.72Skamil	if (strcmp(regset, "fpregs") == 0)
39231.72Skamil		atf_tc_fail("Impossible test scenario!");
39241.1Skamil#endif
39251.1Skamil
39261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39281.1Skamil	if (child == 0) {
39291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39311.1Skamil
39321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39341.1Skamil
39351.13Schristos		DPRINTF("Before exiting of the child process\n");
39361.1Skamil		_exit(exitval);
39371.1Skamil	}
39381.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39391.1Skamil
39401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39421.1Skamil
39431.1Skamil	validate_status_stopped(status, sigval);
39441.1Skamil
39451.1Skamil#if defined(HAVE_GPREGS)
39461.72Skamil	if (strcmp(regset, "regs") == 0) {
39471.72Skamil		DPRINTF("Call GETREGS for the child process\n");
39481.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
39491.72Skamil
39501.72Skamil		if (strcmp(aux, "none") == 0) {
39511.72Skamil			DPRINTF("Retrieved registers\n");
39521.72Skamil		} else if (strcmp(aux, "pc") == 0) {
39531.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
39541.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39551.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
39561.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
39571.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
39581.72Skamil		} else if (strcmp(aux, "sp") == 0) {
39591.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
39601.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39611.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
39621.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
39631.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
39641.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
39651.72Skamil			DPRINTF("Call SETREGS for the child process\n");
39661.72Skamil			SYSCALL_REQUIRE(
39671.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
39681.72Skamil		}
39691.72Skamil	}
39701.1Skamil#endif
39711.1Skamil
39721.72Skamil#if defined(HAVE_FPREGS)
39731.72Skamil	if (strcmp(regset, "fpregs") == 0) {
39741.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
39751.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
39761.72Skamil
39771.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
39781.72Skamil			DPRINTF("Retrieved FP registers\n");
39791.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
39801.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
39811.72Skamil			SYSCALL_REQUIRE(
39821.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
39831.72Skamil		}
39841.1Skamil	}
39851.1Skamil#endif
39861.1Skamil
39871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39881.1Skamil	    "without signal to be sent\n");
39891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39901.1Skamil
39911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39931.1Skamil
39941.1Skamil	validate_status_exited(status, exitval);
39951.1Skamil
39961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39981.1Skamil}
39991.1Skamil
40001.72Skamil#define ACCESS_REGS(test, regset, aux)					\
40011.72SkamilATF_TC(test);								\
40021.72SkamilATF_TC_HEAD(test, tc)							\
40031.72Skamil{									\
40041.72Skamil        atf_tc_set_md_var(tc, "descr",					\
40051.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
40061.72Skamil}									\
40071.72Skamil									\
40081.72SkamilATF_TC_BODY(test, tc)							\
40091.72Skamil{									\
40101.72Skamil									\
40111.72Skamil        access_regs(regset, aux);					\
40121.1Skamil}
40131.1Skamil#endif
40141.1Skamil
40151.72Skamil#if defined(HAVE_GPREGS)
40161.72SkamilACCESS_REGS(access_regs1, "regs", "none")
40171.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
40181.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
40191.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
40201.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
40211.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
40221.1Skamil#endif
40231.1Skamil#if defined(HAVE_FPREGS)
40241.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
40251.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
40261.1Skamil#endif
40271.1Skamil
40281.72Skamil/// ----------------------------------------------------------------------------
40291.1Skamil
40301.1Skamil#if defined(PT_STEP)
40311.1Skamilstatic void
40321.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored)
40331.1Skamil{
40341.1Skamil	const int exitval = 5;
40351.1Skamil	const int sigval = SIGSTOP;
40361.1Skamil	pid_t child, wpid;
40371.1Skamil#if defined(TWAIT_HAVE_STATUS)
40381.1Skamil	int status;
40391.1Skamil#endif
40401.1Skamil	int happy;
40411.95Skamil	struct sigaction sa;
40421.81Skamil	struct ptrace_siginfo info;
40431.95Skamil	sigset_t intmask;
40441.95Skamil	struct kinfo_proc2 kp;
40451.95Skamil	size_t len = sizeof(kp);
40461.95Skamil
40471.95Skamil	int name[6];
40481.95Skamil	const size_t namelen = __arraycount(name);
40491.95Skamil	ki_sigset_t kp_sigmask;
40501.95Skamil	ki_sigset_t kp_sigignore;
40511.1Skamil
40521.1Skamil#if defined(__arm__)
40531.1Skamil	/* PT_STEP not supported on arm 32-bit */
40541.1Skamil	atf_tc_expect_fail("PR kern/52119");
40551.1Skamil#endif
40561.1Skamil
40571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40591.1Skamil	if (child == 0) {
40601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40621.1Skamil
40631.95Skamil		if (masked) {
40641.95Skamil			sigemptyset(&intmask);
40651.95Skamil			sigaddset(&intmask, SIGTRAP);
40661.95Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
40671.95Skamil		}
40681.95Skamil
40691.95Skamil		if (ignored) {
40701.95Skamil			memset(&sa, 0, sizeof(sa));
40711.95Skamil			sa.sa_handler = SIG_IGN;
40721.95Skamil			sigemptyset(&sa.sa_mask);
40731.95Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
40741.95Skamil		}
40751.95Skamil
40761.1Skamil		happy = check_happy(999);
40771.1Skamil
40781.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40791.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40801.1Skamil
40811.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
40821.1Skamil
40831.13Schristos		DPRINTF("Before exiting of the child process\n");
40841.1Skamil		_exit(exitval);
40851.1Skamil	}
40861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40871.1Skamil
40881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40901.1Skamil
40911.1Skamil	validate_status_stopped(status, sigval);
40921.1Skamil
40931.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40941.81Skamil	SYSCALL_REQUIRE(
40951.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
40961.81Skamil
40971.81Skamil	DPRINTF("Before checking siginfo_t\n");
40981.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
40991.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
41001.81Skamil
41011.95Skamil	name[0] = CTL_KERN,
41021.95Skamil	name[1] = KERN_PROC2,
41031.95Skamil	name[2] = KERN_PROC_PID;
41041.95Skamil	name[3] = child;
41051.95Skamil	name[4] = sizeof(kp);
41061.95Skamil	name[5] = 1;
41071.95Skamil
41081.95Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
41091.95Skamil
41101.95Skamil	if (masked)
41111.95Skamil		kp_sigmask = kp.p_sigmask;
41121.95Skamil
41131.95Skamil	if (ignored)
41141.95Skamil		kp_sigignore = kp.p_sigignore;
41151.95Skamil
41161.1Skamil	while (N --> 0) {
41171.2Skamil		if (setstep) {
41181.13Schristos			DPRINTF("Before resuming the child process where it "
41191.2Skamil			    "left off and without signal to be sent (use "
41201.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
41211.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
41221.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
41231.2Skamil			    != -1);
41241.2Skamil		} else {
41251.13Schristos			DPRINTF("Before resuming the child process where it "
41261.2Skamil			    "left off and without signal to be sent (use "
41271.2Skamil			    "PT_STEP)\n");
41281.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
41291.2Skamil			    != -1);
41301.2Skamil		}
41311.1Skamil
41321.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41331.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
41341.1Skamil		    child);
41351.1Skamil
41361.1Skamil		validate_status_stopped(status, SIGTRAP);
41371.2Skamil
41381.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
41391.81Skamil		SYSCALL_REQUIRE(
41401.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41411.81Skamil
41421.81Skamil		DPRINTF("Before checking siginfo_t\n");
41431.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
41441.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
41451.81Skamil
41461.2Skamil		if (setstep) {
41471.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
41481.2Skamil		}
41491.95Skamil
41501.95Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
41511.95Skamil
41521.95Skamil		if (masked) {
41531.95Skamil			DPRINTF("kp_sigmask="
41541.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41551.95Skamil			    PRIx32 "\n",
41561.95Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
41571.95Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
41581.95Skamil
41591.95Skamil			DPRINTF("kp.p_sigmask="
41601.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41611.95Skamil			    PRIx32 "\n",
41621.95Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
41631.95Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
41641.95Skamil
41651.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
41661.95Skamil			    sizeof(kp_sigmask)));
41671.95Skamil		}
41681.95Skamil
41691.95Skamil		if (ignored) {
41701.95Skamil			DPRINTF("kp_sigignore="
41711.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41721.95Skamil			    PRIx32 "\n",
41731.95Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
41741.95Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
41751.95Skamil
41761.95Skamil			DPRINTF("kp.p_sigignore="
41771.95Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
41781.95Skamil			    PRIx32 "\n",
41791.95Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
41801.95Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
41811.95Skamil
41821.95Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
41831.95Skamil			    sizeof(kp_sigignore)));
41841.95Skamil		}
41851.1Skamil	}
41861.1Skamil
41871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41881.1Skamil	    "without signal to be sent\n");
41891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41901.1Skamil
41911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41931.1Skamil
41941.1Skamil	validate_status_exited(status, exitval);
41951.1Skamil
41961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41981.1Skamil}
41991.1Skamil
42001.73Skamil#define PTRACE_STEP(test, N, setstep)					\
42011.73SkamilATF_TC(test);								\
42021.73SkamilATF_TC_HEAD(test, tc)							\
42031.73Skamil{									\
42041.73Skamil        atf_tc_set_md_var(tc, "descr",					\
42051.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
42061.73Skamil}									\
42071.73Skamil									\
42081.73SkamilATF_TC_BODY(test, tc)							\
42091.73Skamil{									\
42101.73Skamil									\
42111.95Skamil        ptrace_step(N, setstep, false, false);				\
42121.1Skamil}
42131.1Skamil
42141.73SkamilPTRACE_STEP(step1, 1, 0)
42151.73SkamilPTRACE_STEP(step2, 2, 0)
42161.73SkamilPTRACE_STEP(step3, 3, 0)
42171.73SkamilPTRACE_STEP(step4, 4, 0)
42181.73SkamilPTRACE_STEP(setstep1, 1, 1)
42191.73SkamilPTRACE_STEP(setstep2, 2, 1)
42201.73SkamilPTRACE_STEP(setstep3, 3, 1)
42211.73SkamilPTRACE_STEP(setstep4, 4, 1)
42221.95Skamil
42231.95SkamilATF_TC(step_signalmasked);
42241.95SkamilATF_TC_HEAD(step_signalmasked, tc)
42251.95Skamil{
42261.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP");
42271.95Skamil}
42281.95Skamil
42291.95SkamilATF_TC_BODY(step_signalmasked, tc)
42301.95Skamil{
42311.95Skamil
42321.95Skamil	ptrace_step(1, 0, true, false);
42331.95Skamil}
42341.95Skamil
42351.95SkamilATF_TC(step_signalignored);
42361.95SkamilATF_TC_HEAD(step_signalignored, tc)
42371.95Skamil{
42381.95Skamil	atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP");
42391.95Skamil}
42401.95Skamil
42411.95SkamilATF_TC_BODY(step_signalignored, tc)
42421.95Skamil{
42431.95Skamil
42441.95Skamil	ptrace_step(1, 0, false, true);
42451.95Skamil}
42461.1Skamil#endif
42471.1Skamil
42481.73Skamil/// ----------------------------------------------------------------------------
42491.1Skamil
42501.75Skamilstatic void
42511.75Skamilptrace_kill(const char *type)
42521.1Skamil{
42531.75Skamil	const int sigval = SIGSTOP;
42541.1Skamil	pid_t child, wpid;
42551.1Skamil#if defined(TWAIT_HAVE_STATUS)
42561.1Skamil	int status;
42571.1Skamil#endif
42581.1Skamil
42591.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42601.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42611.1Skamil	if (child == 0) {
42621.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42631.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42641.1Skamil
42651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42671.1Skamil
42681.1Skamil		/* NOTREACHED */
42691.1Skamil		FORKEE_ASSERTX(0 &&
42701.1Skamil		    "Child should be terminated by a signal from its parent");
42711.1Skamil	}
42721.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42731.1Skamil
42741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42761.1Skamil
42771.1Skamil	validate_status_stopped(status, sigval);
42781.1Skamil
42791.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
42801.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
42811.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
42821.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
42831.75Skamil		kill(child, SIGKILL);
42841.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
42851.75Skamil		setpgid(child, 0);
42861.75Skamil		killpg(getpgid(child), SIGKILL);
42871.75Skamil	}
42881.1Skamil
42891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42911.1Skamil
42921.75Skamil	validate_status_signaled(status, SIGKILL, 0);
42931.1Skamil
42941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42951.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42961.1Skamil}
42971.1Skamil
42981.75Skamil#define PTRACE_KILL(test, type)						\
42991.75SkamilATF_TC(test);								\
43001.75SkamilATF_TC_HEAD(test, tc)							\
43011.75Skamil{									\
43021.75Skamil        atf_tc_set_md_var(tc, "descr",					\
43031.75Skamil            "Verify killing the child with " type);			\
43041.75Skamil}									\
43051.75Skamil									\
43061.75SkamilATF_TC_BODY(test, tc)							\
43071.75Skamil{									\
43081.75Skamil									\
43091.75Skamil        ptrace_kill(type);						\
43101.1Skamil}
43111.1Skamil
43121.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
43131.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
43141.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
43151.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
43161.1Skamil
43171.75Skamil/// ----------------------------------------------------------------------------
43181.1Skamil
43191.77Skamilstatic void
43201.77Skamiltraceme_lwpinfo(const int threads)
43211.1Skamil{
43221.1Skamil	const int sigval = SIGSTOP;
43231.77Skamil	const int sigval2 = SIGINT;
43241.1Skamil	pid_t child, wpid;
43251.1Skamil#if defined(TWAIT_HAVE_STATUS)
43261.1Skamil	int status;
43271.1Skamil#endif
43281.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
43291.77Skamil	struct ptrace_siginfo info;
43301.77Skamil
43311.77Skamil	/* Maximum number of supported threads in this test */
43321.77Skamil	pthread_t t[3];
43331.77Skamil	int n, rv;
43341.77Skamil
43351.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
43361.1Skamil
43371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43391.1Skamil	if (child == 0) {
43401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43421.1Skamil
43431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43451.1Skamil
43461.77Skamil		for (n = 0; n < threads; n++) {
43471.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
43481.77Skamil			FORKEE_ASSERT(rv == 0);
43491.77Skamil		}
43501.77Skamil
43511.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
43521.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
43531.77Skamil
43541.77Skamil		/* NOTREACHED */
43551.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
43561.1Skamil	}
43571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43581.1Skamil
43591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43611.1Skamil
43621.1Skamil	validate_status_stopped(status, sigval);
43631.1Skamil
43641.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
43651.77Skamil	SYSCALL_REQUIRE(
43661.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
43671.77Skamil
43681.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
43691.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
43701.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
43711.77Skamil	    info.psi_siginfo.si_errno);
43721.77Skamil
43731.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
43741.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
43751.77Skamil
43761.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
43771.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
43781.1Skamil
43791.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
43801.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
43811.1Skamil
43821.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
43831.77Skamil	    lwp.pl_lwpid);
43841.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
43851.1Skamil
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_EQ(lwp.pl_lwpid, 0);
43911.1Skamil
43921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43931.1Skamil	    "without signal to be sent\n");
43941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43951.1Skamil
43961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43981.1Skamil
43991.77Skamil	validate_status_stopped(status, sigval2);
44001.77Skamil
44011.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
44021.77Skamil	SYSCALL_REQUIRE(
44031.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
44041.77Skamil
44051.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
44061.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
44071.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
44081.77Skamil	    info.psi_siginfo.si_errno);
44091.77Skamil
44101.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
44111.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
44121.77Skamil
44131.77Skamil	memset(&lwp, 0, sizeof(lwp));
44141.77Skamil
44151.77Skamil	for (n = 0; n <= threads; n++) {
44161.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
44171.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
44181.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
44191.77Skamil
44201.77Skamil		DPRINTF("Assert that the thread exists\n");
44211.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
44221.77Skamil
44231.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
44241.77Skamil		    lwp.pl_lwpid);
44251.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
44261.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
44271.77Skamil	}
44281.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
44291.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
44301.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
44311.77Skamil
44321.77Skamil	DPRINTF("Assert that there are no more threads\n");
44331.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
44341.77Skamil
44351.77Skamil	DPRINTF("Before resuming the child process where it left off and "
44361.77Skamil	    "without signal to be sent\n");
44371.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
44381.77Skamil
44391.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44401.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44411.77Skamil
44421.77Skamil	validate_status_signaled(status, SIGKILL, 0);
44431.1Skamil
44441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44461.1Skamil}
44471.1Skamil
44481.77Skamil#define TRACEME_LWPINFO(test, threads)					\
44491.77SkamilATF_TC(test);								\
44501.77SkamilATF_TC_HEAD(test, tc)							\
44511.77Skamil{									\
44521.77Skamil	atf_tc_set_md_var(tc, "descr",					\
44531.77Skamil	    "Verify LWPINFO with the child with " #threads		\
44541.77Skamil	    " spawned extra threads");					\
44551.77Skamil}									\
44561.77Skamil									\
44571.77SkamilATF_TC_BODY(test, tc)							\
44581.77Skamil{									\
44591.77Skamil									\
44601.77Skamil	traceme_lwpinfo(threads);					\
44611.1Skamil}
44621.1Skamil
44631.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
44641.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
44651.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
44661.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
44671.77Skamil
44681.77Skamil/// ----------------------------------------------------------------------------
44691.77Skamil
44701.77Skamil#if defined(TWAIT_HAVE_PID)
44711.77Skamilstatic void
44721.77Skamilattach_lwpinfo(const int threads)
44731.1Skamil{
44741.77Skamil	const int sigval = SIGINT;
44751.1Skamil	struct msg_fds parent_tracee, parent_tracer;
44761.1Skamil	const int exitval_tracer = 10;
44771.1Skamil	pid_t tracee, tracer, wpid;
44781.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
44791.1Skamil#if defined(TWAIT_HAVE_STATUS)
44801.1Skamil	int status;
44811.1Skamil#endif
44821.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
44831.77Skamil	struct ptrace_siginfo info;
44841.77Skamil
44851.77Skamil	/* Maximum number of supported threads in this test */
44861.77Skamil	pthread_t t[3];
44871.77Skamil	int n, rv;
44881.1Skamil
44891.13Schristos	DPRINTF("Spawn tracee\n");
44901.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
44911.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
44921.1Skamil	tracee = atf_utils_fork();
44931.1Skamil	if (tracee == 0) {
44941.1Skamil		/* Wait for message from the parent */
44951.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
44961.1Skamil
44971.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
44981.77Skamil
44991.77Skamil		for (n = 0; n < threads; n++) {
45001.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
45011.77Skamil			FORKEE_ASSERT(rv == 0);
45021.77Skamil		}
45031.77Skamil
45041.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
45051.77Skamil
45061.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45071.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45081.77Skamil
45091.77Skamil		/* NOTREACHED */
45101.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
45111.1Skamil	}
45121.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
45131.1Skamil
45141.13Schristos	DPRINTF("Spawn debugger\n");
45151.1Skamil	tracer = atf_utils_fork();
45161.1Skamil	if (tracer == 0) {
45171.1Skamil		/* No IPC to communicate with the child */
45181.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
45191.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
45201.1Skamil
45211.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
45221.1Skamil		FORKEE_REQUIRE_SUCCESS(
45231.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
45241.1Skamil
45251.1Skamil		forkee_status_stopped(status, SIGSTOP);
45261.1Skamil
45271.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
45281.77Skamil		    "tracee");
45291.77Skamil		FORKEE_ASSERT(
45301.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
45311.77Skamil
45321.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45331.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
45341.77Skamil		    "si_errno=%#x\n",
45351.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45361.77Skamil		    info.psi_siginfo.si_errno);
45371.77Skamil
45381.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
45391.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
45401.77Skamil
45411.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
45421.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
45431.1Skamil		    != -1);
45441.1Skamil
45451.13Schristos		DPRINTF("Assert that there exists a thread\n");
45461.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
45471.1Skamil
45481.13Schristos		DPRINTF("Assert that lwp thread %d received event "
45491.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
45501.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
45511.1Skamil
45521.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
45531.77Skamil		    "tracee\n");
45541.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
45551.1Skamil		    != -1);
45561.1Skamil
45571.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
45581.77Skamil		    "tracee\n");
45591.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
45601.1Skamil
45611.1Skamil		/* Resume tracee with PT_CONTINUE */
45621.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
45631.1Skamil
45641.1Skamil		/* Inform parent that tracer has attached to tracee */
45651.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
45661.77Skamil
45671.1Skamil		/* Wait for parent */
45681.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
45691.1Skamil
45701.77Skamil		/* Wait for tracee and assert that it raised a signal */
45711.77Skamil		FORKEE_REQUIRE_SUCCESS(
45721.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
45731.77Skamil
45741.77Skamil		forkee_status_stopped(status, SIGINT);
45751.77Skamil
45761.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
45771.77Skamil		    "child");
45781.77Skamil		FORKEE_ASSERT(
45791.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
45801.77Skamil
45811.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45821.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
45831.77Skamil		    "si_errno=%#x\n",
45841.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45851.77Skamil		    info.psi_siginfo.si_errno);
45861.77Skamil
45871.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
45881.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
45891.77Skamil
45901.77Skamil		memset(&lwp, 0, sizeof(lwp));
45911.77Skamil
45921.77Skamil		for (n = 0; n <= threads; n++) {
45931.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
45941.77Skamil			    "child\n");
45951.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
45961.77Skamil			    sizeof(lwp)) != -1);
45971.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
45981.77Skamil
45991.77Skamil			DPRINTF("Assert that the thread exists\n");
46001.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
46011.77Skamil
46021.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
46031.77Skamil			    "event\n", lwp.pl_lwpid);
46041.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
46051.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
46061.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
46071.77Skamil		}
46081.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
46091.77Skamil		    "tracee\n");
46101.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
46111.77Skamil		    != -1);
46121.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
46131.77Skamil
46141.77Skamil		DPRINTF("Assert that there are no more threads\n");
46151.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
46161.77Skamil
46171.77Skamil		DPRINTF("Before resuming the child process where it left off "
46181.77Skamil		    "and without signal to be sent\n");
46191.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
46201.77Skamil		    != -1);
46211.77Skamil
46221.1Skamil		/* Wait for tracee and assert that it exited */
46231.1Skamil		FORKEE_REQUIRE_SUCCESS(
46241.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
46251.1Skamil
46261.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
46271.1Skamil
46281.13Schristos		DPRINTF("Before exiting of the tracer process\n");
46291.1Skamil		_exit(exitval_tracer);
46301.1Skamil	}
46311.1Skamil
46321.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
46331.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
46341.1Skamil
46351.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
46361.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
46371.77Skamil
46381.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
46391.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
46401.1Skamil
46411.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
46421.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
46431.1Skamil
46441.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
46451.1Skamil	    TWAIT_FNAME);
46461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
46471.1Skamil	    tracer);
46481.1Skamil
46491.1Skamil	validate_status_exited(status, exitval_tracer);
46501.1Skamil
46511.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
46521.1Skamil	    TWAIT_FNAME);
46531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
46541.1Skamil	    tracee);
46551.1Skamil
46561.77Skamil	validate_status_signaled(status, SIGKILL, 0);
46571.1Skamil
46581.1Skamil	msg_close(&parent_tracer);
46591.1Skamil	msg_close(&parent_tracee);
46601.1Skamil}
46611.77Skamil
46621.77Skamil#define ATTACH_LWPINFO(test, threads)					\
46631.77SkamilATF_TC(test);								\
46641.77SkamilATF_TC_HEAD(test, tc)							\
46651.77Skamil{									\
46661.77Skamil	atf_tc_set_md_var(tc, "descr",					\
46671.77Skamil	    "Verify LWPINFO with the child with " #threads		\
46681.77Skamil	    " spawned extra threads (tracer is not the original "	\
46691.77Skamil	    "parent)");							\
46701.77Skamil}									\
46711.77Skamil									\
46721.77SkamilATF_TC_BODY(test, tc)							\
46731.77Skamil{									\
46741.77Skamil									\
46751.77Skamil	attach_lwpinfo(threads);					\
46761.77Skamil}
46771.77Skamil
46781.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
46791.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
46801.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
46811.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
46821.1Skamil#endif
46831.1Skamil
46841.77Skamil/// ----------------------------------------------------------------------------
46851.77Skamil
46861.1Skamilstatic void
46871.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
46881.1Skamil{
46891.1Skamil	const int exitval = 5;
46901.1Skamil	const int sigval = SIGINT;
46911.1Skamil	const int sigfaked = SIGTRAP;
46921.1Skamil	const int sicodefaked = TRAP_BRKPT;
46931.1Skamil	pid_t child, wpid;
46941.1Skamil	struct sigaction sa;
46951.1Skamil#if defined(TWAIT_HAVE_STATUS)
46961.1Skamil	int status;
46971.1Skamil#endif
46981.1Skamil	struct ptrace_siginfo info;
46991.1Skamil	memset(&info, 0, sizeof(info));
47001.1Skamil
47011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47031.1Skamil	if (child == 0) {
47041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47061.1Skamil
47071.79Skamil		sa.sa_sigaction = sah;
47081.1Skamil		sa.sa_flags = SA_SIGINFO;
47091.1Skamil		sigemptyset(&sa.sa_mask);
47101.1Skamil
47111.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
47121.79Skamil		    != -1);
47131.1Skamil
47141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47161.1Skamil
47171.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
47181.1Skamil
47191.13Schristos		DPRINTF("Before exiting of the child process\n");
47201.1Skamil		_exit(exitval);
47211.1Skamil	}
47221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47231.1Skamil
47241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47261.1Skamil
47271.1Skamil	validate_status_stopped(status, sigval);
47281.1Skamil
47291.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
47301.61Skre	SYSCALL_REQUIRE(
47311.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
47321.1Skamil
47331.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47341.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
47351.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47361.1Skamil	    info.psi_siginfo.si_errno);
47371.1Skamil
47381.79Skamil	if (faked) {
47391.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
47401.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
47411.79Skamil		info.psi_siginfo.si_signo = sigfaked;
47421.79Skamil		info.psi_siginfo.si_code = sicodefaked;
47431.79Skamil	}
47441.1Skamil
47451.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
47461.61Skre	SYSCALL_REQUIRE(
47471.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
47481.1Skamil
47491.79Skamil	if (faked) {
47501.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
47511.79Skamil		    "child\n");
47521.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
47531.79Skamil		    sizeof(info)) != -1);
47541.1Skamil
47551.79Skamil		DPRINTF("Before checking siginfo_t\n");
47561.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
47571.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
47581.79Skamil	}
47591.1Skamil
47601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47611.1Skamil	    "without signal to be sent\n");
47621.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
47631.79Skamil	    faked ? sigfaked : sigval) != -1);
47641.1Skamil
47651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47671.1Skamil
47681.1Skamil	validate_status_exited(status, exitval);
47691.1Skamil
47701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47721.1Skamil}
47731.1Skamil
47741.79Skamil#define PTRACE_SIGINFO(test, faked)					\
47751.79SkamilATF_TC(test);								\
47761.79SkamilATF_TC_HEAD(test, tc)							\
47771.79Skamil{									\
47781.79Skamil	atf_tc_set_md_var(tc, "descr",					\
47791.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
47801.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
47811.79Skamil}									\
47821.79Skamil									\
47831.79Skamilstatic int test##_caught = 0;						\
47841.79Skamil									\
47851.79Skamilstatic void								\
47861.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
47871.79Skamil{									\
47881.79Skamil	if (faked) {							\
47891.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
47901.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
47911.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
47921.79Skamil	} else {							\
47931.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
47941.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
47951.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
47961.79Skamil	}								\
47971.79Skamil									\
47981.79Skamil	++ test##_caught;						\
47991.79Skamil}									\
48001.79Skamil									\
48011.79SkamilATF_TC_BODY(test, tc)							\
48021.79Skamil{									\
48031.79Skamil									\
48041.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
48051.79Skamil}
48061.79Skamil
48071.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
48081.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
48091.79Skamil
48101.79Skamil/// ----------------------------------------------------------------------------
48111.79Skamil
48121.97Skamilstatic void
48131.97Skamiltraceme_exec(bool masked, bool ignored)
48141.1Skamil{
48151.1Skamil	const int sigval = SIGTRAP;
48161.1Skamil	pid_t child, wpid;
48171.1Skamil#if defined(TWAIT_HAVE_STATUS)
48181.1Skamil	int status;
48191.1Skamil#endif
48201.97Skamil	struct sigaction sa;
48211.97Skamil	struct ptrace_siginfo info;
48221.97Skamil	sigset_t intmask;
48231.97Skamil	struct kinfo_proc2 kp;
48241.97Skamil	size_t len = sizeof(kp);
48251.97Skamil
48261.97Skamil	int name[6];
48271.97Skamil	const size_t namelen = __arraycount(name);
48281.97Skamil	ki_sigset_t kp_sigmask;
48291.97Skamil	ki_sigset_t kp_sigignore;
48301.1Skamil
48311.1Skamil	memset(&info, 0, sizeof(info));
48321.1Skamil
48331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48351.1Skamil	if (child == 0) {
48361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48381.1Skamil
48391.97Skamil		if (masked) {
48401.97Skamil			sigemptyset(&intmask);
48411.97Skamil			sigaddset(&intmask, sigval);
48421.97Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
48431.97Skamil		}
48441.97Skamil
48451.97Skamil		if (ignored) {
48461.97Skamil			memset(&sa, 0, sizeof(sa));
48471.97Skamil			sa.sa_handler = SIG_IGN;
48481.97Skamil			sigemptyset(&sa.sa_mask);
48491.97Skamil			FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
48501.97Skamil		}
48511.97Skamil
48521.13Schristos		DPRINTF("Before calling execve(2) from child\n");
48531.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
48541.1Skamil
48551.1Skamil		FORKEE_ASSERT(0 && "Not reached");
48561.1Skamil	}
48571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48581.1Skamil
48591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48611.1Skamil
48621.1Skamil	validate_status_stopped(status, sigval);
48631.1Skamil
48641.97Skamil	name[0] = CTL_KERN,
48651.97Skamil	name[1] = KERN_PROC2,
48661.97Skamil	name[2] = KERN_PROC_PID;
48671.97Skamil	name[3] = getpid();
48681.97Skamil	name[4] = sizeof(kp);
48691.97Skamil	name[5] = 1;
48701.97Skamil
48711.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
48721.97Skamil
48731.97Skamil	if (masked)
48741.97Skamil		kp_sigmask = kp.p_sigmask;
48751.97Skamil
48761.97Skamil	if (ignored)
48771.97Skamil		kp_sigignore = kp.p_sigignore;
48781.97Skamil
48791.97Skamil	name[3] = getpid();
48801.97Skamil
48811.97Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
48821.97Skamil
48831.97Skamil	if (masked) {
48841.97Skamil		DPRINTF("kp_sigmask="
48851.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
48861.97Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
48871.97Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
48881.97Skamil
48891.97Skamil		DPRINTF("kp.p_sigmask="
48901.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
48911.97Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
48921.97Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
48931.97Skamil
48941.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
48951.97Skamil		    sizeof(kp_sigmask)));
48961.97Skamil	}
48971.97Skamil
48981.97Skamil	if (ignored) {
48991.97Skamil		DPRINTF("kp_sigignore="
49001.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
49011.97Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
49021.97Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
49031.97Skamil
49041.97Skamil		DPRINTF("kp.p_sigignore="
49051.97Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n",
49061.97Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
49071.97Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
49081.97Skamil
49091.97Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
49101.97Skamil		    sizeof(kp_sigignore)));
49111.97Skamil	}
49121.97Skamil
49131.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49141.61Skre	SYSCALL_REQUIRE(
49151.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49161.1Skamil
49171.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49181.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49191.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49201.1Skamil	    info.psi_siginfo.si_errno);
49211.1Skamil
49221.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
49231.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
49241.1Skamil
49251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49261.1Skamil	    "without signal to be sent\n");
49271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49281.1Skamil
49291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49311.1Skamil
49321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49341.1Skamil}
49351.1Skamil
49361.97Skamil#define TRACEME_EXEC(test, masked, ignored)				\
49371.97SkamilATF_TC(test);								\
49381.97SkamilATF_TC_HEAD(test, tc)							\
49391.97Skamil{									\
49401.97Skamil       atf_tc_set_md_var(tc, "descr",					\
49411.97Skamil           "Detect SIGTRAP TRAP_EXEC from "				\
49421.97Skamil           "child%s%s", masked ? " with masked signal" : "",		\
49431.97Skamil           masked ? " with ignored signal" : "");			\
49441.97Skamil}									\
49451.97Skamil									\
49461.97SkamilATF_TC_BODY(test, tc)							\
49471.97Skamil{									\
49481.97Skamil									\
49491.97Skamil       traceme_exec(masked, ignored);					\
49501.97Skamil}
49511.97Skamil
49521.97SkamilTRACEME_EXEC(traceme_exec, false, false)
49531.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false)
49541.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true)
49551.97Skamil
49561.82Skamil/// ----------------------------------------------------------------------------
49571.82Skamil
49581.83Skamilstatic volatile int done;
49591.1Skamil
49601.83Skamilstatic void *
49611.83Skamiltrace_threads_cb(void *arg __unused)
49621.1Skamil{
49631.1Skamil
49641.83Skamil	done++;
49651.83Skamil
49661.83Skamil	while (done < 3)
49671.83Skamil		continue;
49681.83Skamil
49691.83Skamil	return NULL;
49701.1Skamil}
49711.1Skamil
49721.83Skamilstatic void
49731.83Skamiltrace_threads(bool trace_create, bool trace_exit)
49741.1Skamil{
49751.1Skamil	const int sigval = SIGSTOP;
49761.1Skamil	pid_t child, wpid;
49771.1Skamil#if defined(TWAIT_HAVE_STATUS)
49781.1Skamil	int status;
49791.1Skamil#endif
49801.1Skamil	ptrace_state_t state;
49811.1Skamil	const int slen = sizeof(state);
49821.1Skamil	ptrace_event_t event;
49831.1Skamil	const int elen = sizeof(event);
49841.83Skamil	struct ptrace_siginfo info;
49851.83Skamil
49861.83Skamil	pthread_t t[3];
49871.83Skamil	int rv;
49881.83Skamil	size_t n;
49891.1Skamil	lwpid_t lid;
49901.83Skamil
49911.83Skamil	/* Track created and exited threads */
49921.83Skamil	bool traced_lwps[__arraycount(t)];
49931.83Skamil
49941.83Skamil	atf_tc_skip("PR kern/51995");
49951.1Skamil
49961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49981.1Skamil	if (child == 0) {
49991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50011.1Skamil
50021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50041.1Skamil
50051.83Skamil		for (n = 0; n < __arraycount(t); n++) {
50061.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
50071.83Skamil			    NULL);
50081.83Skamil			FORKEE_ASSERT(rv == 0);
50091.83Skamil		}
50101.1Skamil
50111.83Skamil		for (n = 0; n < __arraycount(t); n++) {
50121.83Skamil			rv = pthread_join(t[n], NULL);
50131.83Skamil			FORKEE_ASSERT(rv == 0);
50141.83Skamil		}
50151.1Skamil
50161.83Skamil		/*
50171.83Skamil		 * There is race between _exit() and pthread_join() detaching
50181.83Skamil		 * a thread. For simplicity kill the process after detecting
50191.83Skamil		 * LWP events.
50201.83Skamil		 */
50211.83Skamil		while (true)
50221.83Skamil			continue;
50231.1Skamil
50241.83Skamil		FORKEE_ASSERT(0 && "Not reached");
50251.1Skamil	}
50261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50271.1Skamil
50281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50301.1Skamil
50311.1Skamil	validate_status_stopped(status, sigval);
50321.1Skamil
50331.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50341.83Skamil	SYSCALL_REQUIRE(
50351.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50361.1Skamil
50371.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50381.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
50391.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50401.83Skamil	    info.psi_siginfo.si_errno);
50411.1Skamil
50421.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
50431.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
50441.1Skamil
50451.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
50461.83Skamil	memset(&event, 0, sizeof(event));
50471.83Skamil	if (trace_create)
50481.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
50491.83Skamil	if (trace_exit)
50501.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
50511.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50521.1Skamil
50531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50541.1Skamil	    "without signal to be sent\n");
50551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50561.1Skamil
50571.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
50581.1Skamil
50591.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
50601.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
50611.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
50621.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
50631.83Skamil		    child);
50641.1Skamil
50651.83Skamil		validate_status_stopped(status, SIGTRAP);
50661.1Skamil
50671.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
50681.83Skamil		    "child\n");
50691.83Skamil		SYSCALL_REQUIRE(
50701.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50711.1Skamil
50721.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50731.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
50741.83Skamil		    "si_errno=%#x\n",
50751.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50761.83Skamil		    info.psi_siginfo.si_errno);
50771.1Skamil
50781.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
50791.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
50801.1Skamil
50811.83Skamil		SYSCALL_REQUIRE(
50821.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50831.1Skamil
50841.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
50851.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
50861.1Skamil
50871.83Skamil		lid = state.pe_lwp;
50881.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
50891.1Skamil
50901.83Skamil		traced_lwps[lid - 1] = true;
50911.1Skamil
50921.83Skamil		DPRINTF("Before resuming the child process where it left off "
50931.83Skamil		    "and without signal to be sent\n");
50941.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50951.83Skamil	}
50961.1Skamil
50971.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
50981.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
50991.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
51001.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
51011.83Skamil		    child);
51021.1Skamil
51031.83Skamil		validate_status_stopped(status, SIGTRAP);
51041.1Skamil
51051.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
51061.83Skamil		    "child\n");
51071.83Skamil		SYSCALL_REQUIRE(
51081.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51091.1Skamil
51101.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
51111.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
51121.83Skamil		    "si_errno=%#x\n",
51131.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
51141.83Skamil		    info.psi_siginfo.si_errno);
51151.1Skamil
51161.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51171.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
51181.1Skamil
51191.83Skamil		SYSCALL_REQUIRE(
51201.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51211.1Skamil
51221.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
51231.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
51241.1Skamil
51251.83Skamil		lid = state.pe_lwp;
51261.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
51271.1Skamil
51281.83Skamil		if (trace_create) {
51291.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
51301.83Skamil			traced_lwps[lid - 1] = false;
51311.83Skamil		}
51321.1Skamil
51331.83Skamil		DPRINTF("Before resuming the child process where it left off "
51341.83Skamil		    "and without signal to be sent\n");
51351.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51361.83Skamil	}
51371.1Skamil
51381.83Skamil	kill(child, SIGKILL);
51391.1Skamil
51401.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51411.1Skamil	    TWAIT_FNAME);
51421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51431.1Skamil
51441.83Skamil	validate_status_signaled(status, SIGKILL, 0);
51451.1Skamil
51461.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51471.1Skamil	    TWAIT_FNAME);
51481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51491.1Skamil}
51501.1Skamil
51511.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
51521.83SkamilATF_TC(test);								\
51531.83SkamilATF_TC_HEAD(test, tc)							\
51541.83Skamil{									\
51551.83Skamil        atf_tc_set_md_var(tc, "descr",					\
51561.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
51571.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
51581.83Skamil	    trace_exit ? "" : "out");					\
51591.83Skamil}									\
51601.83Skamil									\
51611.83SkamilATF_TC_BODY(test, tc)							\
51621.83Skamil{									\
51631.83Skamil									\
51641.83Skamil        trace_threads(trace_create, trace_exit);			\
51651.83Skamil}
51661.83Skamil
51671.83SkamilTRACE_THREADS(trace_thread1, false, false)
51681.83SkamilTRACE_THREADS(trace_thread2, false, true)
51691.83SkamilTRACE_THREADS(trace_thread3, true, false)
51701.83SkamilTRACE_THREADS(trace_thread4, true, true)
51711.83Skamil
51721.83Skamil/// ----------------------------------------------------------------------------
51731.83Skamil
51741.84SkamilATF_TC(signal_mask_unrelated);
51751.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
51761.1Skamil{
51771.1Skamil	atf_tc_set_md_var(tc, "descr",
51781.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
51791.1Skamil	    "from catching other signals");
51801.1Skamil}
51811.1Skamil
51821.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
51831.1Skamil{
51841.1Skamil	const int exitval = 5;
51851.1Skamil	const int sigval = SIGSTOP;
51861.1Skamil	const int sigmasked = SIGTRAP;
51871.1Skamil	const int signotmasked = SIGINT;
51881.1Skamil	pid_t child, wpid;
51891.1Skamil#if defined(TWAIT_HAVE_STATUS)
51901.1Skamil	int status;
51911.1Skamil#endif
51921.1Skamil	sigset_t intmask;
51931.1Skamil
51941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51961.1Skamil	if (child == 0) {
51971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51991.1Skamil
52001.1Skamil		sigemptyset(&intmask);
52011.1Skamil		sigaddset(&intmask, sigmasked);
52021.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
52031.1Skamil
52041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52061.1Skamil
52071.13Schristos		DPRINTF("Before raising %s from child\n",
52081.1Skamil		    strsignal(signotmasked));
52091.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
52101.1Skamil
52111.13Schristos		DPRINTF("Before exiting of the child process\n");
52121.1Skamil		_exit(exitval);
52131.1Skamil	}
52141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52151.1Skamil
52161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52181.1Skamil
52191.1Skamil	validate_status_stopped(status, sigval);
52201.1Skamil
52211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52221.1Skamil	    "without signal to be sent\n");
52231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52241.1Skamil
52251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52271.1Skamil
52281.1Skamil	validate_status_stopped(status, signotmasked);
52291.1Skamil
52301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52311.1Skamil	    "without signal to be sent\n");
52321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52331.1Skamil
52341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52361.1Skamil
52371.1Skamil	validate_status_exited(status, exitval);
52381.1Skamil
52391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52411.1Skamil}
52421.1Skamil
52431.84Skamil/// ----------------------------------------------------------------------------
52441.84Skamil
52451.1Skamil#if defined(TWAIT_HAVE_PID)
52461.99Skamilstatic void
52471.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked,
52481.99Skamil           bool ignored)
52491.1Skamil{
52501.1Skamil	const int exitval = 5;
52511.1Skamil	const int exitval2 = 15;
52521.1Skamil	const int sigval = SIGSTOP;
52531.99Skamil	pid_t child, child2 = 0, wpid;
52541.1Skamil#if defined(TWAIT_HAVE_STATUS)
52551.1Skamil	int status;
52561.1Skamil#endif
52571.1Skamil	ptrace_state_t state;
52581.1Skamil	const int slen = sizeof(state);
52591.1Skamil	ptrace_event_t event;
52601.1Skamil	const int elen = sizeof(event);
52611.99Skamil	pid_t (*fn)(void);
52621.99Skamil	struct sigaction sa;
52631.99Skamil	struct ptrace_siginfo info;
52641.99Skamil	sigset_t intmask;
52651.99Skamil	struct kinfo_proc2 kp;
52661.99Skamil	size_t len = sizeof(kp);
52671.99Skamil
52681.99Skamil	int name[6];
52691.99Skamil	const size_t namelen = __arraycount(name);
52701.99Skamil	ki_sigset_t kp_sigmask;
52711.99Skamil	ki_sigset_t kp_sigignore;
52721.1Skamil
52731.99Skamil	if (trackfork)
52741.99Skamil		fn = fork;
52751.99Skamil	if (trackvfork || trackvforkdone)
52761.99Skamil		fn = vfork;
52771.14Schristos
52781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52801.1Skamil	if (child == 0) {
52811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52831.1Skamil
52841.99Skamil		if (masked) {
52851.99Skamil			sigemptyset(&intmask);
52861.99Skamil			sigaddset(&intmask, SIGTRAP);
52871.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
52881.99Skamil		}
52891.99Skamil
52901.99Skamil		if (ignored) {
52911.99Skamil			memset(&sa, 0, sizeof(sa));
52921.99Skamil			sa.sa_handler = SIG_IGN;
52931.99Skamil			sigemptyset(&sa.sa_mask);
52941.99Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
52951.99Skamil		}
52961.1Skamil
52971.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52981.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52991.1Skamil
53001.99Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
53011.1Skamil
53021.1Skamil		if (child2 == 0)
53031.1Skamil			_exit(exitval2);
53041.1Skamil
53051.1Skamil		FORKEE_REQUIRE_SUCCESS
53061.99Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
53071.1Skamil
53081.1Skamil		forkee_status_exited(status, exitval2);
53091.1Skamil
53101.13Schristos		DPRINTF("Before exiting of the child process\n");
53111.1Skamil		_exit(exitval);
53121.1Skamil	}
53131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53141.1Skamil
53151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53171.1Skamil
53181.1Skamil	validate_status_stopped(status, sigval);
53191.1Skamil
53201.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53211.99Skamil	SYSCALL_REQUIRE(
53221.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53231.99Skamil
53241.99Skamil	DPRINTF("Before checking siginfo_t\n");
53251.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
53261.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
53271.1Skamil
53281.99Skamil	name[0] = CTL_KERN,
53291.99Skamil	name[1] = KERN_PROC2,
53301.99Skamil	name[2] = KERN_PROC_PID;
53311.99Skamil	name[3] = child;
53321.99Skamil	name[4] = sizeof(kp);
53331.99Skamil	name[5] = 1;
53341.1Skamil
53351.99Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53361.1Skamil
53371.99Skamil	if (masked)
53381.99Skamil		kp_sigmask = kp.p_sigmask;
53391.1Skamil
53401.99Skamil	if (ignored)
53411.99Skamil		kp_sigignore = kp.p_sigignore;
53421.1Skamil
53431.99Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
53441.99Skamil	    trackfork ? "|PTRACE_FORK" : "",
53451.99Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
53461.99Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
53471.99Skamil	event.pe_set_event = 0;
53481.99Skamil	if (trackfork)
53491.99Skamil		event.pe_set_event |= PTRACE_FORK;
53501.99Skamil	if (trackvfork)
53511.99Skamil		event.pe_set_event |= PTRACE_VFORK;
53521.99Skamil	if (trackvforkdone)
53531.99Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
53541.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
53551.1Skamil
53561.99Skamil	DPRINTF("Before resuming the child process where it left off and "
53571.99Skamil	    "without signal to be sent\n");
53581.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53591.1Skamil
53601.99Skamil	if (trackfork || trackvfork) {
53611.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
53621.99Skamil		    child);
53631.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
53641.99Skamil		    child);
53651.1Skamil
53661.99Skamil		validate_status_stopped(status, SIGTRAP);
53671.1Skamil
53681.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
53691.1Skamil
53701.99Skamil		if (masked) {
53711.99Skamil			DPRINTF("kp_sigmask="
53721.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53731.99Skamil			    PRIx32 "\n",
53741.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
53751.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
53761.1Skamil
53771.99Skamil			DPRINTF("kp.p_sigmask="
53781.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53791.99Skamil			    PRIx32 "\n",
53801.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
53811.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
53821.1Skamil
53831.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
53841.99Skamil			    sizeof(kp_sigmask)));
53851.99Skamil		}
53861.1Skamil
53871.99Skamil		if (ignored) {
53881.99Skamil			DPRINTF("kp_sigignore="
53891.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53901.99Skamil			    PRIx32 "\n",
53911.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
53921.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
53931.1Skamil
53941.99Skamil			DPRINTF("kp.p_sigignore="
53951.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
53961.99Skamil			    PRIx32 "\n",
53971.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
53981.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
53991.1Skamil
54001.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
54011.99Skamil			    sizeof(kp_sigignore)));
54021.99Skamil		}
54031.1Skamil
54041.99Skamil		SYSCALL_REQUIRE(
54051.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54061.99Skamil		if (trackfork) {
54071.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
54081.99Skamil			       PTRACE_FORK);
54091.99Skamil		}
54101.99Skamil		if (trackvfork) {
54111.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
54121.99Skamil			       PTRACE_VFORK);
54131.99Skamil		}
54141.1Skamil
54151.99Skamil		child2 = state.pe_other_pid;
54161.99Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
54171.1Skamil
54181.99Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
54191.99Skamil		    "%d\n", TWAIT_FNAME, child2, child);
54201.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
54211.99Skamil		    child2);
54221.1Skamil
54231.99Skamil		validate_status_stopped(status, SIGTRAP);
54241.1Skamil
54251.99Skamil		name[3] = child2;
54261.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
54271.1Skamil
54281.99Skamil		if (masked) {
54291.99Skamil			DPRINTF("kp_sigmask="
54301.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54311.99Skamil			    PRIx32 "\n",
54321.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
54331.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
54341.1Skamil
54351.99Skamil			DPRINTF("kp.p_sigmask="
54361.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54371.99Skamil			    PRIx32 "\n",
54381.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
54391.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
54401.14Schristos
54411.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
54421.99Skamil			    sizeof(kp_sigmask)));
54431.99Skamil		}
54441.1Skamil
54451.99Skamil		if (ignored) {
54461.99Skamil			DPRINTF("kp_sigignore="
54471.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54481.99Skamil			    PRIx32 "\n",
54491.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
54501.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
54511.1Skamil
54521.99Skamil			DPRINTF("kp.p_sigignore="
54531.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
54541.99Skamil			    PRIx32 "\n",
54551.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
54561.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
54571.1Skamil
54581.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
54591.99Skamil			    sizeof(kp_sigignore)));
54601.99Skamil		}
54611.1Skamil
54621.99Skamil		SYSCALL_REQUIRE(
54631.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
54641.99Skamil		if (trackfork) {
54651.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
54661.99Skamil			       PTRACE_FORK);
54671.99Skamil		}
54681.99Skamil		if (trackvfork) {
54691.99Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
54701.99Skamil			       PTRACE_VFORK);
54711.99Skamil		}
54721.1Skamil
54731.99Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
54741.1Skamil
54751.99Skamil		DPRINTF("Before resuming the forkee process where it left off "
54761.99Skamil		    "and without signal to be sent\n");
54771.99Skamil		SYSCALL_REQUIRE(
54781.99Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
54791.1Skamil
54801.99Skamil		DPRINTF("Before resuming the child process where it left off "
54811.99Skamil		    "and without signal to be sent\n");
54821.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54831.1Skamil	}
54841.1Skamil
54851.99Skamil	if (trackvforkdone) {
54861.99Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
54871.99Skamil		    child);
54881.99Skamil		TWAIT_REQUIRE_SUCCESS(
54891.99Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
54901.1Skamil
54911.99Skamil		validate_status_stopped(status, SIGTRAP);
54921.1Skamil
54931.99Skamil		name[3] = child;
54941.99Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
54951.1Skamil
54961.102Skamil		/*
54971.102Skamil		 * SIGCHLD is now pending in the signal queue and
54981.102Skamil		 * the kernel presents it to userland as a masked signal.
54991.102Skamil		 */
55001.102Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
55011.102Skamil
55021.99Skamil		if (masked) {
55031.99Skamil			DPRINTF("kp_sigmask="
55041.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55051.99Skamil			    PRIx32 "\n",
55061.99Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
55071.99Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
55081.1Skamil
55091.99Skamil			DPRINTF("kp.p_sigmask="
55101.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55111.99Skamil			    PRIx32 "\n",
55121.99Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
55131.99Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
55141.1Skamil
55151.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
55161.99Skamil			    sizeof(kp_sigmask)));
55171.99Skamil		}
55181.1Skamil
55191.99Skamil		if (ignored) {
55201.99Skamil			DPRINTF("kp_sigignore="
55211.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55221.99Skamil			    PRIx32 "\n",
55231.99Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
55241.99Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
55251.1Skamil
55261.99Skamil			DPRINTF("kp.p_sigignore="
55271.99Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
55281.99Skamil			    PRIx32 "\n",
55291.99Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
55301.99Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
55311.1Skamil
55321.99Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
55331.99Skamil			    sizeof(kp_sigignore)));
55341.99Skamil		}
55351.1Skamil
55361.99Skamil		SYSCALL_REQUIRE(
55371.99Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55381.99Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
55391.1Skamil
55401.99Skamil		child2 = state.pe_other_pid;
55411.99Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
55421.99Skamil		    child2);
55431.1Skamil
55441.99Skamil		DPRINTF("Before resuming the child process where it left off "
55451.99Skamil		    "and without signal to be sent\n");
55461.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55471.99Skamil	}
55481.1Skamil
55491.99Skamil	if (trackfork || trackvfork) {
55501.99Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
55511.99Skamil		    "\n", TWAIT_FNAME);
55521.99Skamil		TWAIT_REQUIRE_SUCCESS(
55531.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
55541.1Skamil
55551.99Skamil		validate_status_exited(status, exitval2);
55561.1Skamil
55571.99Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
55581.99Skamil		    "process\n", TWAIT_FNAME);
55591.99Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
55601.99Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
55611.99Skamil	}
55621.1Skamil
55631.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
55641.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
55651.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55661.1Skamil
55671.1Skamil	validate_status_stopped(status, SIGCHLD);
55681.1Skamil
55691.57Skamil	DPRINTF("Before resuming the child process where it left off and "
55701.1Skamil	    "without signal to be sent\n");
55711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55721.1Skamil
55731.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55741.1Skamil	    TWAIT_FNAME);
55751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55761.1Skamil
55771.1Skamil	validate_status_exited(status, exitval);
55781.1Skamil
55791.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55801.57Skamil	    TWAIT_FNAME);
55811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55821.1Skamil}
55831.1Skamil
55841.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone,		\
55851.99Skamil                   masked,ignored)					\
55861.99SkamilATF_TC(name);								\
55871.99SkamilATF_TC_HEAD(name, tc)							\
55881.99Skamil{									\
55891.99Skamil	atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught "	\
55901.99Skamil	    "regardless of signal %s%s", 				\
55911.99Skamil	    trackfork ? "PTRACE_FORK" : "",				\
55921.99Skamil	    trackvfork ? "PTRACE_VFORK" : "",				\
55931.99Skamil	    trackvforkdone ? "PTRACE_VFORK_DONE" : "",			\
55941.99Skamil	    masked ? "masked" : "", ignored ? "ignored" : "");		\
55951.99Skamil}									\
55961.99Skamil									\
55971.99SkamilATF_TC_BODY(name, tc)							\
55981.99Skamil{									\
55991.99Skamil									\
56001.99Skamil	fork2_body(trackfork, trackvfork, trackvforkdone, masked,	\
56011.99Skamil	           ignored);						\
56021.1Skamil}
56031.1Skamil
56041.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false)
56051.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true)
56061.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false)
56071.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true)
56081.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false)
56091.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true)
56101.1Skamil#endif
56111.1Skamil
56121.99Skamil/// ----------------------------------------------------------------------------
56131.1Skamil
56141.83Skamilvolatile lwpid_t the_lwp_id = 0;
56151.83Skamil
56161.83Skamilstatic void
56171.83Skamillwp_main_func(void *arg)
56181.83Skamil{
56191.83Skamil	the_lwp_id = _lwp_self();
56201.83Skamil	_lwp_exit();
56211.83Skamil}
56221.83Skamil
56231.1SkamilATF_TC(signal9);
56241.1SkamilATF_TC_HEAD(signal9, tc)
56251.1Skamil{
56261.1Skamil	atf_tc_set_md_var(tc, "descr",
56271.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
56281.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
56291.1Skamil}
56301.1Skamil
56311.1SkamilATF_TC_BODY(signal9, tc)
56321.1Skamil{
56331.1Skamil	const int exitval = 5;
56341.1Skamil	const int sigval = SIGSTOP;
56351.1Skamil	const int sigmasked = SIGTRAP;
56361.1Skamil	pid_t child, wpid;
56371.1Skamil#if defined(TWAIT_HAVE_STATUS)
56381.1Skamil	int status;
56391.1Skamil#endif
56401.1Skamil	sigset_t intmask;
56411.1Skamil	ptrace_state_t state;
56421.1Skamil	const int slen = sizeof(state);
56431.1Skamil	ptrace_event_t event;
56441.1Skamil	const int elen = sizeof(event);
56451.1Skamil	ucontext_t uc;
56461.1Skamil	lwpid_t lid;
56471.1Skamil	static const size_t ssize = 16*1024;
56481.1Skamil	void *stack;
56491.1Skamil
56501.14Schristos	atf_tc_expect_fail("PR kern/51918");
56511.14Schristos
56521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56541.1Skamil	if (child == 0) {
56551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56571.1Skamil
56581.1Skamil		sigemptyset(&intmask);
56591.1Skamil		sigaddset(&intmask, sigmasked);
56601.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56611.1Skamil
56621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56641.1Skamil
56651.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
56661.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
56671.1Skamil
56681.13Schristos		DPRINTF("Before making context for new lwp in child\n");
56691.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
56701.1Skamil
56711.13Schristos		DPRINTF("Before creating new in child\n");
56721.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
56731.1Skamil
56741.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
56751.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
56761.1Skamil
56771.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
56781.1Skamil		    "are the same\n", lid, the_lwp_id);
56791.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
56801.1Skamil
56811.13Schristos		DPRINTF("Before exiting of the child process\n");
56821.1Skamil		_exit(exitval);
56831.1Skamil	}
56841.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56851.1Skamil
56861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56881.1Skamil
56891.1Skamil	validate_status_stopped(status, sigval);
56901.1Skamil
56911.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
56921.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
56931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
56941.1Skamil
56951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56961.1Skamil	    "without signal to be sent\n");
56971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56981.1Skamil
56991.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
57001.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
57011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57021.1Skamil
57031.1Skamil	validate_status_stopped(status, sigmasked);
57041.1Skamil
57051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
57061.1Skamil
57071.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
57081.1Skamil
57091.1Skamil	lid = state.pe_lwp;
57101.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
57111.1Skamil
57121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57131.1Skamil	    "without signal to be sent\n");
57141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57151.1Skamil
57161.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
57171.1Skamil	    TWAIT_FNAME);
57181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57191.1Skamil
57201.1Skamil	validate_status_exited(status, exitval);
57211.1Skamil
57221.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
57231.1Skamil	    TWAIT_FNAME);
57241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57251.1Skamil}
57261.1Skamil
57271.1SkamilATF_TC(signal10);
57281.1SkamilATF_TC_HEAD(signal10, tc)
57291.1Skamil{
57301.1Skamil	atf_tc_set_md_var(tc, "descr",
57311.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57321.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
57331.1Skamil}
57341.1Skamil
57351.1SkamilATF_TC_BODY(signal10, tc)
57361.1Skamil{
57371.1Skamil	const int exitval = 5;
57381.1Skamil	const int sigval = SIGSTOP;
57391.1Skamil	const int sigmasked = SIGTRAP;
57401.1Skamil	pid_t child, wpid;
57411.1Skamil#if defined(TWAIT_HAVE_STATUS)
57421.1Skamil	int status;
57431.1Skamil#endif
57441.1Skamil	sigset_t intmask;
57451.1Skamil	ptrace_state_t state;
57461.1Skamil	const int slen = sizeof(state);
57471.1Skamil	ptrace_event_t event;
57481.1Skamil	const int elen = sizeof(event);
57491.1Skamil	ucontext_t uc;
57501.1Skamil	lwpid_t lid;
57511.1Skamil	static const size_t ssize = 16*1024;
57521.1Skamil	void *stack;
57531.1Skamil
57541.14Schristos	atf_tc_expect_fail("PR kern/51918");
57551.14Schristos
57561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57581.1Skamil	if (child == 0) {
57591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57611.1Skamil
57621.1Skamil		sigemptyset(&intmask);
57631.1Skamil		sigaddset(&intmask, sigmasked);
57641.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57651.1Skamil
57661.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57671.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57681.1Skamil
57691.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
57701.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
57711.1Skamil
57721.13Schristos		DPRINTF("Before making context for new lwp in child\n");
57731.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
57741.1Skamil
57751.13Schristos		DPRINTF("Before creating new in child\n");
57761.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
57771.1Skamil
57781.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
57791.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
57801.1Skamil
57811.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
57821.1Skamil		    "are the same\n", lid, the_lwp_id);
57831.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
57841.1Skamil
57851.13Schristos		DPRINTF("Before exiting of the child process\n");
57861.1Skamil		_exit(exitval);
57871.1Skamil	}
57881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57891.1Skamil
57901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57921.1Skamil
57931.1Skamil	validate_status_stopped(status, sigval);
57941.1Skamil
57951.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
57961.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
57971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
57981.1Skamil
57991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58001.1Skamil	    "without signal to be sent\n");
58011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58021.1Skamil
58031.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
58041.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
58051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58061.1Skamil
58071.1Skamil	validate_status_stopped(status, sigmasked);
58081.1Skamil
58091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
58101.1Skamil
58111.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
58121.1Skamil
58131.1Skamil	lid = state.pe_lwp;
58141.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
58151.1Skamil
58161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58171.1Skamil	    "without signal to be sent\n");
58181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58191.1Skamil
58201.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
58211.1Skamil	    TWAIT_FNAME);
58221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58231.1Skamil
58241.1Skamil	validate_status_exited(status, exitval);
58251.1Skamil
58261.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
58271.1Skamil	    TWAIT_FNAME);
58281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58291.1Skamil}
58301.1Skamil
58311.1Skamilstatic void
58321.1Skamillwp_main_stop(void *arg)
58331.1Skamil{
58341.1Skamil	the_lwp_id = _lwp_self();
58351.1Skamil
58361.1Skamil	raise(SIGTRAP);
58371.1Skamil
58381.1Skamil	_lwp_exit();
58391.1Skamil}
58401.1Skamil
58411.1SkamilATF_TC(suspend1);
58421.1SkamilATF_TC_HEAD(suspend1, tc)
58431.1Skamil{
58441.1Skamil	atf_tc_set_md_var(tc, "descr",
58451.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
58461.1Skamil	    "resumed by a tracee");
58471.1Skamil}
58481.1Skamil
58491.1SkamilATF_TC_BODY(suspend1, tc)
58501.1Skamil{
58511.1Skamil	const int exitval = 5;
58521.1Skamil	const int sigval = SIGSTOP;
58531.1Skamil	pid_t child, wpid;
58541.1Skamil#if defined(TWAIT_HAVE_STATUS)
58551.1Skamil	int status;
58561.1Skamil#endif
58571.1Skamil	ucontext_t uc;
58581.1Skamil	lwpid_t lid;
58591.1Skamil	static const size_t ssize = 16*1024;
58601.1Skamil	void *stack;
58611.1Skamil	struct ptrace_lwpinfo pl;
58621.1Skamil	struct ptrace_siginfo psi;
58631.1Skamil	volatile int go = 0;
58641.1Skamil
58651.17Skamil	// Feature pending for refactoring
58661.17Skamil	atf_tc_expect_fail("PR kern/51995");
58671.17Skamil
58681.16Skamil	// Hangs with qemu
58691.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
58701.16Skamil
58711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58731.1Skamil	if (child == 0) {
58741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58761.1Skamil
58771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58791.1Skamil
58801.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
58811.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
58821.1Skamil
58831.13Schristos		DPRINTF("Before making context for new lwp in child\n");
58841.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
58851.1Skamil
58861.13Schristos		DPRINTF("Before creating new in child\n");
58871.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
58881.1Skamil
58891.1Skamil		while (go == 0)
58901.1Skamil			continue;
58911.1Skamil
58921.1Skamil		raise(SIGINT);
58931.1Skamil
58941.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
58951.1Skamil
58961.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
58971.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
58981.1Skamil
58991.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
59001.1Skamil		    "are the same\n", lid, the_lwp_id);
59011.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
59021.1Skamil
59031.13Schristos		DPRINTF("Before exiting of the child process\n");
59041.1Skamil		_exit(exitval);
59051.1Skamil	}
59061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59071.1Skamil
59081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59101.1Skamil
59111.1Skamil	validate_status_stopped(status, sigval);
59121.1Skamil
59131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59141.1Skamil	    "without signal to be sent\n");
59151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59161.1Skamil
59171.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59181.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
59191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59201.1Skamil
59211.1Skamil	validate_status_stopped(status, SIGTRAP);
59221.1Skamil
59231.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
59241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
59251.1Skamil
59261.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
59271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
59281.1Skamil
59291.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
59301.1Skamil	    child, getpid());
59311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
59321.1Skamil
59331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59341.1Skamil	    "without signal to be sent\n");
59351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59361.1Skamil
59371.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59381.1Skamil	    "SIGINT\n", TWAIT_FNAME);
59391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59401.1Skamil
59411.1Skamil	validate_status_stopped(status, SIGINT);
59421.1Skamil
59431.1Skamil	pl.pl_lwpid = 0;
59441.1Skamil
59451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
59461.1Skamil	while (pl.pl_lwpid != 0) {
59471.1Skamil
59481.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
59491.1Skamil		switch (pl.pl_lwpid) {
59501.1Skamil		case 1:
59511.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
59521.1Skamil			break;
59531.1Skamil		case 2:
59541.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
59551.1Skamil			break;
59561.1Skamil		}
59571.1Skamil	}
59581.1Skamil
59591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59601.1Skamil	    "without signal to be sent\n");
59611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59621.1Skamil
59631.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59641.1Skamil	    TWAIT_FNAME);
59651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59661.1Skamil
59671.1Skamil	validate_status_exited(status, exitval);
59681.1Skamil
59691.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59701.1Skamil	    TWAIT_FNAME);
59711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59721.1Skamil}
59731.1Skamil
59741.1SkamilATF_TC(suspend2);
59751.1SkamilATF_TC_HEAD(suspend2, tc)
59761.1Skamil{
59771.1Skamil	atf_tc_set_md_var(tc, "descr",
59781.1Skamil	    "Verify that the while the only thread within a process is "
59791.1Skamil	    "suspended, the whole process cannot be unstopped");
59801.1Skamil}
59811.1Skamil
59821.1SkamilATF_TC_BODY(suspend2, tc)
59831.1Skamil{
59841.1Skamil	const int exitval = 5;
59851.1Skamil	const int sigval = SIGSTOP;
59861.1Skamil	pid_t child, wpid;
59871.1Skamil#if defined(TWAIT_HAVE_STATUS)
59881.1Skamil	int status;
59891.1Skamil#endif
59901.1Skamil	struct ptrace_siginfo psi;
59911.1Skamil
59921.17Skamil	// Feature pending for refactoring
59931.17Skamil	atf_tc_expect_fail("PR kern/51995");
59941.17Skamil
59951.16Skamil	// Hangs with qemu
59961.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
59971.16Skamil
59981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60001.1Skamil	if (child == 0) {
60011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60031.1Skamil
60041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60061.1Skamil
60071.13Schristos		DPRINTF("Before exiting of the child process\n");
60081.1Skamil		_exit(exitval);
60091.1Skamil	}
60101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60111.1Skamil
60121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60141.1Skamil
60151.1Skamil	validate_status_stopped(status, sigval);
60161.1Skamil
60171.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
60181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
60191.1Skamil
60201.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
60211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
60221.1Skamil
60231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60241.1Skamil	    "without signal to be sent\n");
60251.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
60261.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
60271.1Skamil
60281.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
60291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
60301.1Skamil
60311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60321.1Skamil	    "without signal to be sent\n");
60331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60341.1Skamil
60351.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60361.1Skamil	    TWAIT_FNAME);
60371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60381.1Skamil
60391.1Skamil	validate_status_exited(status, exitval);
60401.1Skamil
60411.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60421.1Skamil	    TWAIT_FNAME);
60431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60441.1Skamil}
60451.1Skamil
60461.1SkamilATF_TC(resume1);
60471.1SkamilATF_TC_HEAD(resume1, tc)
60481.1Skamil{
60491.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
60501.1Skamil	atf_tc_set_md_var(tc, "descr",
60511.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
60521.1Skamil	    "resumed by the debugger");
60531.1Skamil}
60541.1Skamil
60551.1SkamilATF_TC_BODY(resume1, tc)
60561.1Skamil{
60571.1Skamil	struct msg_fds fds;
60581.1Skamil	const int exitval = 5;
60591.1Skamil	const int sigval = SIGSTOP;
60601.1Skamil	pid_t child, wpid;
60611.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
60621.1Skamil#if defined(TWAIT_HAVE_STATUS)
60631.1Skamil	int status;
60641.1Skamil#endif
60651.1Skamil	ucontext_t uc;
60661.1Skamil	lwpid_t lid;
60671.1Skamil	static const size_t ssize = 16*1024;
60681.1Skamil	void *stack;
60691.1Skamil	struct ptrace_lwpinfo pl;
60701.1Skamil	struct ptrace_siginfo psi;
60711.1Skamil
60721.17Skamil	// Feature pending for refactoring
60731.17Skamil	atf_tc_expect_fail("PR kern/51995");
60741.17Skamil
60751.15Schristos	// Hangs with qemu
60761.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
60771.1Skamil
60781.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
60791.1Skamil
60801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60821.1Skamil	if (child == 0) {
60831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60851.1Skamil
60861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60881.1Skamil
60891.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
60901.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
60911.1Skamil
60921.13Schristos		DPRINTF("Before making context for new lwp in child\n");
60931.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
60941.1Skamil
60951.13Schristos		DPRINTF("Before creating new in child\n");
60961.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
60971.1Skamil
60981.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
60991.1Skamil
61001.1Skamil		raise(SIGINT);
61011.1Skamil
61021.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
61031.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
61041.1Skamil
61051.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
61061.1Skamil		    "are the same\n", lid, the_lwp_id);
61071.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
61081.1Skamil
61091.13Schristos		DPRINTF("Before exiting of the child process\n");
61101.1Skamil		_exit(exitval);
61111.1Skamil	}
61121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61131.1Skamil
61141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61161.1Skamil
61171.1Skamil	validate_status_stopped(status, sigval);
61181.1Skamil
61191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61201.1Skamil	    "without signal to be sent\n");
61211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61221.1Skamil
61231.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61241.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
61251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61261.1Skamil
61271.1Skamil	validate_status_stopped(status, SIGTRAP);
61281.1Skamil
61291.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
61301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
61311.1Skamil
61321.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
61331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
61341.1Skamil
61351.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
61361.1Skamil
61371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61381.1Skamil	    "without signal to be sent\n");
61391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61401.1Skamil
61411.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61421.1Skamil	    "SIGINT\n", TWAIT_FNAME);
61431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61441.1Skamil
61451.1Skamil	validate_status_stopped(status, SIGINT);
61461.1Skamil
61471.1Skamil	pl.pl_lwpid = 0;
61481.1Skamil
61491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
61501.1Skamil	while (pl.pl_lwpid != 0) {
61511.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
61521.1Skamil		switch (pl.pl_lwpid) {
61531.1Skamil		case 1:
61541.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
61551.1Skamil			break;
61561.1Skamil		case 2:
61571.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
61581.1Skamil			break;
61591.1Skamil		}
61601.1Skamil	}
61611.1Skamil
61621.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
61631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
61641.1Skamil
61651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61661.1Skamil	    "without signal to be sent\n");
61671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61681.1Skamil
61691.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61701.1Skamil	    TWAIT_FNAME);
61711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61721.1Skamil
61731.1Skamil	validate_status_exited(status, exitval);
61741.1Skamil
61751.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61761.1Skamil	    TWAIT_FNAME);
61771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61781.1Skamil
61791.1Skamil	msg_close(&fds);
61801.1Skamil
61811.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
61821.1Skamil	sleep(10);
61831.1Skamil}
61841.1Skamil
61851.1SkamilATF_TC(syscall1);
61861.1SkamilATF_TC_HEAD(syscall1, tc)
61871.1Skamil{
61881.1Skamil	atf_tc_set_md_var(tc, "descr",
61891.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
61901.1Skamil}
61911.1Skamil
61921.1SkamilATF_TC_BODY(syscall1, tc)
61931.1Skamil{
61941.1Skamil	const int exitval = 5;
61951.1Skamil	const int sigval = SIGSTOP;
61961.1Skamil	pid_t child, wpid;
61971.1Skamil#if defined(TWAIT_HAVE_STATUS)
61981.1Skamil	int status;
61991.1Skamil#endif
62001.1Skamil	struct ptrace_siginfo info;
62011.1Skamil	memset(&info, 0, sizeof(info));
62021.1Skamil
62031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62051.1Skamil	if (child == 0) {
62061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62081.1Skamil
62091.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62101.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62111.1Skamil
62121.1Skamil		syscall(SYS_getpid);
62131.1Skamil
62141.13Schristos		DPRINTF("Before exiting of the child process\n");
62151.1Skamil		_exit(exitval);
62161.1Skamil	}
62171.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62181.1Skamil
62191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62211.1Skamil
62221.1Skamil	validate_status_stopped(status, sigval);
62231.1Skamil
62241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62251.1Skamil	    "without signal to be sent\n");
62261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
62271.1Skamil
62281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62301.1Skamil
62311.1Skamil	validate_status_stopped(status, SIGTRAP);
62321.1Skamil
62331.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
62341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
62351.1Skamil
62361.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
62371.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
62381.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
62391.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
62401.1Skamil
62411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62421.1Skamil	    "without signal to be sent\n");
62431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
62441.1Skamil
62451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62471.1Skamil
62481.1Skamil	validate_status_stopped(status, SIGTRAP);
62491.1Skamil
62501.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
62511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
62521.1Skamil
62531.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
62541.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
62551.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
62561.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
62571.1Skamil
62581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62591.1Skamil	    "without signal to be sent\n");
62601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62611.1Skamil
62621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62641.1Skamil
62651.1Skamil	validate_status_exited(status, exitval);
62661.1Skamil
62671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62691.1Skamil}
62701.1Skamil
62711.1SkamilATF_TC(syscallemu1);
62721.1SkamilATF_TC_HEAD(syscallemu1, tc)
62731.1Skamil{
62741.1Skamil	atf_tc_set_md_var(tc, "descr",
62751.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
62761.1Skamil}
62771.1Skamil
62781.1SkamilATF_TC_BODY(syscallemu1, tc)
62791.1Skamil{
62801.1Skamil	const int exitval = 5;
62811.1Skamil	const int sigval = SIGSTOP;
62821.1Skamil	pid_t child, wpid;
62831.1Skamil#if defined(TWAIT_HAVE_STATUS)
62841.1Skamil	int status;
62851.1Skamil#endif
62861.1Skamil
62871.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
62881.6Skamil	/* syscallemu does not work on sparc (32-bit) */
62891.6Skamil	atf_tc_expect_fail("PR kern/52166");
62901.6Skamil#endif
62911.6Skamil
62921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62941.1Skamil	if (child == 0) {
62951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62971.1Skamil
62981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63001.1Skamil
63011.1Skamil		syscall(SYS_exit, 100);
63021.1Skamil
63031.13Schristos		DPRINTF("Before exiting of the child process\n");
63041.1Skamil		_exit(exitval);
63051.1Skamil	}
63061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63071.1Skamil
63081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63101.1Skamil
63111.1Skamil	validate_status_stopped(status, sigval);
63121.1Skamil
63131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63141.1Skamil	    "without signal to be sent\n");
63151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
63161.1Skamil
63171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63191.1Skamil
63201.1Skamil	validate_status_stopped(status, SIGTRAP);
63211.1Skamil
63221.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
63231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
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("Before resuming the child process where it left off and "
63351.1Skamil	    "without signal to be sent\n");
63361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63371.1Skamil
63381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63401.1Skamil
63411.1Skamil	validate_status_exited(status, exitval);
63421.1Skamil
63431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63451.1Skamil}
63461.1Skamil
63471.103Skamil/// ----------------------------------------------------------------------------
63481.103Skamil
63491.106Skamilstatic void
63501.106Skamilclone_body(int flags, bool trackfork, bool trackvfork,
63511.106Skamil    bool trackvforkdone)
63521.106Skamil{
63531.106Skamil	const int exitval = 5;
63541.106Skamil	const int exitval2 = 15;
63551.106Skamil	const int sigval = SIGSTOP;
63561.106Skamil	pid_t child, child2 = 0, wpid;
63571.106Skamil#if defined(TWAIT_HAVE_STATUS)
63581.106Skamil	int status;
63591.106Skamil#endif
63601.106Skamil	ptrace_state_t state;
63611.106Skamil	const int slen = sizeof(state);
63621.106Skamil	ptrace_event_t event;
63631.106Skamil	const int elen = sizeof(event);
63641.106Skamil
63651.106Skamil	const size_t stack_size = 1024 * 1024;
63661.106Skamil	void *stack, *stack_base;
63671.106Skamil
63681.106Skamil	stack = malloc(stack_size);
63691.106Skamil	ATF_REQUIRE(stack != NULL);
63701.106Skamil
63711.106Skamil#ifdef __MACHINE_STACK_GROWS_UP
63721.106Skamil	stack_base = stack;
63731.106Skamil#else
63741.106Skamil	stack_base = (char *)stack + stack_size;
63751.106Skamil#endif
63761.106Skamil
63771.106Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
63781.106Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
63791.106Skamil	if (child == 0) {
63801.106Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63811.106Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63821.106Skamil
63831.106Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63841.106Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63851.106Skamil
63861.106Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
63871.106Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
63881.106Skamil
63891.106Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
63901.106Skamil		    child2);
63911.106Skamil
63921.106Skamil		// XXX WALLSIG?
63931.106Skamil		FORKEE_REQUIRE_SUCCESS
63941.106Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
63951.106Skamil
63961.106Skamil		forkee_status_exited(status, exitval2);
63971.106Skamil
63981.106Skamil		DPRINTF("Before exiting of the child process\n");
63991.106Skamil		_exit(exitval);
64001.106Skamil	}
64011.106Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64021.106Skamil
64031.106Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64041.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64051.106Skamil
64061.106Skamil	validate_status_stopped(status, sigval);
64071.106Skamil
64081.106Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
64091.106Skamil	    trackfork ? "|PTRACE_FORK" : "",
64101.106Skamil	    trackvfork ? "|PTRACE_VFORK" : "",
64111.106Skamil	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
64121.106Skamil	event.pe_set_event = 0;
64131.106Skamil	if (trackfork)
64141.106Skamil		event.pe_set_event |= PTRACE_FORK;
64151.106Skamil	if (trackvfork)
64161.106Skamil		event.pe_set_event |= PTRACE_VFORK;
64171.106Skamil	if (trackvforkdone)
64181.106Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
64191.106Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
64201.106Skamil
64211.106Skamil	DPRINTF("Before resuming the child process where it left off and "
64221.106Skamil	    "without signal to be sent\n");
64231.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64241.106Skamil
64251.106Skamil#if defined(TWAIT_HAVE_PID)
64261.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
64271.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
64281.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
64291.106Skamil		    child);
64301.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
64311.106Skamil		    child);
64321.106Skamil
64331.106Skamil		validate_status_stopped(status, SIGTRAP);
64341.106Skamil
64351.106Skamil		SYSCALL_REQUIRE(
64361.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
64371.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
64381.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
64391.106Skamil			       PTRACE_FORK);
64401.106Skamil		}
64411.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
64421.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
64431.106Skamil			       PTRACE_VFORK);
64441.106Skamil		}
64451.106Skamil
64461.106Skamil		child2 = state.pe_other_pid;
64471.106Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
64481.106Skamil
64491.106Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
64501.106Skamil		    "%d\n", TWAIT_FNAME, child2, child);
64511.106Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
64521.106Skamil		    child2);
64531.106Skamil
64541.106Skamil		validate_status_stopped(status, SIGTRAP);
64551.106Skamil
64561.106Skamil		SYSCALL_REQUIRE(
64571.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
64581.106Skamil		if (trackfork && !(flags & CLONE_VFORK)) {
64591.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
64601.106Skamil			       PTRACE_FORK);
64611.106Skamil		}
64621.106Skamil		if (trackvfork && (flags & CLONE_VFORK)) {
64631.106Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
64641.106Skamil			       PTRACE_VFORK);
64651.106Skamil		}
64661.106Skamil
64671.106Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
64681.106Skamil
64691.106Skamil		DPRINTF("Before resuming the forkee process where it left off "
64701.106Skamil		    "and without signal to be sent\n");
64711.106Skamil		SYSCALL_REQUIRE(
64721.106Skamil		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
64731.106Skamil
64741.106Skamil		DPRINTF("Before resuming the child process where it left off "
64751.106Skamil		    "and without signal to be sent\n");
64761.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64771.106Skamil	}
64781.106Skamil#endif
64791.106Skamil
64801.106Skamil	if (trackvforkdone && (flags & CLONE_VFORK)) {
64811.106Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
64821.106Skamil		    child);
64831.106Skamil		TWAIT_REQUIRE_SUCCESS(
64841.106Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
64851.106Skamil
64861.106Skamil		validate_status_stopped(status, SIGTRAP);
64871.106Skamil
64881.106Skamil		SYSCALL_REQUIRE(
64891.106Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
64901.106Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
64911.106Skamil
64921.106Skamil		child2 = state.pe_other_pid;
64931.106Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
64941.106Skamil		    child2);
64951.106Skamil
64961.106Skamil		DPRINTF("Before resuming the child process where it left off "
64971.106Skamil		    "and without signal to be sent\n");
64981.106Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64991.106Skamil	}
65001.106Skamil
65011.103Skamil#if defined(TWAIT_HAVE_PID)
65021.106Skamil	if ((trackfork && !(flags & CLONE_VFORK)) ||
65031.106Skamil	    (trackvfork && (flags & CLONE_VFORK))) {
65041.106Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
65051.106Skamil		    "\n", TWAIT_FNAME);
65061.106Skamil		TWAIT_REQUIRE_SUCCESS(
65071.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
65081.106Skamil
65091.106Skamil		validate_status_exited(status, exitval2);
65101.106Skamil
65111.106Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
65121.106Skamil		    "process\n", TWAIT_FNAME);
65131.106Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
65141.106Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
65151.106Skamil	}
65161.106Skamil#endif
65171.106Skamil
65181.106Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
65191.106Skamil	    "SIGCHLD\n", TWAIT_FNAME);
65201.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65211.106Skamil
65221.106Skamil	validate_status_stopped(status, SIGCHLD);
65231.106Skamil
65241.106Skamil	DPRINTF("Before resuming the child process where it left off and "
65251.106Skamil	    "without signal to be sent\n");
65261.106Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65271.106Skamil
65281.106Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
65291.106Skamil	    TWAIT_FNAME);
65301.106Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65311.106Skamil
65321.106Skamil	validate_status_exited(status, exitval);
65331.103Skamil
65341.106Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
65351.106Skamil	    TWAIT_FNAME);
65361.106Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65371.106Skamil}
65381.103Skamil
65391.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone)			\
65401.106SkamilATF_TC(name);								\
65411.106SkamilATF_TC_HEAD(name, tc)							\
65421.106Skamil{									\
65431.106Skamil	atf_tc_set_md_var(tc, "descr", "Verify clone(%s) "		\
65441.106Skamil	    "called with 0%s%s%s in EVENT_MASK",			\
65451.106Skamil	    #flags,							\
65461.106Skamil	    tfork ? "|PTRACE_FORK" : "",				\
65471.106Skamil	    tvfork ? "|PTRACE_VFORK" : "",				\
65481.106Skamil	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
65491.106Skamil}									\
65501.106Skamil									\
65511.106SkamilATF_TC_BODY(name, tc)							\
65521.106Skamil{									\
65531.106Skamil									\
65541.106Skamil	clone_body(flags, tfork, tvfork, tvforkdone);			\
65551.103Skamil}
65561.103Skamil
65571.106SkamilCLONE_TEST(clone1, 0, false, false, false)
65581.106Skamil#if defined(TWAIT_HAVE_PID)
65591.106SkamilCLONE_TEST(clone2, 0, true, false, false)
65601.106SkamilCLONE_TEST(clone3, 0, false, true, false)
65611.106SkamilCLONE_TEST(clone4, 0, true, true, false)
65621.106Skamil#endif
65631.106SkamilCLONE_TEST(clone5, 0, false, false, true)
65641.106Skamil#if defined(TWAIT_HAVE_PID)
65651.106SkamilCLONE_TEST(clone6, 0, true, false, true)
65661.106SkamilCLONE_TEST(clone7, 0, false, true, true)
65671.106SkamilCLONE_TEST(clone8, 0, true, true, true)
65681.106Skamil#endif
65691.106Skamil
65701.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false)
65711.106Skamil#if defined(TWAIT_HAVE_PID)
65721.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false)
65731.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false)
65741.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false)
65751.106Skamil#endif
65761.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true)
65771.106Skamil#if defined(TWAIT_HAVE_PID)
65781.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true)
65791.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true)
65801.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true)
65811.106Skamil#endif
65821.106Skamil
65831.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false)
65841.106Skamil#if defined(TWAIT_HAVE_PID)
65851.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false)
65861.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false)
65871.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false)
65881.106Skamil#endif
65891.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true)
65901.106Skamil#if defined(TWAIT_HAVE_PID)
65911.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true)
65921.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true)
65931.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true)
65941.106Skamil#endif
65951.106Skamil
65961.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false)
65971.106Skamil#if defined(TWAIT_HAVE_PID)
65981.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false)
65991.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false)
66001.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false)
66011.106Skamil#endif
66021.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true)
66031.106Skamil#if defined(TWAIT_HAVE_PID)
66041.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true)
66051.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true)
66061.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true)
66071.106Skamil#endif
66081.106Skamil
66091.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false)
66101.106Skamil#if defined(TWAIT_HAVE_PID)
66111.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false)
66121.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false)
66131.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false)
66141.106Skamil#endif
66151.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true)
66161.106Skamil#if defined(TWAIT_HAVE_PID)
66171.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true)
66181.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true)
66191.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true)
66201.106Skamil#endif
66211.106Skamil
66221.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false)
66231.106Skamil#if defined(TWAIT_HAVE_PID)
66241.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false)
66251.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false)
66261.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false)
66271.106Skamil#endif
66281.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true)
66291.106Skamil#if defined(TWAIT_HAVE_PID)
66301.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true)
66311.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true)
66321.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true)
66331.106Skamil#endif
66341.106Skamil
66351.106Skamil/// ----------------------------------------------------------------------------
66361.106Skamil
66371.106Skamil#if defined(TWAIT_HAVE_PID)
66381.103Skamilstatic void
66391.106Skamilclone_body2(int flags, bool masked, bool ignored)
66401.103Skamil{
66411.103Skamil	const int exitval = 5;
66421.103Skamil	const int exitval2 = 15;
66431.103Skamil	const int sigval = SIGSTOP;
66441.103Skamil	pid_t child, child2 = 0, wpid;
66451.103Skamil#if defined(TWAIT_HAVE_STATUS)
66461.103Skamil	int status;
66471.103Skamil#endif
66481.103Skamil	ptrace_state_t state;
66491.103Skamil	const int slen = sizeof(state);
66501.103Skamil	ptrace_event_t event;
66511.103Skamil	const int elen = sizeof(event);
66521.103Skamil	struct sigaction sa;
66531.103Skamil	struct ptrace_siginfo info;
66541.103Skamil	sigset_t intmask;
66551.103Skamil	struct kinfo_proc2 kp;
66561.103Skamil	size_t len = sizeof(kp);
66571.103Skamil
66581.103Skamil	int name[6];
66591.103Skamil	const size_t namelen = __arraycount(name);
66601.103Skamil	ki_sigset_t kp_sigmask;
66611.103Skamil	ki_sigset_t kp_sigignore;
66621.103Skamil
66631.103Skamil	const size_t stack_size = 1024 * 1024;
66641.103Skamil	void *stack, *stack_base;
66651.103Skamil
66661.103Skamil	stack = malloc(stack_size);
66671.103Skamil	ATF_REQUIRE(stack != NULL);
66681.103Skamil
66691.103Skamil#ifdef __MACHINE_STACK_GROWS_UP
66701.103Skamil	stack_base = stack;
66711.103Skamil#else
66721.103Skamil	stack_base = (char *)stack + stack_size;
66731.103Skamil#endif
66741.103Skamil
66751.103Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
66761.103Skamil	if (child == 0) {
66771.103Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66781.103Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66791.103Skamil
66801.103Skamil		if (masked) {
66811.103Skamil			sigemptyset(&intmask);
66821.103Skamil			sigaddset(&intmask, SIGTRAP);
66831.103Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
66841.103Skamil		}
66851.103Skamil
66861.103Skamil		if (ignored) {
66871.103Skamil			memset(&sa, 0, sizeof(sa));
66881.103Skamil			sa.sa_handler = SIG_IGN;
66891.103Skamil			sigemptyset(&sa.sa_mask);
66901.103Skamil			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
66911.103Skamil		}
66921.103Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66931.103Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66941.103Skamil
66951.103Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
66961.103Skamil		    flags);
66971.103Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
66981.103Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
66991.103Skamil
67001.103Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
67011.103Skamil		    child2);
67021.103Skamil
67031.103Skamil		// XXX WALLSIG?
67041.103Skamil		FORKEE_REQUIRE_SUCCESS
67051.103Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
67061.103Skamil
67071.103Skamil		forkee_status_exited(status, exitval2);
67081.103Skamil
67091.103Skamil		DPRINTF("Before exiting of the child process\n");
67101.103Skamil		_exit(exitval);
67111.103Skamil	}
67121.103Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67131.103Skamil
67141.103Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67151.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67161.103Skamil
67171.103Skamil	validate_status_stopped(status, sigval);
67181.103Skamil
67191.103Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
67201.103Skamil	SYSCALL_REQUIRE(
67211.103Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
67221.103Skamil
67231.103Skamil	DPRINTF("Before checking siginfo_t\n");
67241.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
67251.103Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
67261.103Skamil
67271.103Skamil	name[0] = CTL_KERN,
67281.103Skamil	name[1] = KERN_PROC2,
67291.103Skamil	name[2] = KERN_PROC_PID;
67301.103Skamil	name[3] = child;
67311.103Skamil	name[4] = sizeof(kp);
67321.103Skamil	name[5] = 1;
67331.103Skamil
67341.103Skamil	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
67351.103Skamil
67361.103Skamil	if (masked)
67371.103Skamil		kp_sigmask = kp.p_sigmask;
67381.103Skamil
67391.103Skamil	if (ignored)
67401.103Skamil		kp_sigignore = kp.p_sigignore;
67411.103Skamil
67421.103Skamil	DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in "
67431.103Skamil	    "EVENT_MASK for the child %d\n", child);
67441.103Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
67451.103Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
67461.103Skamil
67471.103Skamil	DPRINTF("Before resuming the child process where it left off and "
67481.103Skamil	    "without signal to be sent\n");
67491.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67501.103Skamil
67511.103Skamil	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
67521.103Skamil	    child);
67531.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
67541.103Skamil	    child);
67551.103Skamil
67561.103Skamil	validate_status_stopped(status, SIGTRAP);
67571.103Skamil
67581.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
67591.103Skamil
67601.103Skamil	if (masked) {
67611.103Skamil		DPRINTF("kp_sigmask="
67621.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
67631.103Skamil		    PRIx32 "\n",
67641.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
67651.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
67661.103Skamil
67671.103Skamil		DPRINTF("kp.p_sigmask="
67681.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
67691.103Skamil		    PRIx32 "\n",
67701.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
67711.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
67721.103Skamil
67731.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
67741.103Skamil		    sizeof(kp_sigmask)));
67751.103Skamil	}
67761.103Skamil
67771.103Skamil	if (ignored) {
67781.103Skamil		DPRINTF("kp_sigignore="
67791.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
67801.103Skamil		    PRIx32 "\n",
67811.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
67821.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
67831.103Skamil
67841.103Skamil		DPRINTF("kp.p_sigignore="
67851.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
67861.103Skamil		    PRIx32 "\n",
67871.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
67881.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
67891.103Skamil
67901.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
67911.103Skamil		    sizeof(kp_sigignore)));
67921.103Skamil	}
67931.103Skamil
67941.103Skamil	SYSCALL_REQUIRE(
67951.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
67961.103Skamil	DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event,
67971.103Skamil	    child2);
67981.103Skamil	if (!(flags & CLONE_VFORK)) {
67991.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
68001.103Skamil		       PTRACE_FORK);
68011.103Skamil	} else {
68021.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
68031.103Skamil		       PTRACE_VFORK);
68041.103Skamil	}
68051.103Skamil
68061.103Skamil	child2 = state.pe_other_pid;
68071.103Skamil	DPRINTF("Reported ptrace event with forkee %d\n", child2);
68081.103Skamil
68091.103Skamil	DPRINTF("Before calling %s() for the forkee %d of the child "
68101.103Skamil	    "%d\n", TWAIT_FNAME, child2, child);
68111.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
68121.103Skamil	    child2);
68131.103Skamil
68141.103Skamil	validate_status_stopped(status, SIGTRAP);
68151.103Skamil
68161.103Skamil	name[3] = child2;
68171.103Skamil	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
68181.103Skamil
68191.103Skamil	if (masked) {
68201.103Skamil		DPRINTF("kp_sigmask="
68211.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68221.103Skamil		    PRIx32 "\n",
68231.103Skamil		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
68241.103Skamil		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
68251.103Skamil
68261.103Skamil		DPRINTF("kp.p_sigmask="
68271.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68281.103Skamil		    PRIx32 "\n",
68291.103Skamil		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
68301.103Skamil		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
68311.103Skamil
68321.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
68331.103Skamil		    sizeof(kp_sigmask)));
68341.103Skamil	}
68351.103Skamil
68361.103Skamil	if (ignored) {
68371.103Skamil		DPRINTF("kp_sigignore="
68381.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68391.103Skamil		    PRIx32 "\n",
68401.103Skamil		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
68411.103Skamil		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
68421.103Skamil
68431.103Skamil		DPRINTF("kp.p_sigignore="
68441.103Skamil		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68451.103Skamil		    PRIx32 "\n",
68461.103Skamil		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
68471.103Skamil		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
68481.103Skamil
68491.103Skamil		ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
68501.103Skamil		    sizeof(kp_sigignore)));
68511.103Skamil	}
68521.103Skamil
68531.103Skamil	SYSCALL_REQUIRE(
68541.103Skamil	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
68551.103Skamil	if (!(flags & CLONE_VFORK)) {
68561.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
68571.103Skamil		       PTRACE_FORK);
68581.103Skamil	} else {
68591.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
68601.103Skamil		       PTRACE_VFORK);
68611.103Skamil	}
68621.103Skamil
68631.103Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
68641.103Skamil
68651.103Skamil	DPRINTF("Before resuming the forkee process where it left off "
68661.103Skamil	    "and without signal to be sent\n");
68671.103Skamil	SYSCALL_REQUIRE(
68681.103Skamil	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
68691.103Skamil
68701.103Skamil	DPRINTF("Before resuming the child process where it left off "
68711.103Skamil	    "and without signal to be sent\n");
68721.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68731.103Skamil
68741.103Skamil	if (flags & CLONE_VFORK) {
68751.103Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
68761.103Skamil		    child);
68771.103Skamil		TWAIT_REQUIRE_SUCCESS(
68781.103Skamil		    wpid = TWAIT_GENERIC(child, &status, 0), child);
68791.103Skamil
68801.103Skamil		validate_status_stopped(status, SIGTRAP);
68811.103Skamil
68821.103Skamil		name[3] = child;
68831.103Skamil		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
68841.103Skamil
68851.103Skamil		/*
68861.103Skamil		 * SIGCHLD is now pending in the signal queue and
68871.103Skamil		 * the kernel presents it to userland as a masked signal.
68881.103Skamil		 */
68891.103Skamil		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
68901.103Skamil
68911.103Skamil		if (masked) {
68921.103Skamil			DPRINTF("kp_sigmask="
68931.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
68941.103Skamil			    PRIx32 "\n",
68951.103Skamil			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
68961.103Skamil			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
68971.103Skamil
68981.103Skamil			DPRINTF("kp.p_sigmask="
68991.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69001.103Skamil			    PRIx32 "\n",
69011.103Skamil			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
69021.103Skamil			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
69031.103Skamil
69041.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
69051.103Skamil			    sizeof(kp_sigmask)));
69061.103Skamil		}
69071.103Skamil
69081.103Skamil		if (ignored) {
69091.103Skamil			DPRINTF("kp_sigignore="
69101.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69111.103Skamil			    PRIx32 "\n",
69121.103Skamil			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
69131.103Skamil			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
69141.103Skamil
69151.103Skamil			DPRINTF("kp.p_sigignore="
69161.103Skamil			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
69171.103Skamil			    PRIx32 "\n",
69181.103Skamil			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
69191.103Skamil			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
69201.103Skamil
69211.103Skamil			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
69221.103Skamil			    sizeof(kp_sigignore)));
69231.103Skamil		}
69241.103Skamil
69251.103Skamil		SYSCALL_REQUIRE(
69261.103Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
69271.103Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
69281.103Skamil
69291.103Skamil		child2 = state.pe_other_pid;
69301.103Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
69311.103Skamil		    child2);
69321.103Skamil
69331.103Skamil		DPRINTF("Before resuming the child process where it left off "
69341.103Skamil		    "and without signal to be sent\n");
69351.103Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69361.103Skamil	}
69371.103Skamil
69381.103Skamil	DPRINTF("Before calling %s() for the forkee - expected exited"
69391.103Skamil	    "\n", TWAIT_FNAME);
69401.103Skamil	TWAIT_REQUIRE_SUCCESS(
69411.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
69421.103Skamil
69431.103Skamil	validate_status_exited(status, exitval2);
69441.103Skamil
69451.103Skamil	DPRINTF("Before calling %s() for the forkee - expected no "
69461.103Skamil	    "process\n", TWAIT_FNAME);
69471.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
69481.103Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
69491.103Skamil
69501.103Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
69511.103Skamil	    "SIGCHLD\n", TWAIT_FNAME);
69521.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69531.103Skamil
69541.103Skamil	validate_status_stopped(status, SIGCHLD);
69551.103Skamil
69561.103Skamil	DPRINTF("Before resuming the child process where it left off and "
69571.103Skamil	    "without signal to be sent\n");
69581.103Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69591.103Skamil
69601.103Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
69611.103Skamil	    TWAIT_FNAME);
69621.103Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69631.103Skamil
69641.103Skamil	validate_status_exited(status, exitval);
69651.103Skamil
69661.103Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
69671.103Skamil	    TWAIT_FNAME);
69681.103Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69691.103Skamil}
69701.103Skamil
69711.106Skamil#define CLONE_TEST2(name,flags,masked,ignored)				\
69721.103SkamilATF_TC(name);								\
69731.103SkamilATF_TC_HEAD(name, tc)							\
69741.103Skamil{									\
69751.103Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\
69761.103Skamil	    " regardless of signal %s%s", 				\
69771.103Skamil	    #flags, masked ? "masked" : "", ignored ? "ignored" : "");	\
69781.103Skamil}									\
69791.103Skamil									\
69801.103SkamilATF_TC_BODY(name, tc)							\
69811.103Skamil{									\
69821.103Skamil									\
69831.106Skamil	clone_body2(flags, masked, ignored);				\
69841.103Skamil}
69851.103Skamil
69861.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false)
69871.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true)
69881.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false)
69891.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true)
69901.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false)
69911.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true)
69921.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false)
69931.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true)
69941.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX
69951.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true)  // XXX
69961.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false)
69971.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true)
69981.103Skamil#endif
69991.103Skamil
70001.103Skamil/// ----------------------------------------------------------------------------
70011.103Skamil
70021.107Skamil#if defined(TWAIT_HAVE_PID)
70031.107Skamilstatic void
70041.107Skamiltraceme_vfork_clone_body(int flags)
70051.107Skamil{
70061.107Skamil	const int exitval = 5;
70071.107Skamil	const int exitval2 = 15;
70081.107Skamil	pid_t child, child2 = 0, wpid;
70091.107Skamil#if defined(TWAIT_HAVE_STATUS)
70101.107Skamil	int status;
70111.107Skamil#endif
70121.107Skamil
70131.107Skamil	const size_t stack_size = 1024 * 1024;
70141.107Skamil	void *stack, *stack_base;
70151.107Skamil
70161.107Skamil	stack = malloc(stack_size);
70171.107Skamil	ATF_REQUIRE(stack != NULL);
70181.107Skamil
70191.107Skamil#ifdef __MACHINE_STACK_GROWS_UP
70201.107Skamil	stack_base = stack;
70211.107Skamil#else
70221.107Skamil	stack_base = (char *)stack + stack_size;
70231.107Skamil#endif
70241.107Skamil
70251.107Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
70261.107Skamil	if (child == 0) {
70271.107Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
70281.107Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
70291.107Skamil
70301.107Skamil		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
70311.107Skamil		    flags);
70321.107Skamil		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
70331.107Skamil		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
70341.107Skamil
70351.107Skamil		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
70361.107Skamil		    child2);
70371.107Skamil
70381.107Skamil		// XXX WALLSIG?
70391.107Skamil		FORKEE_REQUIRE_SUCCESS
70401.107Skamil		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
70411.107Skamil
70421.107Skamil		forkee_status_exited(status, exitval2);
70431.107Skamil
70441.107Skamil		DPRINTF("Before exiting of the child process\n");
70451.107Skamil		_exit(exitval);
70461.107Skamil	}
70471.107Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
70481.107Skamil
70491.107Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
70501.107Skamil	    TWAIT_FNAME);
70511.107Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
70521.107Skamil
70531.107Skamil	validate_status_exited(status, exitval);
70541.107Skamil
70551.107Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
70561.107Skamil	    TWAIT_FNAME);
70571.107Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
70581.107Skamil}
70591.107Skamil
70601.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags)				\
70611.107SkamilATF_TC(name);								\
70621.107SkamilATF_TC_HEAD(name, tc)							\
70631.107Skamil{									\
70641.107Skamil	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is "	\
70651.107Skamil	    "handled correctly with vfork(2)ed tracer", 		\
70661.107Skamil	    #flags);							\
70671.107Skamil}									\
70681.107Skamil									\
70691.107SkamilATF_TC_BODY(name, tc)							\
70701.107Skamil{									\
70711.107Skamil									\
70721.107Skamil	traceme_vfork_clone_body(flags);				\
70731.107Skamil}
70741.107Skamil
70751.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0)
70761.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM)
70771.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS)
70781.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES)
70791.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND)  // XXX
70801.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK)
70811.107Skamil#endif
70821.107Skamil
70831.107Skamil/// ----------------------------------------------------------------------------
70841.107Skamil
70851.1Skamil#include "t_ptrace_amd64_wait.h"
70861.1Skamil#include "t_ptrace_i386_wait.h"
70871.1Skamil#include "t_ptrace_x86_wait.h"
70881.1Skamil
70891.1SkamilATF_TP_ADD_TCS(tp)
70901.1Skamil{
70911.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
70921.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
70931.33Skamil
70941.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
70951.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
70961.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
70971.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
70981.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
70991.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
71001.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
71011.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
71021.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
71031.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
71041.33Skamil
71051.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
71061.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
71071.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
71081.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
71091.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
71101.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
71111.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
71121.87Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
71131.87Skamil
71141.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
71151.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
71161.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
71171.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
71181.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
71191.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
71201.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
71211.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
71221.86Skamil
71231.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
71241.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
71251.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
71261.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
71271.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
71281.59Skamil
71291.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap);
71301.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv);
71311.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill);
71321.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe);
71331.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus);
71341.88Skamil
71351.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap);
71361.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv);
71371.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill);
71381.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe);
71391.88Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus);
71401.88Skamil
71411.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
71421.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
71431.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
71441.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
71451.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
71461.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
71471.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
71481.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
71491.50Skamil
71501.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
71511.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
71521.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
71531.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
71541.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
71551.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
71561.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
71571.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
71581.50Skamil
71591.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
71601.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
71611.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
71621.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
71631.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
71641.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
71651.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
71661.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
71671.50Skamil
71681.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
71691.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
71701.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
71711.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
71721.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
71731.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
71741.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
71751.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
71761.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
71771.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
71781.1Skamil
71791.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
71801.37Skamil
71811.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
71821.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
71831.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
71841.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
71851.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
71861.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
71871.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
71881.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
71891.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
71901.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
71911.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
71921.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
71931.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
71941.40Skamil
71951.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
71961.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
71971.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
71981.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
71991.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
72001.41Skamil
72011.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap);
72021.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv);
72031.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill);
72041.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe);
72051.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus);
72061.92Skamil
72071.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap);
72081.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv);
72091.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill);
72101.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe);
72111.92Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus);
72121.92Skamil
72131.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
72141.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec);
72151.96Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec);
72161.43Skamil
72171.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
72181.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
72191.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
72201.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
72211.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
72221.59Skamil
72231.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72241.94Skamil	    unrelated_tracer_sees_signalmasked_crash_trap);
72251.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72261.94Skamil	    unrelated_tracer_sees_signalmasked_crash_segv);
72271.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72281.94Skamil	    unrelated_tracer_sees_signalmasked_crash_ill);
72291.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72301.94Skamil	    unrelated_tracer_sees_signalmasked_crash_fpe);
72311.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72321.94Skamil	    unrelated_tracer_sees_signalmasked_crash_bus);
72331.94Skamil
72341.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72351.94Skamil	    unrelated_tracer_sees_signalignored_crash_trap);
72361.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72371.94Skamil	    unrelated_tracer_sees_signalignored_crash_segv);
72381.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72391.94Skamil	    unrelated_tracer_sees_signalignored_crash_ill);
72401.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72411.94Skamil	    unrelated_tracer_sees_signalignored_crash_fpe);
72421.94Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72431.94Skamil	    unrelated_tracer_sees_signalignored_crash_bus);
72441.94Skamil
72451.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
72461.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
72471.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
72481.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
72491.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
72501.51Skamil
72511.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
72521.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
72531.51Skamil
72541.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
72551.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
72561.51Skamil
72571.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72581.51Skamil		tracee_sees_its_original_parent_getppid);
72591.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72601.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
72611.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
72621.51Skamil		tracee_sees_its_original_parent_procfs_status);
72631.1Skamil
72641.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
72651.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
72661.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
72671.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
72681.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
72691.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
72701.1Skamil
72711.31Skamil	ATF_TP_ADD_TC(tp, fork1);
72721.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
72731.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
72741.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
72751.31Skamil	ATF_TP_ADD_TC(tp, fork5);
72761.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
72771.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
72781.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
72791.31Skamil
72801.109Skamil#if TEST_VFORK_ENABLED
72811.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
72821.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
72831.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
72841.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
72851.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
72861.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
72871.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
72881.104Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
72891.1Skamil
72901.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_fork);
72911.108Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_vfork);
72921.109Skamil#endif
72931.108Skamil
72941.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
72951.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
72961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
72971.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
72981.54Skamil
72991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
73001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
73011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
73021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
73031.54Skamil
73041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
73051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
73061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
73071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
73081.54Skamil
73091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
73101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
73111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
73121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
73131.54Skamil
73141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
73151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
73161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
73171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
73181.54Skamil
73191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
73201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
73211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
73221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
73231.54Skamil
73241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
73251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
73261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
73271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
73281.54Skamil
73291.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
73301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
73311.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
73321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
73331.54Skamil
73341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
73351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
73361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
73371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
73381.54Skamil
73391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
73401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
73411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
73421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
73431.1Skamil
73441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
73451.1Skamil
73461.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i);
73471.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d);
73481.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i);
73491.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d);
73501.101Skamil
73511.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i);
73521.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d);
73531.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i);
73541.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d);
73551.101Skamil
73561.101Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv);
73571.101Skamil
73581.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
73591.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
73601.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
73611.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
73621.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
73631.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
73641.1Skamil
73651.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
73661.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
73671.1Skamil
73681.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
73691.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
73701.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
73711.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
73721.1Skamil
73731.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
73741.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
73751.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
73761.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
73771.2Skamil
73781.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked);
73791.95Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored);
73801.95Skamil
73811.1Skamil	ATF_TP_ADD_TC(tp, kill1);
73821.1Skamil	ATF_TP_ADD_TC(tp, kill2);
73831.75Skamil	ATF_TP_ADD_TC(tp, kill3);
73841.1Skamil
73851.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
73861.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
73871.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
73881.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
73891.77Skamil
73901.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
73911.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
73921.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
73931.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
73941.1Skamil
73951.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
73961.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
73971.79Skamil
73981.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
73991.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalmasked_exec);
74001.97Skamil	ATF_TP_ADD_TC(tp, traceme_signalignored_exec);
74011.1Skamil
74021.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
74031.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
74041.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
74051.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
74061.1Skamil
74071.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
74081.84Skamil
74091.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked);
74101.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored);
74111.109Skamil#if TEST_VFORK_ENABLED
74121.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked);
74131.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored);
74141.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked);
74151.99Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored);
74161.109Skamil#endif
74171.99Skamil
74181.1Skamil	ATF_TP_ADD_TC(tp, signal9);
74191.1Skamil	ATF_TP_ADD_TC(tp, signal10);
74201.1Skamil
74211.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
74221.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
74231.1Skamil
74241.1Skamil	ATF_TP_ADD_TC(tp, resume1);
74251.1Skamil
74261.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
74271.1Skamil
74281.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
74291.1Skamil
74301.106Skamil	ATF_TP_ADD_TC(tp, clone1);
74311.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone2);
74321.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone3);
74331.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone4);
74341.106Skamil	ATF_TP_ADD_TC(tp, clone5);
74351.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone6);
74361.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone7);
74371.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone8);
74381.106Skamil
74391.106Skamil	ATF_TP_ADD_TC(tp, clone_vm1);
74401.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2);
74411.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3);
74421.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4);
74431.106Skamil	ATF_TP_ADD_TC(tp, clone_vm5);
74441.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6);
74451.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7);
74461.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8);
74471.106Skamil
74481.106Skamil	ATF_TP_ADD_TC(tp, clone_fs1);
74491.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2);
74501.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3);
74511.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4);
74521.106Skamil	ATF_TP_ADD_TC(tp, clone_fs5);
74531.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6);
74541.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7);
74551.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8);
74561.106Skamil
74571.106Skamil	ATF_TP_ADD_TC(tp, clone_files1);
74581.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2);
74591.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3);
74601.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4);
74611.106Skamil	ATF_TP_ADD_TC(tp, clone_files5);
74621.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6);
74631.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7);
74641.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8);
74651.106Skamil
74661.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand1); // XXX
74671.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX
74681.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX
74691.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX
74701.106Skamil//	ATF_TP_ADD_TC(tp, clone_sighand5); // XXX
74711.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX
74721.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX
74731.106Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX
74741.106Skamil
74751.109Skamil#if TEST_VFORK_ENABLED
74761.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork1);
74771.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2);
74781.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3);
74791.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4);
74801.106Skamil	ATF_TP_ADD_TC(tp, clone_vfork5);
74811.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6);
74821.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7);
74831.106Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8);
74841.109Skamil#endif
74851.106Skamil
74861.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored);
74871.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked);
74881.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored);
74891.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked);
74901.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored);
74911.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked);
74921.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored);
74931.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked);
74941.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX
74951.103Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX
74961.109Skamil#if TEST_VFORK_ENABLED
74971.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored);
74981.103Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked);
74991.109Skamil#endif
75001.103Skamil
75011.109Skamil#if TEST_VFORK_ENABLED
75021.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone);
75031.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm);
75041.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs);
75051.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files);
75061.107Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX
75071.107Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork);
75081.109Skamil#endif
75091.107Skamil
75101.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
75111.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
75121.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
75131.1Skamil
75141.1Skamil	return atf_no_error();
75151.1Skamil}
7516