t_ptrace_wait.c revision 1.86
11.86Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.86 2019/02/14 06:47:32 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.86Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.86 2019/02/14 06:47:32 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.77Skamil#include <pthread.h>
471.1Skamil#include <sched.h>
481.1Skamil#include <signal.h>
491.1Skamil#include <stdint.h>
501.1Skamil#include <stdio.h>
511.1Skamil#include <stdlib.h>
521.1Skamil#include <strings.h>
531.26Skamil#include <time.h>
541.1Skamil#include <unistd.h>
551.1Skamil
561.1Skamil#include <atf-c.h>
571.1Skamil
581.1Skamil#include "h_macros.h"
591.1Skamil
601.1Skamil#include "t_ptrace_wait.h"
611.1Skamil#include "msg.h"
621.1Skamil
631.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
641.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
651.61Skre	sizeof(msg)) == 0)
661.1Skamil
671.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
681.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
691.61Skre	sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
721.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
731.61Skre	sizeof(msg)) == 0)
741.1Skamil
751.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
761.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
771.61Skre	sizeof(msg)) == 0)
781.13Schristos
791.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
801.13Schristos    strerror(errno))
811.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
821.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
831.13Schristos
841.13Schristosstatic int debug = 0;
851.13Schristos
861.13Schristos#define DPRINTF(a, ...)	do  \
871.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
881.13Schristos    while (/*CONSTCOND*/0)
891.1Skamil
901.34Skamil/// ----------------------------------------------------------------------------
911.34Skamil
921.33Skamilstatic void
931.33Skamiltraceme_raise(int sigval)
941.1Skamil{
951.1Skamil	const int exitval = 5;
961.1Skamil	pid_t child, wpid;
971.1Skamil#if defined(TWAIT_HAVE_STATUS)
981.1Skamil	int status;
991.1Skamil#endif
1001.1Skamil
1011.45Skamil	struct ptrace_siginfo info;
1021.45Skamil	memset(&info, 0, sizeof(info));
1031.45Skamil
1041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1061.1Skamil	if (child == 0) {
1071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1091.1Skamil
1101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1121.1Skamil
1131.36Skamil		switch (sigval) {
1141.36Skamil		case SIGKILL:
1151.36Skamil			/* NOTREACHED */
1161.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1171.70Smrg			__unreachable();
1181.36Skamil		default:
1191.36Skamil			DPRINTF("Before exiting of the child process\n");
1201.36Skamil			_exit(exitval);
1211.36Skamil		}
1221.1Skamil	}
1231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1241.1Skamil
1251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1271.1Skamil
1281.36Skamil	switch (sigval) {
1291.36Skamil	case SIGKILL:
1301.36Skamil		validate_status_signaled(status, sigval, 0);
1311.36Skamil		break;
1321.36Skamil	default:
1331.36Skamil		validate_status_stopped(status, sigval);
1341.1Skamil
1351.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1361.61Skre			"child\n");
1371.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1381.61Skre			sizeof(info)) != -1);
1391.45Skamil
1401.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1411.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1421.61Skre			"si_errno=%#x\n",
1431.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1441.61Skre			info.psi_siginfo.si_errno);
1451.45Skamil
1461.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1471.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1481.45Skamil
1491.36Skamil		DPRINTF("Before resuming the child process where it left off "
1501.36Skamil		    "and without signal to be sent\n");
1511.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1521.1Skamil
1531.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1541.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1551.61Skre		    child);
1561.36Skamil		break;
1571.36Skamil	}
1581.1Skamil
1591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1611.1Skamil}
1621.1Skamil
1631.61Skre#define TRACEME_RAISE(test, sig)					\
1641.61SkreATF_TC(test);								\
1651.61SkreATF_TC_HEAD(test, tc)							\
1661.61Skre{									\
1671.61Skre	atf_tc_set_md_var(tc, "descr",					\
1681.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1691.61Skre}									\
1701.61Skre									\
1711.61SkreATF_TC_BODY(test, tc)							\
1721.61Skre{									\
1731.61Skre									\
1741.61Skre	traceme_raise(sig);						\
1751.33Skamil}
1761.33Skamil
1771.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1781.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1791.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1801.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1811.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1821.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1831.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1841.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1851.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
1861.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
1871.33Skamil
1881.34Skamil/// ----------------------------------------------------------------------------
1891.1Skamil
1901.1Skamilstatic void
1911.86Skamiltraceme_raisesignal_masked(int sigmasked)
1921.86Skamil{
1931.86Skamil	const int exitval = 5;
1941.86Skamil	const int sigval = SIGSTOP;
1951.86Skamil	pid_t child, wpid;
1961.86Skamil#if defined(TWAIT_HAVE_STATUS)
1971.86Skamil	int status;
1981.86Skamil#endif
1991.86Skamil	sigset_t intmask;
2001.86Skamil	struct ptrace_siginfo info;
2011.86Skamil
2021.86Skamil	memset(&info, 0, sizeof(info));
2031.86Skamil
2041.86Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2051.86Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2061.86Skamil	if (child == 0) {
2071.86Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2081.86Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2091.86Skamil
2101.86Skamil		sigemptyset(&intmask);
2111.86Skamil		sigaddset(&intmask, sigmasked);
2121.86Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
2131.86Skamil
2141.86Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2151.86Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2161.86Skamil
2171.86Skamil		DPRINTF("Before raising %s breakpoint from child\n",
2181.86Skamil		    strsignal(sigmasked));
2191.86Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
2201.86Skamil
2211.86Skamil		DPRINTF("Before exiting of the child process\n");
2221.86Skamil		_exit(exitval);
2231.86Skamil	}
2241.86Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2251.86Skamil
2261.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2271.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2281.86Skamil
2291.86Skamil	validate_status_stopped(status, sigval);
2301.86Skamil
2311.86Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2321.86Skamil	SYSCALL_REQUIRE(
2331.86Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2341.86Skamil
2351.86Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2361.86Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2371.86Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2381.86Skamil	    info.psi_siginfo.si_errno);
2391.86Skamil
2401.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2411.86Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2421.86Skamil
2431.86Skamil	DPRINTF("Before resuming the child process where it left off and "
2441.86Skamil	    "without signal to be sent\n");
2451.86Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2461.86Skamil
2471.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2481.86Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2491.86Skamil
2501.86Skamil	validate_status_exited(status, exitval);
2511.86Skamil
2521.86Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2531.86Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2541.86Skamil}
2551.86Skamil
2561.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
2571.86SkamilATF_TC(test);								\
2581.86SkamilATF_TC_HEAD(test, tc)							\
2591.86Skamil{									\
2601.86Skamil	atf_tc_set_md_var(tc, "descr",					\
2611.86Skamil	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
2621.86Skamil	    "stops tracer from catching this raised signal");		\
2631.86Skamil}									\
2641.86Skamil									\
2651.86SkamilATF_TC_BODY(test, tc)							\
2661.86Skamil{									\
2671.86Skamil									\
2681.86Skamil	traceme_raisesignal_masked(sig);				\
2691.86Skamil}
2701.86Skamil
2711.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
2721.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
2731.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
2741.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
2751.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
2761.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
2771.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
2781.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
2791.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
2801.86Skamil
2811.86Skamil/// ----------------------------------------------------------------------------
2821.86Skamil
2831.86Skamilstatic void
2841.59Skamiltraceme_crash(int sig)
2851.59Skamil{
2861.59Skamil	pid_t child, wpid;
2871.59Skamil#if defined(TWAIT_HAVE_STATUS)
2881.59Skamil	int status;
2891.59Skamil#endif
2901.59Skamil	struct ptrace_siginfo info;
2911.61Skre
2921.71Skamil#ifndef PTRACE_ILLEGAL_ASM
2931.71Skamil	if (sig == SIGILL)
2941.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
2951.71Skamil#endif
2961.71Skamil
2971.59Skamil	memset(&info, 0, sizeof(info));
2981.59Skamil
2991.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3001.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3011.59Skamil	if (child == 0) {
3021.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3031.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3041.59Skamil
3051.59Skamil		DPRINTF("Before executing a trap\n");
3061.59Skamil		switch (sig) {
3071.59Skamil		case SIGTRAP:
3081.59Skamil			trigger_trap();
3091.59Skamil			break;
3101.59Skamil		case SIGSEGV:
3111.59Skamil			trigger_segv();
3121.59Skamil			break;
3131.59Skamil		case SIGILL:
3141.59Skamil			trigger_ill();
3151.59Skamil			break;
3161.59Skamil		case SIGFPE:
3171.59Skamil			trigger_fpe();
3181.59Skamil			break;
3191.59Skamil		case SIGBUS:
3201.59Skamil			trigger_bus();
3211.59Skamil			break;
3221.59Skamil		default:
3231.59Skamil			/* NOTREACHED */
3241.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
3251.59Skamil		}
3261.59Skamil
3271.59Skamil		/* NOTREACHED */
3281.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
3291.59Skamil	}
3301.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3311.59Skamil
3321.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3331.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3341.59Skamil
3351.59Skamil	validate_status_stopped(status, sig);
3361.59Skamil
3371.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
3381.61Skre	SYSCALL_REQUIRE(
3391.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3401.59Skamil
3411.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3421.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3431.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3441.61Skre	    info.psi_siginfo.si_errno);
3451.59Skamil
3461.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
3471.59Skamil	switch (sig) {
3481.59Skamil	case SIGTRAP:
3491.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
3501.59Skamil		break;
3511.59Skamil	case SIGSEGV:
3521.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
3531.59Skamil		break;
3541.71Skamil	case SIGILL:
3551.71Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
3561.71Skamil		break;
3571.59Skamil	case SIGFPE:
3581.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
3591.59Skamil		break;
3601.59Skamil	case SIGBUS:
3611.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
3621.59Skamil		break;
3631.59Skamil	}
3641.59Skamil
3651.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
3661.59Skamil
3671.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3681.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3691.59Skamil
3701.59Skamil	validate_status_signaled(status, SIGKILL, 0);
3711.59Skamil
3721.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3731.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3741.59Skamil}
3751.59Skamil
3761.61Skre#define TRACEME_CRASH(test, sig)					\
3771.61SkreATF_TC(test);								\
3781.61SkreATF_TC_HEAD(test, tc)							\
3791.61Skre{									\
3801.61Skre	atf_tc_set_md_var(tc, "descr",					\
3811.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
3821.61Skre}									\
3831.61Skre									\
3841.61SkreATF_TC_BODY(test, tc)							\
3851.61Skre{									\
3861.61Skre									\
3871.61Skre	traceme_crash(sig);						\
3881.59Skamil}
3891.59Skamil
3901.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
3911.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
3921.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
3931.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
3941.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
3951.59Skamil
3961.59Skamil/// ----------------------------------------------------------------------------
3971.59Skamil
3981.59Skamilstatic void
3991.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
4001.1Skamil{
4011.1Skamil	const int exitval = 5;
4021.34Skamil	const int sigval = SIGSTOP;
4031.1Skamil	pid_t child, wpid;
4041.1Skamil	struct sigaction sa;
4051.1Skamil#if defined(TWAIT_HAVE_STATUS)
4061.1Skamil	int status;
4071.1Skamil#endif
4081.61Skre	struct ptrace_siginfo info;
4091.1Skamil
4101.45Skamil	memset(&info, 0, sizeof(info));
4111.45Skamil
4121.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
4131.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
4141.1Skamil	if (child == 0) {
4151.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4161.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4171.1Skamil
4181.34Skamil		sa.sa_handler = sah;
4191.1Skamil		sa.sa_flags = SA_SIGINFO;
4201.1Skamil		sigemptyset(&sa.sa_mask);
4211.1Skamil
4221.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
4231.1Skamil
4241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4261.1Skamil
4271.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
4281.1Skamil
4291.13Schristos		DPRINTF("Before exiting of the child process\n");
4301.1Skamil		_exit(exitval);
4311.1Skamil	}
4321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4331.1Skamil
4341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4361.1Skamil
4371.1Skamil	validate_status_stopped(status, sigval);
4381.1Skamil
4391.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4401.61Skre	SYSCALL_REQUIRE(
4411.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4421.45Skamil
4431.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4441.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4451.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4461.45Skamil	    info.psi_siginfo.si_errno);
4471.45Skamil
4481.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4491.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4501.45Skamil
4511.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
4521.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4541.1Skamil
4551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4571.1Skamil
4581.1Skamil	validate_status_exited(status, exitval);
4591.1Skamil
4601.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
4611.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4621.1Skamil}
4631.1Skamil
4641.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
4651.61SkreATF_TC(test);								\
4661.61SkreATF_TC_HEAD(test, tc)							\
4671.61Skre{									\
4681.61Skre	atf_tc_set_md_var(tc, "descr",					\
4691.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
4701.61Skre	    "handled correctly and caught by a signal handler");	\
4711.61Skre}									\
4721.61Skre									\
4731.61Skrestatic int test##_caught = 0;						\
4741.61Skre									\
4751.61Skrestatic void								\
4761.61Skretest##_sighandler(int arg)						\
4771.61Skre{									\
4781.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
4791.61Skre									\
4801.61Skre	++ test##_caught;						\
4811.61Skre}									\
4821.61Skre									\
4831.61SkreATF_TC_BODY(test, tc)							\
4841.61Skre{									\
4851.61Skre									\
4861.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
4871.34Skamil}
4881.34Skamil
4891.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
4901.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
4911.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
4921.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
4931.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
4941.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
4951.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
4961.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
4971.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
4981.34Skamil
4991.34Skamil/// ----------------------------------------------------------------------------
5001.34Skamil
5011.35Skamilstatic void
5021.50Skamiltraceme_sendsignal_masked(int sigsent)
5031.50Skamil{
5041.50Skamil	const int exitval = 5;
5051.50Skamil	const int sigval = SIGSTOP;
5061.50Skamil	pid_t child, wpid;
5071.50Skamil	sigset_t set;
5081.50Skamil#if defined(TWAIT_HAVE_STATUS)
5091.50Skamil	int status;
5101.50Skamil#endif
5111.61Skre	struct ptrace_siginfo info;
5121.50Skamil
5131.50Skamil	memset(&info, 0, sizeof(info));
5141.50Skamil
5151.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5161.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5171.50Skamil	if (child == 0) {
5181.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5191.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5201.50Skamil
5211.50Skamil		sigemptyset(&set);
5221.50Skamil		sigaddset(&set, sigsent);
5231.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
5241.50Skamil
5251.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5261.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5271.50Skamil
5281.50Skamil		_exit(exitval);
5291.50Skamil	}
5301.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5311.50Skamil
5321.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5331.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5341.50Skamil
5351.50Skamil	validate_status_stopped(status, sigval);
5361.50Skamil
5371.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5381.61Skre	SYSCALL_REQUIRE(
5391.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5401.50Skamil
5411.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5421.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5431.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5441.50Skamil	    info.psi_siginfo.si_errno);
5451.50Skamil
5461.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5471.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5481.50Skamil
5491.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
5501.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
5511.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
5521.50Skamil
5531.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5541.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5551.50Skamil
5561.50Skamil	validate_status_exited(status, exitval);
5571.50Skamil
5581.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5591.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5601.50Skamil}
5611.50Skamil
5621.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
5631.61SkreATF_TC(test);								\
5641.61SkreATF_TC_HEAD(test, tc)							\
5651.61Skre{									\
5661.61Skre	atf_tc_set_md_var(tc, "descr",					\
5671.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
5681.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
5691.61Skre}									\
5701.61Skre									\
5711.61SkreATF_TC_BODY(test, tc)							\
5721.61Skre{									\
5731.61Skre									\
5741.61Skre	traceme_sendsignal_masked(sig);					\
5751.50Skamil}
5761.50Skamil
5771.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
5781.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
5791.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
5801.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
5811.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
5821.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
5831.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
5841.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
5851.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
5861.50Skamil
5871.50Skamil/// ----------------------------------------------------------------------------
5881.50Skamil
5891.50Skamilstatic void
5901.50Skamiltraceme_sendsignal_ignored(int sigsent)
5911.50Skamil{
5921.50Skamil	const int exitval = 5;
5931.50Skamil	const int sigval = SIGSTOP;
5941.50Skamil	pid_t child, wpid;
5951.50Skamil	struct sigaction sa;
5961.50Skamil#if defined(TWAIT_HAVE_STATUS)
5971.50Skamil	int status;
5981.50Skamil#endif
5991.61Skre	struct ptrace_siginfo info;
6001.50Skamil
6011.50Skamil	memset(&info, 0, sizeof(info));
6021.50Skamil
6031.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
6041.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
6051.50Skamil	if (child == 0) {
6061.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
6071.61Skre
6081.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
6091.50Skamil
6101.50Skamil		memset(&sa, 0, sizeof(sa));
6111.50Skamil		sa.sa_handler = SIG_IGN;
6121.50Skamil		sigemptyset(&sa.sa_mask);
6131.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
6141.50Skamil
6151.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
6161.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
6171.50Skamil
6181.50Skamil		_exit(exitval);
6191.50Skamil	}
6201.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
6211.50Skamil
6221.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6231.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6241.50Skamil
6251.50Skamil	validate_status_stopped(status, sigval);
6261.50Skamil
6271.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6281.61Skre	SYSCALL_REQUIRE(
6291.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6301.50Skamil
6311.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6321.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6331.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6341.50Skamil	    info.psi_siginfo.si_errno);
6351.50Skamil
6361.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6371.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6381.50Skamil
6391.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
6401.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
6411.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
6421.50Skamil
6431.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6441.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6451.50Skamil
6461.50Skamil	validate_status_exited(status, exitval);
6471.50Skamil
6481.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
6491.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6501.50Skamil}
6511.50Skamil
6521.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
6531.61SkreATF_TC(test);								\
6541.61SkreATF_TC_HEAD(test, tc)							\
6551.61Skre{									\
6561.61Skre	atf_tc_set_md_var(tc, "descr",					\
6571.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
6581.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
6591.61Skre}									\
6601.61Skre									\
6611.61SkreATF_TC_BODY(test, tc)							\
6621.61Skre{									\
6631.61Skre									\
6641.61Skre	traceme_sendsignal_ignored(sig);				\
6651.50Skamil}
6661.50Skamil
6671.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
6681.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
6691.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
6701.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
6711.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
6721.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
6731.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
6741.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
6751.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
6761.50Skamil
6771.50Skamil/// ----------------------------------------------------------------------------
6781.50Skamil
6791.50Skamilstatic void
6801.50Skamiltraceme_sendsignal_simple(int sigsent)
6811.1Skamil{
6821.35Skamil	const int sigval = SIGSTOP;
6831.35Skamil	int exitval = 0;
6841.1Skamil	pid_t child, wpid;
6851.1Skamil#if defined(TWAIT_HAVE_STATUS)
6861.1Skamil	int status;
6871.85Skamil	int expect_core;
6881.85Skamil
6891.85Skamil	switch (sigsent) {
6901.85Skamil	case SIGABRT:
6911.85Skamil	case SIGTRAP:
6921.85Skamil	case SIGBUS:
6931.85Skamil	case SIGILL:
6941.85Skamil	case SIGFPE:
6951.85Skamil	case SIGSEGV:
6961.85Skamil		expect_core = 1;
6971.85Skamil		break;
6981.85Skamil	default:
6991.85Skamil		expect_core = 0;
7001.85Skamil		break;
7011.85Skamil	}
7021.1Skamil#endif
7031.61Skre	struct ptrace_siginfo info;
7041.1Skamil
7051.45Skamil	memset(&info, 0, sizeof(info));
7061.45Skamil
7071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
7081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
7091.1Skamil	if (child == 0) {
7101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7121.1Skamil
7131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7151.1Skamil
7161.35Skamil		switch (sigsent) {
7171.35Skamil		case SIGCONT:
7181.48Skamil		case SIGSTOP:
7191.35Skamil			_exit(exitval);
7201.35Skamil		default:
7211.35Skamil			/* NOTREACHED */
7221.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7231.35Skamil		}
7241.1Skamil	}
7251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7261.1Skamil
7271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7291.1Skamil
7301.1Skamil	validate_status_stopped(status, sigval);
7311.1Skamil
7321.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7331.61Skre	SYSCALL_REQUIRE(
7341.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7351.45Skamil
7361.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7371.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7381.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7391.45Skamil	    info.psi_siginfo.si_errno);
7401.45Skamil
7411.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
7421.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
7431.45Skamil
7441.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
7451.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
7461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
7471.1Skamil
7481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7501.1Skamil
7511.35Skamil	switch (sigsent) {
7521.48Skamil	case SIGSTOP:
7531.48Skamil		validate_status_stopped(status, sigsent);
7541.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
7551.61Skre		    "child\n");
7561.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
7571.61Skre		    sizeof(info)) != -1);
7581.48Skamil
7591.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7601.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
7611.61Skre		    "si_errno=%#x\n",
7621.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7631.61Skre		    info.psi_siginfo.si_errno);
7641.48Skamil
7651.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
7661.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
7671.48Skamil
7681.48Skamil		DPRINTF("Before resuming the child process where it left off "
7691.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
7701.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
7711.48Skamil
7721.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7731.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
7741.61Skre		    child);
7751.48Skamil		/* FALLTHROUGH */
7761.35Skamil	case SIGCONT:
7771.35Skamil		validate_status_exited(status, exitval);
7781.35Skamil		break;
7791.35Skamil	default:
7801.35Skamil		validate_status_signaled(status, sigsent, expect_core);
7811.35Skamil		break;
7821.35Skamil	}
7831.1Skamil
7841.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
7851.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
7861.1Skamil}
7871.1Skamil
7881.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
7891.61SkreATF_TC(test);								\
7901.61SkreATF_TC_HEAD(test, tc)							\
7911.61Skre{									\
7921.61Skre	atf_tc_set_md_var(tc, "descr",					\
7931.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
7941.61Skre	    "handled correctly in a child without a signal handler");	\
7951.61Skre}									\
7961.61Skre									\
7971.61SkreATF_TC_BODY(test, tc)							\
7981.61Skre{									\
7991.61Skre									\
8001.61Skre	traceme_sendsignal_simple(sig);					\
8011.35Skamil}
8021.35Skamil
8031.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
8041.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
8051.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
8061.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
8071.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
8081.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
8091.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
8101.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
8111.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
8121.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
8131.35Skamil
8141.35Skamil/// ----------------------------------------------------------------------------
8151.35Skamil
8161.37SkamilATF_TC(traceme_pid1_parent);
8171.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
8181.37Skamil{
8191.37Skamil	atf_tc_set_md_var(tc, "descr",
8201.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
8211.37Skamil}
8221.37Skamil
8231.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
8241.37Skamil{
8251.37Skamil	struct msg_fds parent_child;
8261.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
8271.37Skamil	pid_t child1, child2, wpid;
8281.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8291.37Skamil#if defined(TWAIT_HAVE_STATUS)
8301.37Skamil	int status;
8311.37Skamil#endif
8321.37Skamil
8331.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
8341.37Skamil
8351.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8361.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
8371.37Skamil	if (child1 == 0) {
8381.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
8391.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
8401.37Skamil		if (child2 != 0) {
8411.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
8421.61Skre			    getpid(), child2);
8431.37Skamil			_exit(exitval_child1);
8441.37Skamil		}
8451.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
8461.37Skamil
8471.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
8481.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
8491.37Skamil
8501.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8511.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
8521.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
8531.37Skamil
8541.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
8551.37Skamil
8561.37Skamil		_exit(exitval_child2);
8571.37Skamil	}
8581.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
8591.37Skamil
8601.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8611.61Skre	TWAIT_REQUIRE_SUCCESS(
8621.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
8631.37Skamil
8641.37Skamil	validate_status_exited(status, exitval_child1);
8651.37Skamil
8661.37Skamil	DPRINTF("Notify that child1 is dead\n");
8671.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
8681.37Skamil
8691.37Skamil	DPRINTF("Wait for exiting of child2\n");
8701.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
8711.37Skamil}
8721.37Skamil
8731.37Skamil/// ----------------------------------------------------------------------------
8741.37Skamil
8751.40Skamilstatic void
8761.40Skamiltraceme_vfork_raise(int sigval)
8771.40Skamil{
8781.46Skamil	const int exitval = 5, exitval_watcher = 10;
8791.46Skamil	pid_t child, parent, watcher, wpid;
8801.46Skamil	int rv;
8811.40Skamil#if defined(TWAIT_HAVE_STATUS)
8821.40Skamil	int status;
8831.85Skamil
8841.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
8851.85Skamil	volatile int expect_core;
8861.85Skamil
8871.85Skamil	switch (sigval) {
8881.85Skamil	case SIGABRT:
8891.85Skamil	case SIGTRAP:
8901.85Skamil	case SIGBUS:
8911.85Skamil	case SIGILL:
8921.85Skamil	case SIGFPE:
8931.85Skamil	case SIGSEGV:
8941.85Skamil		expect_core = 1;
8951.85Skamil		break;
8961.85Skamil	default:
8971.85Skamil		expect_core = 0;
8981.85Skamil		break;
8991.85Skamil	}
9001.40Skamil#endif
9011.40Skamil
9021.46Skamil	/*
9031.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
9041.46Skamil	 * the SIGKILL signal to it.
9051.46Skamil	 *
9061.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
9071.46Skamil	 * simpler to reparent this process to initproc and forget about it.
9081.46Skamil	 */
9091.46Skamil	if (sigval == SIGSTOP) {
9101.46Skamil		parent = getpid();
9111.46Skamil
9121.46Skamil		watcher = fork();
9131.46Skamil		ATF_REQUIRE(watcher != 1);
9141.46Skamil		if (watcher == 0) {
9151.46Skamil			/* Double fork(2) trick to reparent to initproc */
9161.46Skamil			watcher = fork();
9171.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
9181.46Skamil			if (watcher != 0)
9191.46Skamil				_exit(exitval_watcher);
9201.46Skamil
9211.46Skamil			child = await_stopped_child(parent);
9221.46Skamil
9231.46Skamil			errno = 0;
9241.46Skamil			rv = kill(child, SIGKILL);
9251.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
9261.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
9271.46Skamil
9281.46Skamil			/* This exit value will be collected by initproc */
9291.46Skamil			_exit(0);
9301.46Skamil		}
9311.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9321.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
9331.61Skre		    watcher);
9341.46Skamil
9351.46Skamil		validate_status_exited(status, exitval_watcher);
9361.46Skamil
9371.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9381.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
9391.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
9401.46Skamil	}
9411.46Skamil
9421.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9431.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
9441.40Skamil	if (child == 0) {
9451.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9461.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9471.40Skamil
9481.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
9491.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
9501.40Skamil
9511.40Skamil		switch (sigval) {
9521.46Skamil		case SIGSTOP:
9531.40Skamil		case SIGKILL:
9541.40Skamil		case SIGABRT:
9551.40Skamil		case SIGHUP:
9561.85Skamil		case SIGTRAP:
9571.85Skamil		case SIGBUS:
9581.85Skamil		case SIGILL:
9591.85Skamil		case SIGFPE:
9601.85Skamil		case SIGSEGV:
9611.40Skamil			/* NOTREACHED */
9621.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
9631.70Smrg			__unreachable();
9641.40Skamil		default:
9651.40Skamil			DPRINTF("Before exiting of the child process\n");
9661.40Skamil			_exit(exitval);
9671.40Skamil		}
9681.40Skamil	}
9691.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9701.40Skamil
9711.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9721.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9731.40Skamil
9741.40Skamil	switch (sigval) {
9751.40Skamil	case SIGKILL:
9761.40Skamil	case SIGABRT:
9771.40Skamil	case SIGHUP:
9781.85Skamil	case SIGTRAP:
9791.85Skamil	case SIGBUS:
9801.85Skamil	case SIGILL:
9811.85Skamil	case SIGFPE:
9821.85Skamil	case SIGSEGV:
9831.40Skamil		validate_status_signaled(status, sigval, expect_core);
9841.40Skamil		break;
9851.40Skamil	case SIGSTOP:
9861.46Skamil		validate_status_signaled(status, SIGKILL, 0);
9871.46Skamil		break;
9881.40Skamil	case SIGCONT:
9891.47Skamil	case SIGTSTP:
9901.47Skamil	case SIGTTIN:
9911.47Skamil	case SIGTTOU:
9921.40Skamil		validate_status_exited(status, exitval);
9931.40Skamil		break;
9941.40Skamil	default:
9951.40Skamil		/* NOTREACHED */
9961.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
9971.40Skamil		break;
9981.40Skamil	}
9991.40Skamil
10001.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10011.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10021.40Skamil}
10031.40Skamil
10041.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
10051.61SkreATF_TC(test);								\
10061.61SkreATF_TC_HEAD(test, tc)							\
10071.61Skre{									\
10081.61Skre	atf_tc_set_md_var(tc, "descr",					\
10091.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
10101.61Skre	    "vfork(2)ed child");					\
10111.61Skre}									\
10121.61Skre									\
10131.61SkreATF_TC_BODY(test, tc)							\
10141.61Skre{									\
10151.61Skre									\
10161.61Skre	traceme_vfork_raise(sig);					\
10171.40Skamil}
10181.40Skamil
10191.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
10201.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
10211.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
10221.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
10231.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
10241.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
10251.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
10261.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
10271.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
10281.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
10291.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
10301.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
10311.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
10321.40Skamil
10331.40Skamil/// ----------------------------------------------------------------------------
10341.40Skamil
10351.52Skamilstatic void
10361.52Skamiltraceme_vfork_crash(int sig)
10371.41Skamil{
10381.41Skamil	pid_t child, wpid;
10391.41Skamil#if defined(TWAIT_HAVE_STATUS)
10401.41Skamil	int status;
10411.41Skamil#endif
10421.41Skamil
10431.71Skamil#ifndef PTRACE_ILLEGAL_ASM
10441.71Skamil	if (sig == SIGILL)
10451.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
10461.71Skamil#endif
10471.71Skamil
10481.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10491.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
10501.41Skamil	if (child == 0) {
10511.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10521.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10531.41Skamil
10541.52Skamil		DPRINTF("Before executing a trap\n");
10551.52Skamil		switch (sig) {
10561.52Skamil		case SIGTRAP:
10571.52Skamil			trigger_trap();
10581.52Skamil			break;
10591.52Skamil		case SIGSEGV:
10601.52Skamil			trigger_segv();
10611.52Skamil			break;
10621.52Skamil		case SIGILL:
10631.52Skamil			trigger_ill();
10641.52Skamil			break;
10651.52Skamil		case SIGFPE:
10661.52Skamil			trigger_fpe();
10671.52Skamil			break;
10681.52Skamil		case SIGBUS:
10691.52Skamil			trigger_bus();
10701.52Skamil			break;
10711.52Skamil		default:
10721.52Skamil			/* NOTREACHED */
10731.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
10741.52Skamil		}
10751.41Skamil
10761.41Skamil		/* NOTREACHED */
10771.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
10781.41Skamil	}
10791.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10801.41Skamil
10811.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10821.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10831.41Skamil
10841.52Skamil	validate_status_signaled(status, sig, 1);
10851.41Skamil
10861.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10871.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10881.41Skamil}
10891.41Skamil
10901.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
10911.61SkreATF_TC(test);								\
10921.61SkreATF_TC_HEAD(test, tc)							\
10931.61Skre{									\
10941.61Skre	atf_tc_set_md_var(tc, "descr",					\
10951.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
10961.61Skre	    "vfork(2)ed child");					\
10971.61Skre}									\
10981.61Skre									\
10991.61SkreATF_TC_BODY(test, tc)							\
11001.61Skre{									\
11011.61Skre									\
11021.61Skre	traceme_vfork_crash(sig);					\
11031.52Skamil}
11041.52Skamil
11051.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
11061.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
11071.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
11081.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
11091.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
11101.52Skamil
11111.41Skamil/// ----------------------------------------------------------------------------
11121.41Skamil
11131.43SkamilATF_TC(traceme_vfork_exec);
11141.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
11151.43Skamil{
11161.43Skamil	atf_tc_set_md_var(tc, "descr",
11171.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
11181.43Skamil}
11191.43Skamil
11201.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
11211.43Skamil{
11221.43Skamil	const int sigval = SIGTRAP;
11231.43Skamil	pid_t child, wpid;
11241.43Skamil#if defined(TWAIT_HAVE_STATUS)
11251.43Skamil	int status;
11261.43Skamil#endif
11271.61Skre	struct ptrace_siginfo info;
11281.43Skamil
11291.43Skamil	memset(&info, 0, sizeof(info));
11301.43Skamil
11311.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
11321.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
11331.43Skamil	if (child == 0) {
11341.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11351.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11361.43Skamil
11371.43Skamil		DPRINTF("Before calling execve(2) from child\n");
11381.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
11391.43Skamil
11401.43Skamil		/* NOTREACHED */
11411.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
11421.43Skamil	}
11431.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11441.43Skamil
11451.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11461.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11471.43Skamil
11481.43Skamil	validate_status_stopped(status, sigval);
11491.43Skamil
11501.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
11511.61Skre	SYSCALL_REQUIRE(
11521.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
11531.43Skamil
11541.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11551.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
11561.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
11571.43Skamil	    info.psi_siginfo.si_errno);
11581.43Skamil
11591.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
11601.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
11611.43Skamil
11621.43Skamil	DPRINTF("Before resuming the child process where it left off and "
11631.43Skamil	    "without signal to be sent\n");
11641.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
11651.43Skamil
11661.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11671.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11681.43Skamil
11691.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11701.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11711.43Skamil}
11721.43Skamil
11731.43Skamil/// ----------------------------------------------------------------------------
11741.43Skamil
11751.1Skamil#if defined(TWAIT_HAVE_PID)
11761.51Skamilstatic void
11771.59Skamilunrelated_tracer_sees_crash(int sig)
11781.59Skamil{
11791.59Skamil	struct msg_fds parent_tracee, parent_tracer;
11801.59Skamil	const int exitval = 10;
11811.59Skamil	pid_t tracee, tracer, wpid;
11821.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11831.59Skamil#if defined(TWAIT_HAVE_STATUS)
11841.59Skamil	int status;
11851.59Skamil#endif
11861.59Skamil	struct ptrace_siginfo info;
11871.61Skre
11881.71Skamil#ifndef PTRACE_ILLEGAL_ASM
11891.71Skamil	if (sig == SIGILL)
11901.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
11911.71Skamil#endif
11921.71Skamil
11931.59Skamil	memset(&info, 0, sizeof(info));
11941.59Skamil
11951.59Skamil	DPRINTF("Spawn tracee\n");
11961.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
11971.59Skamil	tracee = atf_utils_fork();
11981.59Skamil	if (tracee == 0) {
11991.59Skamil		// Wait for parent to let us crash
12001.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
12011.61Skre
12021.59Skamil		DPRINTF("Before executing a trap\n");
12031.59Skamil		switch (sig) {
12041.59Skamil		case SIGTRAP:
12051.59Skamil			trigger_trap();
12061.59Skamil			break;
12071.59Skamil		case SIGSEGV:
12081.59Skamil			trigger_segv();
12091.59Skamil			break;
12101.59Skamil		case SIGILL:
12111.59Skamil			trigger_ill();
12121.59Skamil			break;
12131.59Skamil		case SIGFPE:
12141.59Skamil			trigger_fpe();
12151.59Skamil			break;
12161.59Skamil		case SIGBUS:
12171.59Skamil			trigger_bus();
12181.59Skamil			break;
12191.59Skamil		default:
12201.59Skamil			/* NOTREACHED */
12211.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
12221.59Skamil		}
12231.59Skamil
12241.59Skamil		/* NOTREACHED */
12251.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
12261.59Skamil	}
12271.59Skamil
12281.59Skamil	DPRINTF("Spawn debugger\n");
12291.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
12301.59Skamil	tracer = atf_utils_fork();
12311.59Skamil	if (tracer == 0) {
12321.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
12331.59Skamil		tracer = atf_utils_fork();
12341.59Skamil		if (tracer != 0)
12351.61Skre			_exit(exitval);
12361.59Skamil
12371.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
12381.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
12391.59Skamil
12401.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
12411.59Skamil		FORKEE_REQUIRE_SUCCESS(
12421.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12431.59Skamil
12441.59Skamil		forkee_status_stopped(status, SIGSTOP);
12451.59Skamil
12461.59Skamil		/* Resume tracee with PT_CONTINUE */
12471.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
12481.59Skamil
12491.59Skamil		/* Inform parent that tracer has attached to tracee */
12501.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
12511.59Skamil
12521.59Skamil		/* Wait for parent to tell use that tracee should have exited */
12531.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12541.59Skamil
12551.59Skamil		/* Wait for tracee and assert that it exited */
12561.59Skamil		FORKEE_REQUIRE_SUCCESS(
12571.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12581.59Skamil
12591.59Skamil		validate_status_stopped(status, sig);
12601.59Skamil
12611.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
12621.61Skre		    "traced process\n");
12631.61Skre		SYSCALL_REQUIRE(
12641.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
12651.59Skamil
12661.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12671.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
12681.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
12691.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
12701.59Skamil
12711.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
12721.59Skamil		switch (sig) {
12731.59Skamil		case SIGTRAP:
12741.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
12751.59Skamil			break;
12761.59Skamil		case SIGSEGV:
12771.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
12781.59Skamil			break;
12791.71Skamil		case SIGILL:
12801.71Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
12811.71Skamil			break;
12821.59Skamil		case SIGFPE:
12831.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
12841.59Skamil			break;
12851.59Skamil		case SIGBUS:
12861.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
12871.59Skamil			break;
12881.59Skamil		}
12891.59Skamil
12901.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
12911.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
12921.61Skre		TWAIT_REQUIRE_SUCCESS(
12931.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12941.59Skamil
12951.59Skamil		validate_status_signaled(status, SIGKILL, 0);
12961.59Skamil
12971.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
12981.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
12991.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
13001.59Skamil
13011.71Skamil		/* Inform parent that tracer is exiting normally */
13021.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
13031.71Skamil
13041.59Skamil		DPRINTF("Before exiting of the tracer process\n");
13051.59Skamil		_exit(0 /* collect by initproc */);
13061.59Skamil	}
13071.59Skamil
13081.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
13091.59Skamil	    "calling %s()\n", TWAIT_FNAME);
13101.59Skamil	TWAIT_REQUIRE_SUCCESS(
13111.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
13121.59Skamil
13131.59Skamil	validate_status_exited(status, exitval);
13141.59Skamil
13151.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
13161.59Skamil	    TWAIT_FNAME);
13171.59Skamil	TWAIT_REQUIRE_SUCCESS(
13181.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
13191.59Skamil
13201.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
13211.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
13221.59Skamil
13231.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
13241.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
13251.59Skamil
13261.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
13271.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
13281.59Skamil
13291.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
13301.59Skamil	    TWAIT_FNAME);
13311.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13321.59Skamil
13331.59Skamil	validate_status_signaled(status, SIGKILL, 0);
13341.59Skamil
13351.71Skamil	DPRINTF("Await normal exit of tracer\n");
13361.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
13371.71Skamil
13381.59Skamil	msg_close(&parent_tracer);
13391.59Skamil	msg_close(&parent_tracee);
13401.59Skamil}
13411.59Skamil
13421.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
13431.61SkreATF_TC(test);								\
13441.61SkreATF_TC_HEAD(test, tc)							\
13451.61Skre{									\
13461.61Skre	atf_tc_set_md_var(tc, "descr",					\
13471.61Skre	    "Assert that an unrelated tracer sees crash signal from the " \
13481.61Skre	    "debuggee");						\
13491.61Skre}									\
13501.61Skre									\
13511.61SkreATF_TC_BODY(test, tc)							\
13521.61Skre{									\
13531.61Skre									\
13541.61Skre	unrelated_tracer_sees_crash(sig);				\
13551.59Skamil}
13561.59Skamil
13571.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
13581.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
13591.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
13601.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
13611.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
13621.59Skamil#endif
13631.59Skamil
13641.59Skamil/// ----------------------------------------------------------------------------
13651.59Skamil
13661.59Skamil#if defined(TWAIT_HAVE_PID)
13671.59Skamilstatic void
13681.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
13691.67Skamil                                             bool stopped)
13701.1Skamil{
13711.51Skamil	/*
13721.51Skamil	 * notimeout - disable timeout in await zombie function
13731.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
13741.67Skamil	 * stopped - attach to a stopped process
13751.51Skamil	 */
13761.1Skamil
13771.1Skamil	struct msg_fds parent_tracee, parent_tracer;
13781.1Skamil	const int exitval_tracee = 5;
13791.1Skamil	const int exitval_tracer = 10;
13801.1Skamil	pid_t tracee, tracer, wpid;
13811.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13821.1Skamil#if defined(TWAIT_HAVE_STATUS)
13831.1Skamil	int status;
13841.1Skamil#endif
13851.1Skamil
13861.67Skamil	/*
13871.67Skamil	 * Only a subset of options are supported.
13881.67Skamil	 */
13891.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
13901.67Skamil	            (!notimeout && unrelated && !stopped) ||
13911.67Skamil	            (notimeout && !unrelated && !stopped) ||
13921.67Skamil	            (!notimeout && unrelated && stopped));
13931.67Skamil
13941.13Schristos	DPRINTF("Spawn tracee\n");
13951.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
13961.1Skamil	tracee = atf_utils_fork();
13971.1Skamil	if (tracee == 0) {
13981.67Skamil		if (stopped) {
13991.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
14001.67Skamil			raise(SIGSTOP);
14011.67Skamil		}
14021.67Skamil
14031.1Skamil		// Wait for parent to let us exit
14041.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
14051.1Skamil		_exit(exitval_tracee);
14061.1Skamil	}
14071.1Skamil
14081.13Schristos	DPRINTF("Spawn debugger\n");
14091.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
14101.1Skamil	tracer = atf_utils_fork();
14111.1Skamil	if (tracer == 0) {
14121.51Skamil		if(unrelated) {
14131.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
14141.51Skamil			tracer = atf_utils_fork();
14151.51Skamil			if (tracer != 0)
14161.51Skamil				_exit(exitval_tracer);
14171.51Skamil		}
14181.51Skamil
14191.67Skamil		if (stopped) {
14201.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
14211.67Skamil			await_stopped(tracee);
14221.67Skamil		}
14231.67Skamil
14241.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
14251.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
14261.1Skamil
14271.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
14281.1Skamil		FORKEE_REQUIRE_SUCCESS(
14291.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14301.1Skamil
14311.1Skamil		forkee_status_stopped(status, SIGSTOP);
14321.1Skamil
14331.1Skamil		/* Resume tracee with PT_CONTINUE */
14341.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
14351.1Skamil
14361.1Skamil		/* Inform parent that tracer has attached to tracee */
14371.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
14381.1Skamil
14391.1Skamil		/* Wait for parent to tell use that tracee should have exited */
14401.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
14411.1Skamil
14421.1Skamil		/* Wait for tracee and assert that it exited */
14431.1Skamil		FORKEE_REQUIRE_SUCCESS(
14441.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14451.1Skamil
14461.1Skamil		forkee_status_exited(status, exitval_tracee);
14471.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
14481.1Skamil
14491.13Schristos		DPRINTF("Before exiting of the tracer process\n");
14501.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
14511.51Skamil	}
14521.51Skamil
14531.51Skamil	if (unrelated) {
14541.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
14551.51Skamil		    "calling %s()\n", TWAIT_FNAME);
14561.51Skamil		TWAIT_REQUIRE_SUCCESS(
14571.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
14581.51Skamil
14591.51Skamil		validate_status_exited(status, exitval_tracer);
14601.51Skamil
14611.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
14621.51Skamil		    TWAIT_FNAME);
14631.51Skamil		TWAIT_REQUIRE_SUCCESS(
14641.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
14651.1Skamil	}
14661.1Skamil
14671.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
14681.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
14691.1Skamil
14701.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
14711.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
14721.1Skamil
14731.13Schristos	DPRINTF("Detect that tracee is zombie\n");
14741.51Skamil	if (notimeout)
14751.26Skamil		await_zombie_raw(tracee, 0);
14761.26Skamil	else
14771.26Skamil		await_zombie(tracee);
14781.1Skamil
14791.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
14801.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
14811.1Skamil	    TWAIT_FNAME);
14821.1Skamil	TWAIT_REQUIRE_SUCCESS(
14831.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
14841.1Skamil
14851.51Skamil	if (unrelated) {
14861.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
14871.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
14881.51Skamil	} else {
14891.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
14901.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
14911.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
14921.59Skamil			"%s()\n", TWAIT_FNAME);
14931.51Skamil
14941.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
14951.59Skamil			"tracee\n");
14961.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
14971.51Skamil		    tracer);
14981.1Skamil
14991.51Skamil		validate_status_exited(status, exitval_tracer);
15001.51Skamil	}
15011.1Skamil
15021.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
15031.1Skamil	    TWAIT_FNAME);
15041.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
15051.1Skamil
15061.1Skamil	validate_status_exited(status, exitval_tracee);
15071.1Skamil
15081.1Skamil	msg_close(&parent_tracer);
15091.1Skamil	msg_close(&parent_tracee);
15101.1Skamil}
15111.26Skamil
15121.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
15131.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
15141.51Skamil{
15151.51Skamil	atf_tc_set_md_var(tc, "descr",
15161.51Skamil	    "Assert that tracer sees process termination before the parent");
15171.51Skamil}
15181.51Skamil
15191.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
15201.26Skamil{
15211.26Skamil
15221.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
15231.26Skamil}
15241.26Skamil
15251.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
15261.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
15271.1Skamil{
15281.1Skamil	atf_tc_set_md_var(tc, "descr",
15291.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
15301.51Skamil	    "process and no other error is reported");
15311.1Skamil}
15321.1Skamil
15331.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
15341.1Skamil{
15351.51Skamil	time_t start, end;
15361.51Skamil	double diff;
15371.51Skamil	unsigned long N = 0;
15381.1Skamil
15391.51Skamil	/*
15401.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
15411.51Skamil	 * This test body isn't specific to this race, however it's just good
15421.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
15431.51Skamil	 */
15441.1Skamil
15451.51Skamil	start = time(NULL);
15461.51Skamil	while (true) {
15471.51Skamil		DPRINTF("Step: %lu\n", N);
15481.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
15491.67Skamil		                                             false);
15501.51Skamil		end = time(NULL);
15511.51Skamil		diff = difftime(end, start);
15521.51Skamil		if (diff >= 5.0)
15531.51Skamil			break;
15541.51Skamil		++N;
15551.1Skamil	}
15561.51Skamil	DPRINTF("Iterations: %lu\n", N);
15571.51Skamil}
15581.1Skamil
15591.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
15601.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
15611.51Skamil{
15621.51Skamil	atf_tc_set_md_var(tc, "descr",
15631.51Skamil	    "Assert that tracer sees process termination before the parent");
15641.51Skamil}
15651.1Skamil
15661.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
15671.51Skamil{
15681.1Skamil
15691.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
15701.67Skamil}
15711.67Skamil
15721.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
15731.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
15741.67Skamil{
15751.67Skamil	atf_tc_set_md_var(tc, "descr",
15761.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
15771.67Skamil}
15781.67Skamil
15791.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
15801.67Skamil{
15811.67Skamil
15821.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
15831.1Skamil}
15841.1Skamil#endif
15851.1Skamil
15861.51Skamil/// ----------------------------------------------------------------------------
15871.51Skamil
15881.66Skamilstatic void
15891.66Skamilparent_attach_to_its_child(bool stopped)
15901.1Skamil{
15911.1Skamil	struct msg_fds parent_tracee;
15921.1Skamil	const int exitval_tracee = 5;
15931.1Skamil	pid_t tracee, wpid;
15941.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15951.1Skamil#if defined(TWAIT_HAVE_STATUS)
15961.1Skamil	int status;
15971.1Skamil#endif
15981.1Skamil
15991.13Schristos	DPRINTF("Spawn tracee\n");
16001.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
16011.1Skamil	tracee = atf_utils_fork();
16021.1Skamil	if (tracee == 0) {
16031.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
16041.13Schristos		DPRINTF("Parent should now attach to tracee\n");
16051.1Skamil
16061.66Skamil		if (stopped) {
16071.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
16081.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
16091.66Skamil		}
16101.66Skamil
16111.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
16121.1Skamil		/* Wait for message from the parent */
16131.1Skamil		_exit(exitval_tracee);
16141.1Skamil	}
16151.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
16161.57Skamil
16171.66Skamil	if (stopped) {
16181.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
16191.66Skamil		await_stopped(tracee);
16201.66Skamil	}
16211.66Skamil
16221.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
16231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
16241.1Skamil
16251.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
16261.1Skamil	    TWAIT_FNAME);
16271.1Skamil	TWAIT_REQUIRE_SUCCESS(
16281.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
16291.1Skamil
16301.1Skamil	validate_status_stopped(status, SIGSTOP);
16311.1Skamil
16321.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
16331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
16341.1Skamil
16351.13Schristos	DPRINTF("Let the tracee exit now\n");
16361.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
16371.1Skamil
16381.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
16391.1Skamil	TWAIT_REQUIRE_SUCCESS(
16401.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
16411.1Skamil
16421.1Skamil	validate_status_exited(status, exitval_tracee);
16431.1Skamil
16441.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
16451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
16461.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
16471.1Skamil
16481.1Skamil	msg_close(&parent_tracee);
16491.1Skamil}
16501.1Skamil
16511.66SkamilATF_TC(parent_attach_to_its_child);
16521.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
16531.66Skamil{
16541.66Skamil	atf_tc_set_md_var(tc, "descr",
16551.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
16561.66Skamil}
16571.66Skamil
16581.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
16591.66Skamil{
16601.66Skamil
16611.66Skamil	parent_attach_to_its_child(false);
16621.66Skamil}
16631.66Skamil
16641.66SkamilATF_TC(parent_attach_to_its_stopped_child);
16651.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
16661.66Skamil{
16671.66Skamil	atf_tc_set_md_var(tc, "descr",
16681.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
16691.66Skamil}
16701.66Skamil
16711.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
16721.66Skamil{
16731.66Skamil
16741.66Skamil	parent_attach_to_its_child(true);
16751.66Skamil}
16761.66Skamil
16771.51Skamil/// ----------------------------------------------------------------------------
16781.51Skamil
16791.65Skamilstatic void
16801.65Skamilchild_attach_to_its_parent(bool stopped)
16811.1Skamil{
16821.1Skamil	struct msg_fds parent_tracee;
16831.1Skamil	const int exitval_tracer = 5;
16841.1Skamil	pid_t tracer, wpid;
16851.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
16861.1Skamil#if defined(TWAIT_HAVE_STATUS)
16871.1Skamil	int status;
16881.1Skamil#endif
16891.1Skamil
16901.13Schristos	DPRINTF("Spawn tracer\n");
16911.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
16921.1Skamil	tracer = atf_utils_fork();
16931.1Skamil	if (tracer == 0) {
16941.1Skamil		/* Wait for message from the parent */
16951.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
16961.1Skamil
16971.65Skamil		if (stopped) {
16981.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
16991.65Skamil			        getppid());
17001.65Skamil			await_stopped(getppid());
17011.65Skamil		}
17021.65Skamil
17031.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
17041.1Skamil		    getppid());
17051.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
17061.1Skamil
17071.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
17081.1Skamil		    TWAIT_FNAME);
17091.1Skamil		FORKEE_REQUIRE_SUCCESS(
17101.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
17111.1Skamil
17121.1Skamil		forkee_status_stopped(status, SIGSTOP);
17131.1Skamil
17141.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
17151.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
17161.1Skamil		    != -1);
17171.1Skamil
17181.1Skamil		/* Tell parent we are ready */
17191.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
17201.1Skamil
17211.1Skamil		_exit(exitval_tracer);
17221.1Skamil	}
17231.1Skamil
17241.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
17251.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
17261.65Skamil
17271.65Skamil	if (stopped) {
17281.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
17291.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
17301.65Skamil	}
17311.65Skamil
17321.13Schristos	DPRINTF("Allow the tracer to exit now\n");
17331.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
17341.1Skamil
17351.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
17361.1Skamil	TWAIT_REQUIRE_SUCCESS(
17371.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
17381.1Skamil
17391.1Skamil	validate_status_exited(status, exitval_tracer);
17401.1Skamil
17411.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
17421.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
17431.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
17441.1Skamil
17451.1Skamil	msg_close(&parent_tracee);
17461.1Skamil}
17471.1Skamil
17481.65SkamilATF_TC(child_attach_to_its_parent);
17491.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
17501.65Skamil{
17511.65Skamil	atf_tc_set_md_var(tc, "descr",
17521.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
17531.65Skamil}
17541.65Skamil
17551.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
17561.65Skamil{
17571.65Skamil
17581.65Skamil	child_attach_to_its_parent(false);
17591.65Skamil}
17601.65Skamil
17611.65SkamilATF_TC(child_attach_to_its_stopped_parent);
17621.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
17631.65Skamil{
17641.65Skamil	atf_tc_set_md_var(tc, "descr",
17651.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
17661.65Skamil}
17671.65Skamil
17681.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
17691.65Skamil{
17701.65Skamil	/*
17711.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
17721.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
17731.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
17741.65Skamil	 *
17751.65Skamil	 * As a workaround spawn this test as a subprocess.
17761.65Skamil	 */
17771.65Skamil
17781.65Skamil	const int exitval = 15;
17791.65Skamil	pid_t child, wpid;
17801.65Skamil#if defined(TWAIT_HAVE_STATUS)
17811.65Skamil	int status;
17821.65Skamil#endif
17831.65Skamil
17841.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
17851.65Skamil	if (child == 0) {
17861.65Skamil		child_attach_to_its_parent(true);
17871.65Skamil		_exit(exitval);
17881.65Skamil	} else {
17891.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17901.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17911.65Skamil
17921.65Skamil		validate_status_exited(status, exitval);
17931.65Skamil
17941.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
17951.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17961.65Skamil	}
17971.65Skamil}
17981.65Skamil
17991.51Skamil/// ----------------------------------------------------------------------------
18001.51Skamil
18011.1Skamil#if defined(TWAIT_HAVE_PID)
18021.1Skamil
18031.51Skamilenum tracee_sees_its_original_parent_type {
18041.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
18051.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
18061.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
18071.51Skamil};
18081.51Skamil
18091.51Skamilstatic void
18101.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
18111.1Skamil{
18121.1Skamil	struct msg_fds parent_tracer, parent_tracee;
18131.1Skamil	const int exitval_tracee = 5;
18141.1Skamil	const int exitval_tracer = 10;
18151.1Skamil	pid_t parent, tracee, tracer, wpid;
18161.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
18171.1Skamil#if defined(TWAIT_HAVE_STATUS)
18181.1Skamil	int status;
18191.1Skamil#endif
18201.51Skamil	/* sysctl(3) - kinfo_proc2 */
18211.51Skamil	int name[CTL_MAXNAME];
18221.51Skamil	struct kinfo_proc2 kp;
18231.51Skamil	size_t len = sizeof(kp);
18241.51Skamil	unsigned int namelen;
18251.51Skamil
18261.51Skamil	/* procfs - status  */
18271.51Skamil	FILE *fp;
18281.51Skamil	struct stat st;
18291.51Skamil	const char *fname = "/proc/curproc/status";
18301.51Skamil	char s_executable[MAXPATHLEN];
18311.51Skamil	int s_pid, s_ppid;
18321.51Skamil	int rv;
18331.51Skamil
18341.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
18351.61Skre		SYSCALL_REQUIRE(
18361.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
18371.61Skre		if (rv != 0)
18381.51Skamil			atf_tc_skip("/proc/curproc/status not found");
18391.51Skamil	}
18401.1Skamil
18411.13Schristos	DPRINTF("Spawn tracee\n");
18421.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
18431.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
18441.1Skamil	tracee = atf_utils_fork();
18451.1Skamil	if (tracee == 0) {
18461.1Skamil		parent = getppid();
18471.1Skamil
18481.1Skamil		/* Emit message to the parent */
18491.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
18501.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
18511.1Skamil
18521.51Skamil		switch (type) {
18531.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
18541.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
18551.51Skamil			break;
18561.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
18571.51Skamil			namelen = 0;
18581.51Skamil			name[namelen++] = CTL_KERN;
18591.51Skamil			name[namelen++] = KERN_PROC2;
18601.51Skamil			name[namelen++] = KERN_PROC_PID;
18611.51Skamil			name[namelen++] = getpid();
18621.51Skamil			name[namelen++] = len;
18631.51Skamil			name[namelen++] = 1;
18641.51Skamil
18651.61Skre			FORKEE_ASSERT_EQ(
18661.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
18671.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
18681.51Skamil			break;
18691.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
18701.51Skamil			/*
18711.51Skamil			 * Format:
18721.51Skamil			 *  EXECUTABLE PID PPID ...
18731.51Skamil			 */
18741.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
18751.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
18761.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
18771.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
18781.51Skamil			break;
18791.51Skamil		}
18801.1Skamil
18811.1Skamil		_exit(exitval_tracee);
18821.1Skamil	}
18831.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
18841.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
18851.1Skamil
18861.13Schristos	DPRINTF("Spawn debugger\n");
18871.1Skamil	tracer = atf_utils_fork();
18881.1Skamil	if (tracer == 0) {
18891.1Skamil		/* No IPC to communicate with the child */
18901.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
18911.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
18921.1Skamil
18931.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
18941.1Skamil		FORKEE_REQUIRE_SUCCESS(
18951.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
18961.1Skamil
18971.1Skamil		forkee_status_stopped(status, SIGSTOP);
18981.1Skamil
18991.1Skamil		/* Resume tracee with PT_CONTINUE */
19001.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
19011.1Skamil
19021.1Skamil		/* Inform parent that tracer has attached to tracee */
19031.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
19041.1Skamil
19051.1Skamil		/* Wait for parent to tell use that tracee should have exited */
19061.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
19071.1Skamil
19081.1Skamil		/* Wait for tracee and assert that it exited */
19091.1Skamil		FORKEE_REQUIRE_SUCCESS(
19101.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
19111.1Skamil
19121.1Skamil		forkee_status_exited(status, exitval_tracee);
19131.1Skamil
19141.13Schristos		DPRINTF("Before exiting of the tracer process\n");
19151.1Skamil		_exit(exitval_tracer);
19161.1Skamil	}
19171.1Skamil
19181.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
19191.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
19201.1Skamil
19211.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
19221.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
19231.1Skamil
19241.13Schristos	DPRINTF("Detect that tracee is zombie\n");
19251.1Skamil	await_zombie(tracee);
19261.1Skamil
19271.13Schristos	DPRINTF("Assert that there is no status about tracee - "
19281.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
19291.1Skamil	TWAIT_REQUIRE_SUCCESS(
19301.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
19311.1Skamil
19321.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
19331.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
19341.1Skamil
19351.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
19361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
19371.1Skamil	    tracer);
19381.1Skamil
19391.1Skamil	validate_status_exited(status, exitval_tracer);
19401.1Skamil
19411.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
19421.1Skamil	    TWAIT_FNAME);
19431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
19441.1Skamil	    tracee);
19451.1Skamil
19461.1Skamil	validate_status_exited(status, exitval_tracee);
19471.1Skamil
19481.1Skamil	msg_close(&parent_tracer);
19491.1Skamil	msg_close(&parent_tracee);
19501.1Skamil}
19511.1Skamil
19521.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
19531.61SkreATF_TC(test);								\
19541.61SkreATF_TC_HEAD(test, tc)							\
19551.61Skre{									\
19561.61Skre	atf_tc_set_md_var(tc, "descr",					\
19571.61Skre	    "Assert that tracee sees its original parent when being traced " \
19581.61Skre	    "(check " descr ")");					\
19591.61Skre}									\
19601.61Skre									\
19611.61SkreATF_TC_BODY(test, tc)							\
19621.61Skre{									\
19631.61Skre									\
19641.61Skre	tracee_sees_its_original_parent(type);				\
19651.1Skamil}
19661.1Skamil
19671.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
19681.51Skamil	tracee_sees_its_original_parent_getppid,
19691.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
19701.51Skamil	"getppid(2)");
19711.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
19721.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
19731.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
19741.51Skamil	"sysctl(3) and kinfo_proc2");
19751.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
19761.51Skamil	tracee_sees_its_original_parent_procfs_status,
19771.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
19781.51Skamil	"the status file in procfs");
19791.1Skamil#endif
19801.1Skamil
19811.51Skamil/// ----------------------------------------------------------------------------
19821.1Skamil
19831.53Skamilstatic void
19841.53Skamileventmask_preserved(int event)
19851.1Skamil{
19861.1Skamil	const int exitval = 5;
19871.1Skamil	const int sigval = SIGSTOP;
19881.1Skamil	pid_t child, wpid;
19891.1Skamil#if defined(TWAIT_HAVE_STATUS)
19901.1Skamil	int status;
19911.1Skamil#endif
19921.1Skamil	ptrace_event_t set_event, get_event;
19931.1Skamil	const int len = sizeof(ptrace_event_t);
19941.1Skamil
19951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19971.1Skamil	if (child == 0) {
19981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20001.1Skamil
20011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20031.1Skamil
20041.13Schristos		DPRINTF("Before exiting of the child process\n");
20051.1Skamil		_exit(exitval);
20061.1Skamil	}
20071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20081.1Skamil
20091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20111.1Skamil
20121.1Skamil	validate_status_stopped(status, sigval);
20131.1Skamil
20141.53Skamil	set_event.pe_set_event = event;
20151.61Skre	SYSCALL_REQUIRE(
20161.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
20171.61Skre	SYSCALL_REQUIRE(
20181.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
20191.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
20201.1Skamil
20211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20221.1Skamil	    "without signal to be sent\n");
20231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20241.1Skamil
20251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20271.1Skamil
20281.1Skamil	validate_status_exited(status, exitval);
20291.1Skamil
20301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20321.1Skamil}
20331.1Skamil
20341.61Skre#define EVENTMASK_PRESERVED(test, event)				\
20351.61SkreATF_TC(test);								\
20361.61SkreATF_TC_HEAD(test, tc)							\
20371.61Skre{									\
20381.61Skre	atf_tc_set_md_var(tc, "descr",					\
20391.61Skre	    "Verify that eventmask " #event " is preserved");		\
20401.61Skre}									\
20411.61Skre									\
20421.61SkreATF_TC_BODY(test, tc)							\
20431.61Skre{									\
20441.61Skre									\
20451.61Skre	eventmask_preserved(event);					\
20461.1Skamil}
20471.1Skamil
20481.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
20491.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
20501.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
20511.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
20521.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
20531.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
20541.1Skamil
20551.53Skamil/// ----------------------------------------------------------------------------
20561.1Skamil
20571.28Skamilstatic void
20581.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
20591.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
20601.1Skamil{
20611.1Skamil	const int exitval = 5;
20621.1Skamil	const int exitval2 = 15;
20631.1Skamil	const int sigval = SIGSTOP;
20641.31Skamil	pid_t child, child2 = 0, wpid;
20651.1Skamil#if defined(TWAIT_HAVE_STATUS)
20661.1Skamil	int status;
20671.1Skamil#endif
20681.1Skamil	ptrace_state_t state;
20691.1Skamil	const int slen = sizeof(state);
20701.1Skamil	ptrace_event_t event;
20711.1Skamil	const int elen = sizeof(event);
20721.1Skamil
20731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20751.1Skamil	if (child == 0) {
20761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20781.1Skamil
20791.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20801.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20811.1Skamil
20821.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
20831.1Skamil
20841.1Skamil		if (child2 == 0)
20851.1Skamil			_exit(exitval2);
20861.1Skamil
20871.1Skamil		FORKEE_REQUIRE_SUCCESS
20881.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
20891.1Skamil
20901.1Skamil		forkee_status_exited(status, exitval2);
20911.1Skamil
20921.13Schristos		DPRINTF("Before exiting of the child process\n");
20931.1Skamil		_exit(exitval);
20941.1Skamil	}
20951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20961.1Skamil
20971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20991.1Skamil
21001.1Skamil	validate_status_stopped(status, sigval);
21011.1Skamil
21021.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
21031.61Skre	    trackfork ? "|PTRACE_FORK" : "",
21041.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
21051.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
21061.30Skamil	event.pe_set_event = 0;
21071.30Skamil	if (trackfork)
21081.30Skamil		event.pe_set_event |= PTRACE_FORK;
21091.30Skamil	if (trackvfork)
21101.30Skamil		event.pe_set_event |= PTRACE_VFORK;
21111.30Skamil	if (trackvforkdone)
21121.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
21131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
21141.1Skamil
21151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21161.1Skamil	    "without signal to be sent\n");
21171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21181.1Skamil
21191.29Skamil#if defined(TWAIT_HAVE_PID)
21201.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
21211.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
21221.61Skre		    child);
21231.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
21241.61Skre		    child);
21251.1Skamil
21261.29Skamil		validate_status_stopped(status, SIGTRAP);
21271.1Skamil
21281.61Skre		SYSCALL_REQUIRE(
21291.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
21301.31Skamil		if (trackfork && fn == fork) {
21311.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
21321.30Skamil			       PTRACE_FORK);
21331.30Skamil		}
21341.31Skamil		if (trackvfork && fn == vfork) {
21351.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
21361.30Skamil			       PTRACE_VFORK);
21371.30Skamil		}
21381.29Skamil
21391.29Skamil		child2 = state.pe_other_pid;
21401.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
21411.29Skamil
21421.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
21431.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
21441.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
21451.29Skamil		    child2);
21461.1Skamil
21471.29Skamil		validate_status_stopped(status, SIGTRAP);
21481.1Skamil
21491.61Skre		SYSCALL_REQUIRE(
21501.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
21511.31Skamil		if (trackfork && fn == fork) {
21521.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
21531.30Skamil			       PTRACE_FORK);
21541.30Skamil		}
21551.31Skamil		if (trackvfork && fn == vfork) {
21561.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
21571.30Skamil			       PTRACE_VFORK);
21581.30Skamil		}
21591.30Skamil
21601.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
21611.29Skamil
21621.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
21631.29Skamil		    "and without signal to be sent\n");
21641.61Skre		SYSCALL_REQUIRE(
21651.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
21661.29Skamil
21671.29Skamil		DPRINTF("Before resuming the child process where it left off "
21681.61Skre		    "and without signal to be sent\n");
21691.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21701.30Skamil	}
21711.30Skamil#endif
21721.30Skamil
21731.31Skamil	if (trackvforkdone && fn == vfork) {
21741.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
21751.61Skre		    child);
21761.61Skre		TWAIT_REQUIRE_SUCCESS(
21771.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
21781.30Skamil
21791.30Skamil		validate_status_stopped(status, SIGTRAP);
21801.30Skamil
21811.61Skre		SYSCALL_REQUIRE(
21821.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
21831.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
21841.30Skamil
21851.30Skamil		child2 = state.pe_other_pid;
21861.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
21871.61Skre		    child2);
21881.30Skamil
21891.30Skamil		DPRINTF("Before resuming the child process where it left off "
21901.61Skre		    "and without signal to be sent\n");
21911.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21921.30Skamil	}
21931.29Skamil
21941.30Skamil#if defined(TWAIT_HAVE_PID)
21951.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
21961.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
21971.61Skre		    "\n", TWAIT_FNAME);
21981.61Skre		TWAIT_REQUIRE_SUCCESS(
21991.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
22001.29Skamil
22011.29Skamil		validate_status_exited(status, exitval2);
22021.29Skamil
22031.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
22041.61Skre		    "process\n", TWAIT_FNAME);
22051.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
22061.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
22071.29Skamil	}
22081.29Skamil#endif
22091.1Skamil
22101.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
22111.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
22121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22131.1Skamil
22141.1Skamil	validate_status_stopped(status, SIGCHLD);
22151.1Skamil
22161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22171.1Skamil	    "without signal to be sent\n");
22181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22191.1Skamil
22201.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
22211.1Skamil	    TWAIT_FNAME);
22221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22231.1Skamil
22241.1Skamil	validate_status_exited(status, exitval);
22251.1Skamil
22261.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
22271.1Skamil	    TWAIT_FNAME);
22281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22291.1Skamil}
22301.28Skamil
22311.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
22321.61SkreATF_TC(name);								\
22331.61SkreATF_TC_HEAD(name, tc)							\
22341.61Skre{									\
22351.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
22361.61Skre}									\
22371.61Skre									\
22381.61SkreATF_TC_BODY(name, tc)							\
22391.61Skre{									\
22401.61Skre									\
22411.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
22421.32Skamil}
22431.32Skamil
22441.32Skamil#define F false
22451.32Skamil#define T true
22461.32Skamil
22471.32Skamil#define F_IF__0(x)
22481.32Skamil#define F_IF__1(x) x
22491.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
22501.32Skamil#define F_IF_(x,y) F_IF__(x,y)
22511.32Skamil#define F_IF(x,y) F_IF_(x,y)
22521.32Skamil
22531.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
22541.61Skre	"Verify " #function "(2) called with 0"				\
22551.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
22561.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
22571.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
22581.61Skre	" in EVENT_MASK."						\
22591.61Skre	F_IF(dchildbit," Detach child in this test.")			\
22601.61Skre	F_IF(dparentbit," Detach parent in this test.")
22611.1Skamil
22621.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
22631.31Skamil#if defined(TWAIT_HAVE_PID)
22641.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
22651.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
22661.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
22671.31Skamil#endif
22681.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
22691.31Skamil#if defined(TWAIT_HAVE_PID)
22701.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
22711.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
22721.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
22731.31Skamil#endif
22741.1Skamil
22751.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
22761.31Skamil#if defined(TWAIT_HAVE_PID)
22771.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
22781.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
22791.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
22801.31Skamil#endif
22811.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
22821.31Skamil#if defined(TWAIT_HAVE_PID)
22831.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
22841.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
22851.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
22861.31Skamil#endif
22871.31Skamil
22881.54Skamil/// ----------------------------------------------------------------------------
22891.31Skamil
22901.54Skamilenum bytes_transfer_type {
22911.54Skamil	BYTES_TRANSFER_DATA,
22921.54Skamil	BYTES_TRANSFER_DATAIO,
22931.54Skamil	BYTES_TRANSFER_TEXT,
22941.54Skamil	BYTES_TRANSFER_TEXTIO,
22951.54Skamil	BYTES_TRANSFER_AUXV
22961.54Skamil};
22971.31Skamil
22981.54Skamilstatic int __used
22991.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
23001.54Skamil{
23011.54Skamil	int e, f, g, h;
23021.1Skamil
23031.54Skamil	a *= 4;
23041.54Skamil	b += 3;
23051.54Skamil	c -= 2;
23061.54Skamil	d /= 1;
23071.1Skamil
23081.54Skamil	e = strtol("10", NULL, 10);
23091.54Skamil	f = strtol("20", NULL, 10);
23101.54Skamil	g = strtol("30", NULL, 10);
23111.54Skamil	h = strtol("40", NULL, 10);
23121.1Skamil
23131.54Skamil	return (a + b * c - d) + (e * f - g / h);
23141.1Skamil}
23151.1Skamil
23161.54Skamilstatic void
23171.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
23181.1Skamil{
23191.1Skamil	const int exitval = 5;
23201.1Skamil	const int sigval = SIGSTOP;
23211.1Skamil	pid_t child, wpid;
23221.54Skamil	bool skip = false;
23231.1Skamil
23241.54Skamil	int lookup_me = 0;
23251.54Skamil	uint8_t lookup_me8 = 0;
23261.54Skamil	uint16_t lookup_me16 = 0;
23271.54Skamil	uint32_t lookup_me32 = 0;
23281.54Skamil	uint64_t lookup_me64 = 0;
23291.1Skamil
23301.54Skamil	int magic = 0x13579246;
23311.54Skamil	uint8_t magic8 = 0xab;
23321.54Skamil	uint16_t magic16 = 0x1234;
23331.54Skamil	uint32_t magic32 = 0x98765432;
23341.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
23351.1Skamil
23361.54Skamil	struct ptrace_io_desc io;
23371.1Skamil#if defined(TWAIT_HAVE_STATUS)
23381.1Skamil	int status;
23391.1Skamil#endif
23401.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
23411.60Skre	AuxInfo ai[513], *aip;
23421.55Schristos
23431.55Schristos	ATF_REQUIRE(size < sizeof(ai));
23441.1Skamil
23451.54Skamil	/* Prepare variables for .TEXT transfers */
23461.54Skamil	switch (type) {
23471.54Skamil	case BYTES_TRANSFER_TEXT:
23481.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
23491.54Skamil		break;
23501.54Skamil	case BYTES_TRANSFER_TEXTIO:
23511.54Skamil		switch (size) {
23521.54Skamil		case 8:
23531.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
23541.54Skamil			break;
23551.54Skamil		case 16:
23561.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
23571.54Skamil			break;
23581.54Skamil		case 32:
23591.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
23601.54Skamil			break;
23611.54Skamil		case 64:
23621.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
23631.54Skamil			break;
23641.54Skamil		}
23651.54Skamil		break;
23661.54Skamil	default:
23671.54Skamil		break;
23681.54Skamil	}
23691.1Skamil
23701.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
23711.54Skamil	switch (type) {
23721.54Skamil	case BYTES_TRANSFER_TEXTIO:
23731.54Skamil	case BYTES_TRANSFER_DATAIO:
23741.54Skamil		io.piod_op = operation;
23751.54Skamil		switch (size) {
23761.54Skamil		case 8:
23771.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
23781.54Skamil			               (void *)bytes_transfer_dummy :
23791.54Skamil			               &lookup_me8;
23801.54Skamil			io.piod_addr = &lookup_me8;
23811.54Skamil			io.piod_len = sizeof(lookup_me8);
23821.54Skamil			break;
23831.54Skamil		case 16:
23841.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
23851.54Skamil			               (void *)bytes_transfer_dummy :
23861.54Skamil			               &lookup_me16;
23871.54Skamil			io.piod_addr = &lookup_me16;
23881.54Skamil			io.piod_len = sizeof(lookup_me16);
23891.54Skamil			break;
23901.54Skamil		case 32:
23911.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
23921.54Skamil			               (void *)bytes_transfer_dummy :
23931.54Skamil			               &lookup_me32;
23941.54Skamil			io.piod_addr = &lookup_me32;
23951.54Skamil			io.piod_len = sizeof(lookup_me32);
23961.54Skamil			break;
23971.54Skamil		case 64:
23981.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
23991.54Skamil			               (void *)bytes_transfer_dummy :
24001.54Skamil			               &lookup_me64;
24011.54Skamil			io.piod_addr = &lookup_me64;
24021.54Skamil			io.piod_len = sizeof(lookup_me64);
24031.54Skamil			break;
24041.54Skamil		default:
24051.54Skamil			break;
24061.54Skamil		}
24071.54Skamil		break;
24081.54Skamil	case BYTES_TRANSFER_AUXV:
24091.54Skamil		io.piod_op = operation;
24101.54Skamil		io.piod_offs = 0;
24111.54Skamil		io.piod_addr = ai;
24121.54Skamil		io.piod_len = size;
24131.54Skamil		break;
24141.54Skamil	default:
24151.54Skamil		break;
24161.1Skamil	}
24171.1Skamil
24181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24201.1Skamil	if (child == 0) {
24211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24231.1Skamil
24241.54Skamil		switch (type) {
24251.54Skamil		case BYTES_TRANSFER_DATA:
24261.54Skamil			switch (operation) {
24271.54Skamil			case PT_READ_D:
24281.54Skamil			case PT_READ_I:
24291.54Skamil				lookup_me = magic;
24301.54Skamil				break;
24311.54Skamil			default:
24321.54Skamil				break;
24331.54Skamil			}
24341.54Skamil			break;
24351.54Skamil		case BYTES_TRANSFER_DATAIO:
24361.54Skamil			switch (operation) {
24371.54Skamil			case PIOD_READ_D:
24381.54Skamil			case PIOD_READ_I:
24391.54Skamil				switch (size) {
24401.54Skamil				case 8:
24411.54Skamil					lookup_me8 = magic8;
24421.54Skamil					break;
24431.54Skamil				case 16:
24441.54Skamil					lookup_me16 = magic16;
24451.54Skamil					break;
24461.54Skamil				case 32:
24471.54Skamil					lookup_me32 = magic32;
24481.54Skamil					break;
24491.54Skamil				case 64:
24501.54Skamil					lookup_me64 = magic64;
24511.54Skamil					break;
24521.54Skamil				default:
24531.54Skamil					break;
24541.54Skamil				}
24551.54Skamil				break;
24561.54Skamil			default:
24571.54Skamil				break;
24581.54Skamil			}
24591.54Skamil		default:
24601.54Skamil			break;
24611.54Skamil		}
24621.54Skamil
24631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24651.1Skamil
24661.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
24671.54Skamil		switch (type) {
24681.54Skamil		case BYTES_TRANSFER_DATA:
24691.54Skamil			switch (operation) {
24701.54Skamil			case PT_WRITE_D:
24711.54Skamil			case PT_WRITE_I:
24721.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
24731.54Skamil				break;
24741.54Skamil			default:
24751.54Skamil				break;
24761.54Skamil			}
24771.54Skamil			break;
24781.54Skamil		case BYTES_TRANSFER_DATAIO:
24791.54Skamil			switch (operation) {
24801.54Skamil			case PIOD_WRITE_D:
24811.54Skamil			case PIOD_WRITE_I:
24821.54Skamil				switch (size) {
24831.54Skamil				case 8:
24841.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
24851.54Skamil					break;
24861.54Skamil				case 16:
24871.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
24881.54Skamil					break;
24891.54Skamil				case 32:
24901.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
24911.54Skamil					break;
24921.54Skamil				case 64:
24931.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
24941.54Skamil					break;
24951.54Skamil				default:
24961.54Skamil					break;
24971.54Skamil				}
24981.54Skamil				break;
24991.54Skamil			default:
25001.54Skamil				break;
25011.54Skamil			}
25021.54Skamil			break;
25031.54Skamil		case BYTES_TRANSFER_TEXT:
25041.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
25051.54Skamil			                     sizeof(magic)) == 0);
25061.54Skamil			break;
25071.54Skamil		case BYTES_TRANSFER_TEXTIO:
25081.54Skamil			switch (size) {
25091.54Skamil			case 8:
25101.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
25111.54Skamil				                     bytes_transfer_dummy,
25121.54Skamil				                     sizeof(magic8)) == 0);
25131.54Skamil				break;
25141.54Skamil			case 16:
25151.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
25161.54Skamil				                     bytes_transfer_dummy,
25171.54Skamil				                     sizeof(magic16)) == 0);
25181.54Skamil				break;
25191.54Skamil			case 32:
25201.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
25211.54Skamil				                     bytes_transfer_dummy,
25221.54Skamil				                     sizeof(magic32)) == 0);
25231.54Skamil				break;
25241.54Skamil			case 64:
25251.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
25261.54Skamil				                     bytes_transfer_dummy,
25271.54Skamil				                     sizeof(magic64)) == 0);
25281.54Skamil				break;
25291.54Skamil			}
25301.54Skamil			break;
25311.54Skamil		default:
25321.54Skamil			break;
25331.54Skamil		}
25341.54Skamil
25351.13Schristos		DPRINTF("Before exiting of the child process\n");
25361.1Skamil		_exit(exitval);
25371.1Skamil	}
25381.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25391.1Skamil
25401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25421.1Skamil
25431.1Skamil	validate_status_stopped(status, sigval);
25441.1Skamil
25451.54Skamil	/* Check PaX MPROTECT */
25461.54Skamil	if (!can_we_write_to_text(child)) {
25471.54Skamil		switch (type) {
25481.54Skamil		case BYTES_TRANSFER_TEXTIO:
25491.54Skamil			switch (operation) {
25501.54Skamil			case PIOD_WRITE_D:
25511.54Skamil			case PIOD_WRITE_I:
25521.54Skamil				skip = true;
25531.54Skamil				break;
25541.54Skamil			default:
25551.54Skamil				break;
25561.54Skamil			}
25571.54Skamil			break;
25581.54Skamil		case BYTES_TRANSFER_TEXT:
25591.54Skamil			switch (operation) {
25601.54Skamil			case PT_WRITE_D:
25611.54Skamil			case PT_WRITE_I:
25621.54Skamil				skip = true;
25631.54Skamil				break;
25641.54Skamil			default:
25651.54Skamil				break;
25661.54Skamil			}
25671.54Skamil			break;
25681.54Skamil		default:
25691.54Skamil			break;
25701.54Skamil		}
25711.54Skamil	}
25721.1Skamil
25731.54Skamil	/* Bailout cleanly killing the child process */
25741.54Skamil	if (skip) {
25751.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
25761.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25771.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
25781.54Skamil		                      child);
25791.1Skamil
25801.54Skamil		validate_status_signaled(status, SIGKILL, 0);
25811.1Skamil
25821.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
25831.54Skamil	}
25841.1Skamil
25851.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
25861.54Skamil	       "parent=%d\n", child, getpid());
25871.1Skamil
25881.54Skamil	switch (type) {
25891.54Skamil	case BYTES_TRANSFER_TEXTIO:
25901.54Skamil	case BYTES_TRANSFER_DATAIO:
25911.54Skamil	case BYTES_TRANSFER_AUXV:
25921.54Skamil		switch (operation) {
25931.54Skamil		case PIOD_WRITE_D:
25941.54Skamil		case PIOD_WRITE_I:
25951.54Skamil			switch (size) {
25961.54Skamil			case 8:
25971.54Skamil				lookup_me8 = magic8;
25981.54Skamil				break;
25991.54Skamil			case 16:
26001.54Skamil				lookup_me16 = magic16;
26011.54Skamil				break;
26021.54Skamil			case 32:
26031.54Skamil				lookup_me32 = magic32;
26041.54Skamil				break;
26051.54Skamil			case 64:
26061.54Skamil				lookup_me64 = magic64;
26071.54Skamil				break;
26081.54Skamil			default:
26091.54Skamil				break;
26101.54Skamil			}
26111.54Skamil			break;
26121.54Skamil		default:
26131.54Skamil			break;
26141.54Skamil		}
26151.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
26161.54Skamil		switch (operation) {
26171.54Skamil		case PIOD_READ_D:
26181.54Skamil		case PIOD_READ_I:
26191.54Skamil			switch (size) {
26201.54Skamil			case 8:
26211.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
26221.54Skamil				break;
26231.54Skamil			case 16:
26241.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
26251.54Skamil				break;
26261.54Skamil			case 32:
26271.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
26281.54Skamil				break;
26291.54Skamil			case 64:
26301.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
26311.54Skamil				break;
26321.54Skamil			default:
26331.54Skamil				break;
26341.54Skamil			}
26351.54Skamil			break;
26361.54Skamil		case PIOD_READ_AUXV:
26371.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
26381.54Skamil			        io.piod_len);
26391.54Skamil			ATF_REQUIRE(io.piod_len > 0);
26401.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
26411.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
26421.54Skamil				    (long long int)aip->a_type,
26431.54Skamil				    (long long int)aip->a_v);
26441.54Skamil			break;
26451.54Skamil		default:
26461.54Skamil			break;
26471.54Skamil		}
26481.54Skamil		break;
26491.54Skamil	case BYTES_TRANSFER_TEXT:
26501.54Skamil		switch (operation) {
26511.54Skamil		case PT_READ_D:
26521.54Skamil		case PT_READ_I:
26531.54Skamil			errno = 0;
26541.54Skamil			lookup_me = ptrace(operation, child,
26551.54Skamil			                   bytes_transfer_dummy, 0);
26561.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
26571.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
26581.54Skamil			break;
26591.54Skamil		case PT_WRITE_D:
26601.54Skamil		case PT_WRITE_I:
26611.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
26621.54Skamil			                       bytes_transfer_dummy, magic)
26631.54Skamil			                != -1);
26641.54Skamil			break;
26651.54Skamil		default:
26661.54Skamil			break;
26671.54Skamil		}
26681.54Skamil		break;
26691.54Skamil	case BYTES_TRANSFER_DATA:
26701.54Skamil		switch (operation) {
26711.54Skamil		case PT_READ_D:
26721.54Skamil		case PT_READ_I:
26731.54Skamil			errno = 0;
26741.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
26751.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
26761.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
26771.54Skamil			break;
26781.54Skamil		case PT_WRITE_D:
26791.54Skamil		case PT_WRITE_I:
26801.54Skamil			lookup_me = magic;
26811.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
26821.54Skamil			                       magic) != -1);
26831.54Skamil			break;
26841.54Skamil		default:
26851.54Skamil			break;
26861.54Skamil		}
26871.54Skamil		break;
26881.54Skamil	default:
26891.54Skamil		break;
26901.54Skamil	}
26911.1Skamil
26921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26931.1Skamil	    "without signal to be sent\n");
26941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26951.1Skamil
26961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26981.1Skamil
26991.1Skamil	validate_status_exited(status, exitval);
27001.1Skamil
27011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27021.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27031.1Skamil}
27041.1Skamil
27051.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
27061.61SkreATF_TC(test);								\
27071.61SkreATF_TC_HEAD(test, tc)							\
27081.61Skre{									\
27091.61Skre	atf_tc_set_md_var(tc, "descr",					\
27101.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
27111.61Skre	    " of type " #type);						\
27121.61Skre}									\
27131.61Skre									\
27141.61SkreATF_TC_BODY(test, tc)							\
27151.61Skre{									\
27161.61Skre									\
27171.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
27181.1Skamil}
27191.1Skamil
27201.54Skamil// DATA
27211.1Skamil
27221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
27231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
27241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
27251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
27261.54Skamil
27271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
27281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
27291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
27301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
27311.54Skamil
27321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
27331.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
27341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
27351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
27361.54Skamil
27371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
27381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
27391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
27401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
27411.54Skamil
27421.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
27431.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
27441.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
27451.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
27461.54Skamil
27471.54Skamil// TEXT
27481.54Skamil
27491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
27501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
27511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
27521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
27531.54Skamil
27541.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
27551.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
27561.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
27571.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
27581.54Skamil
27591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
27601.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
27611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
27621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
27631.54Skamil
27641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
27651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
27661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
27671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
27681.54Skamil
27691.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
27701.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
27711.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
27721.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
27731.1Skamil
27741.54Skamil// AUXV
27751.1Skamil
27761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
27771.1Skamil
27781.54Skamil/// ----------------------------------------------------------------------------
27791.1Skamil
27801.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
27811.72Skamilstatic void
27821.72Skamilaccess_regs(const char *regset, const char *aux)
27831.1Skamil{
27841.1Skamil	const int exitval = 5;
27851.1Skamil	const int sigval = SIGSTOP;
27861.1Skamil	pid_t child, wpid;
27871.1Skamil#if defined(TWAIT_HAVE_STATUS)
27881.1Skamil	int status;
27891.1Skamil#endif
27901.72Skamil#if defined(HAVE_GPREGS)
27911.72Skamil	struct reg gpr;
27921.76Sscole	register_t rgstr;
27931.1Skamil#endif
27941.72Skamil#if defined(HAVE_FPREGS)
27951.72Skamil	struct fpreg fpr;
27961.1Skamil#endif
27971.76Sscole
27981.72Skamil#if !defined(HAVE_GPREGS)
27991.72Skamil	if (strcmp(regset, "regs") == 0)
28001.72Skamil		atf_tc_fail("Impossible test scenario!");
28011.1Skamil#endif
28021.1Skamil
28031.72Skamil#if !defined(HAVE_FPREGS)
28041.72Skamil	if (strcmp(regset, "fpregs") == 0)
28051.72Skamil		atf_tc_fail("Impossible test scenario!");
28061.1Skamil#endif
28071.1Skamil
28081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28101.1Skamil	if (child == 0) {
28111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28131.1Skamil
28141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28161.1Skamil
28171.13Schristos		DPRINTF("Before exiting of the child process\n");
28181.1Skamil		_exit(exitval);
28191.1Skamil	}
28201.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28211.1Skamil
28221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28241.1Skamil
28251.1Skamil	validate_status_stopped(status, sigval);
28261.1Skamil
28271.1Skamil#if defined(HAVE_GPREGS)
28281.72Skamil	if (strcmp(regset, "regs") == 0) {
28291.72Skamil		DPRINTF("Call GETREGS for the child process\n");
28301.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
28311.72Skamil
28321.72Skamil		if (strcmp(aux, "none") == 0) {
28331.72Skamil			DPRINTF("Retrieved registers\n");
28341.72Skamil		} else if (strcmp(aux, "pc") == 0) {
28351.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
28361.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
28371.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
28381.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
28391.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
28401.72Skamil		} else if (strcmp(aux, "sp") == 0) {
28411.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
28421.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
28431.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
28441.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
28451.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
28461.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
28471.72Skamil			DPRINTF("Call SETREGS for the child process\n");
28481.72Skamil			SYSCALL_REQUIRE(
28491.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
28501.72Skamil		}
28511.72Skamil	}
28521.1Skamil#endif
28531.1Skamil
28541.72Skamil#if defined(HAVE_FPREGS)
28551.72Skamil	if (strcmp(regset, "fpregs") == 0) {
28561.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
28571.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
28581.72Skamil
28591.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
28601.72Skamil			DPRINTF("Retrieved FP registers\n");
28611.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
28621.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
28631.72Skamil			SYSCALL_REQUIRE(
28641.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
28651.72Skamil		}
28661.1Skamil	}
28671.1Skamil#endif
28681.1Skamil
28691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28701.1Skamil	    "without signal to be sent\n");
28711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28721.1Skamil
28731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28751.1Skamil
28761.1Skamil	validate_status_exited(status, exitval);
28771.1Skamil
28781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28801.1Skamil}
28811.1Skamil
28821.72Skamil#define ACCESS_REGS(test, regset, aux)					\
28831.72SkamilATF_TC(test);								\
28841.72SkamilATF_TC_HEAD(test, tc)							\
28851.72Skamil{									\
28861.72Skamil        atf_tc_set_md_var(tc, "descr",					\
28871.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
28881.72Skamil}									\
28891.72Skamil									\
28901.72SkamilATF_TC_BODY(test, tc)							\
28911.72Skamil{									\
28921.72Skamil									\
28931.72Skamil        access_regs(regset, aux);					\
28941.1Skamil}
28951.1Skamil#endif
28961.1Skamil
28971.72Skamil#if defined(HAVE_GPREGS)
28981.72SkamilACCESS_REGS(access_regs1, "regs", "none")
28991.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
29001.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
29011.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
29021.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
29031.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
29041.1Skamil#endif
29051.1Skamil#if defined(HAVE_FPREGS)
29061.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
29071.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
29081.1Skamil#endif
29091.1Skamil
29101.72Skamil/// ----------------------------------------------------------------------------
29111.1Skamil
29121.1Skamil#if defined(PT_STEP)
29131.1Skamilstatic void
29141.2Skamilptrace_step(int N, int setstep)
29151.1Skamil{
29161.1Skamil	const int exitval = 5;
29171.1Skamil	const int sigval = SIGSTOP;
29181.1Skamil	pid_t child, wpid;
29191.1Skamil#if defined(TWAIT_HAVE_STATUS)
29201.1Skamil	int status;
29211.1Skamil#endif
29221.1Skamil	int happy;
29231.81Skamil	struct ptrace_siginfo info;
29241.1Skamil
29251.1Skamil#if defined(__arm__)
29261.1Skamil	/* PT_STEP not supported on arm 32-bit */
29271.1Skamil	atf_tc_expect_fail("PR kern/52119");
29281.1Skamil#endif
29291.1Skamil
29301.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29311.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29321.1Skamil	if (child == 0) {
29331.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29341.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29351.1Skamil
29361.1Skamil		happy = check_happy(999);
29371.1Skamil
29381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29401.1Skamil
29411.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
29421.1Skamil
29431.13Schristos		DPRINTF("Before exiting of the child process\n");
29441.1Skamil		_exit(exitval);
29451.1Skamil	}
29461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29471.1Skamil
29481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29501.1Skamil
29511.1Skamil	validate_status_stopped(status, sigval);
29521.1Skamil
29531.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
29541.81Skamil	SYSCALL_REQUIRE(
29551.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
29561.81Skamil
29571.81Skamil	DPRINTF("Before checking siginfo_t\n");
29581.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
29591.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
29601.81Skamil
29611.1Skamil	while (N --> 0) {
29621.2Skamil		if (setstep) {
29631.13Schristos			DPRINTF("Before resuming the child process where it "
29641.2Skamil			    "left off and without signal to be sent (use "
29651.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
29661.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
29671.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
29681.2Skamil			    != -1);
29691.2Skamil		} else {
29701.13Schristos			DPRINTF("Before resuming the child process where it "
29711.2Skamil			    "left off and without signal to be sent (use "
29721.2Skamil			    "PT_STEP)\n");
29731.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
29741.2Skamil			    != -1);
29751.2Skamil		}
29761.1Skamil
29771.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29781.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
29791.1Skamil		    child);
29801.1Skamil
29811.1Skamil		validate_status_stopped(status, SIGTRAP);
29821.2Skamil
29831.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
29841.81Skamil		SYSCALL_REQUIRE(
29851.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
29861.81Skamil
29871.81Skamil		DPRINTF("Before checking siginfo_t\n");
29881.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
29891.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
29901.81Skamil
29911.2Skamil		if (setstep) {
29921.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
29931.2Skamil		}
29941.1Skamil	}
29951.1Skamil
29961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29971.1Skamil	    "without signal to be sent\n");
29981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29991.1Skamil
30001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30021.1Skamil
30031.1Skamil	validate_status_exited(status, exitval);
30041.1Skamil
30051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30071.1Skamil}
30081.1Skamil
30091.73Skamil#define PTRACE_STEP(test, N, setstep)					\
30101.73SkamilATF_TC(test);								\
30111.73SkamilATF_TC_HEAD(test, tc)							\
30121.73Skamil{									\
30131.73Skamil        atf_tc_set_md_var(tc, "descr",					\
30141.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
30151.73Skamil}									\
30161.73Skamil									\
30171.73SkamilATF_TC_BODY(test, tc)							\
30181.73Skamil{									\
30191.73Skamil									\
30201.73Skamil        ptrace_step(N, setstep);					\
30211.1Skamil}
30221.1Skamil
30231.73SkamilPTRACE_STEP(step1, 1, 0)
30241.73SkamilPTRACE_STEP(step2, 2, 0)
30251.73SkamilPTRACE_STEP(step3, 3, 0)
30261.73SkamilPTRACE_STEP(step4, 4, 0)
30271.73SkamilPTRACE_STEP(setstep1, 1, 1)
30281.73SkamilPTRACE_STEP(setstep2, 2, 1)
30291.73SkamilPTRACE_STEP(setstep3, 3, 1)
30301.73SkamilPTRACE_STEP(setstep4, 4, 1)
30311.1Skamil#endif
30321.1Skamil
30331.73Skamil/// ----------------------------------------------------------------------------
30341.1Skamil
30351.75Skamilstatic void
30361.75Skamilptrace_kill(const char *type)
30371.1Skamil{
30381.75Skamil	const int sigval = SIGSTOP;
30391.1Skamil	pid_t child, wpid;
30401.1Skamil#if defined(TWAIT_HAVE_STATUS)
30411.1Skamil	int status;
30421.1Skamil#endif
30431.1Skamil
30441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30461.1Skamil	if (child == 0) {
30471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30491.1Skamil
30501.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30511.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30521.1Skamil
30531.1Skamil		/* NOTREACHED */
30541.1Skamil		FORKEE_ASSERTX(0 &&
30551.1Skamil		    "Child should be terminated by a signal from its parent");
30561.1Skamil	}
30571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30581.1Skamil
30591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30611.1Skamil
30621.1Skamil	validate_status_stopped(status, sigval);
30631.1Skamil
30641.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
30651.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
30661.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
30671.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
30681.75Skamil		kill(child, SIGKILL);
30691.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
30701.75Skamil		setpgid(child, 0);
30711.75Skamil		killpg(getpgid(child), SIGKILL);
30721.75Skamil	}
30731.1Skamil
30741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30761.1Skamil
30771.75Skamil	validate_status_signaled(status, SIGKILL, 0);
30781.1Skamil
30791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30811.1Skamil}
30821.1Skamil
30831.75Skamil#define PTRACE_KILL(test, type)						\
30841.75SkamilATF_TC(test);								\
30851.75SkamilATF_TC_HEAD(test, tc)							\
30861.75Skamil{									\
30871.75Skamil        atf_tc_set_md_var(tc, "descr",					\
30881.75Skamil            "Verify killing the child with " type);			\
30891.75Skamil}									\
30901.75Skamil									\
30911.75SkamilATF_TC_BODY(test, tc)							\
30921.75Skamil{									\
30931.75Skamil									\
30941.75Skamil        ptrace_kill(type);						\
30951.1Skamil}
30961.1Skamil
30971.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
30981.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
30991.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
31001.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
31011.1Skamil
31021.75Skamil/// ----------------------------------------------------------------------------
31031.1Skamil
31041.77Skamilstatic void
31051.77Skamiltraceme_lwpinfo(const int threads)
31061.1Skamil{
31071.1Skamil	const int sigval = SIGSTOP;
31081.77Skamil	const int sigval2 = SIGINT;
31091.1Skamil	pid_t child, wpid;
31101.1Skamil#if defined(TWAIT_HAVE_STATUS)
31111.1Skamil	int status;
31121.1Skamil#endif
31131.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
31141.77Skamil	struct ptrace_siginfo info;
31151.77Skamil
31161.77Skamil	/* Maximum number of supported threads in this test */
31171.77Skamil	pthread_t t[3];
31181.77Skamil	int n, rv;
31191.77Skamil
31201.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
31211.1Skamil
31221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31241.1Skamil	if (child == 0) {
31251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31271.1Skamil
31281.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31291.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31301.1Skamil
31311.77Skamil		for (n = 0; n < threads; n++) {
31321.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
31331.77Skamil			FORKEE_ASSERT(rv == 0);
31341.77Skamil		}
31351.77Skamil
31361.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
31371.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
31381.77Skamil
31391.77Skamil		/* NOTREACHED */
31401.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
31411.1Skamil	}
31421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31431.1Skamil
31441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31461.1Skamil
31471.1Skamil	validate_status_stopped(status, sigval);
31481.1Skamil
31491.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
31501.77Skamil	SYSCALL_REQUIRE(
31511.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
31521.77Skamil
31531.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
31541.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
31551.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
31561.77Skamil	    info.psi_siginfo.si_errno);
31571.77Skamil
31581.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
31591.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
31601.77Skamil
31611.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
31621.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
31631.1Skamil
31641.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
31651.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
31661.1Skamil
31671.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
31681.77Skamil	    lwp.pl_lwpid);
31691.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
31701.1Skamil
31711.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
31721.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
31731.1Skamil
31741.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
31751.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
31761.1Skamil
31771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31781.1Skamil	    "without signal to be sent\n");
31791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31801.1Skamil
31811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31831.1Skamil
31841.77Skamil	validate_status_stopped(status, sigval2);
31851.77Skamil
31861.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
31871.77Skamil	SYSCALL_REQUIRE(
31881.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
31891.77Skamil
31901.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
31911.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
31921.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
31931.77Skamil	    info.psi_siginfo.si_errno);
31941.77Skamil
31951.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
31961.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
31971.77Skamil
31981.77Skamil	memset(&lwp, 0, sizeof(lwp));
31991.77Skamil
32001.77Skamil	for (n = 0; n <= threads; n++) {
32011.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
32021.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
32031.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
32041.77Skamil
32051.77Skamil		DPRINTF("Assert that the thread exists\n");
32061.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
32071.77Skamil
32081.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
32091.77Skamil		    lwp.pl_lwpid);
32101.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
32111.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
32121.77Skamil	}
32131.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
32141.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
32151.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
32161.77Skamil
32171.77Skamil	DPRINTF("Assert that there are no more threads\n");
32181.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
32191.77Skamil
32201.77Skamil	DPRINTF("Before resuming the child process where it left off and "
32211.77Skamil	    "without signal to be sent\n");
32221.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
32231.77Skamil
32241.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32251.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32261.77Skamil
32271.77Skamil	validate_status_signaled(status, SIGKILL, 0);
32281.1Skamil
32291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32301.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32311.1Skamil}
32321.1Skamil
32331.77Skamil#define TRACEME_LWPINFO(test, threads)					\
32341.77SkamilATF_TC(test);								\
32351.77SkamilATF_TC_HEAD(test, tc)							\
32361.77Skamil{									\
32371.77Skamil	atf_tc_set_md_var(tc, "descr",					\
32381.77Skamil	    "Verify LWPINFO with the child with " #threads		\
32391.77Skamil	    " spawned extra threads");					\
32401.77Skamil}									\
32411.77Skamil									\
32421.77SkamilATF_TC_BODY(test, tc)							\
32431.77Skamil{									\
32441.77Skamil									\
32451.77Skamil	traceme_lwpinfo(threads);					\
32461.1Skamil}
32471.1Skamil
32481.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
32491.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
32501.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
32511.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
32521.77Skamil
32531.77Skamil/// ----------------------------------------------------------------------------
32541.77Skamil
32551.77Skamil#if defined(TWAIT_HAVE_PID)
32561.77Skamilstatic void
32571.77Skamilattach_lwpinfo(const int threads)
32581.1Skamil{
32591.77Skamil	const int sigval = SIGINT;
32601.1Skamil	struct msg_fds parent_tracee, parent_tracer;
32611.1Skamil	const int exitval_tracer = 10;
32621.1Skamil	pid_t tracee, tracer, wpid;
32631.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
32641.1Skamil#if defined(TWAIT_HAVE_STATUS)
32651.1Skamil	int status;
32661.1Skamil#endif
32671.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
32681.77Skamil	struct ptrace_siginfo info;
32691.77Skamil
32701.77Skamil	/* Maximum number of supported threads in this test */
32711.77Skamil	pthread_t t[3];
32721.77Skamil	int n, rv;
32731.1Skamil
32741.13Schristos	DPRINTF("Spawn tracee\n");
32751.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
32761.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
32771.1Skamil	tracee = atf_utils_fork();
32781.1Skamil	if (tracee == 0) {
32791.1Skamil		/* Wait for message from the parent */
32801.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
32811.1Skamil
32821.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
32831.77Skamil
32841.77Skamil		for (n = 0; n < threads; n++) {
32851.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
32861.77Skamil			FORKEE_ASSERT(rv == 0);
32871.77Skamil		}
32881.77Skamil
32891.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
32901.77Skamil
32911.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32921.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32931.77Skamil
32941.77Skamil		/* NOTREACHED */
32951.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
32961.1Skamil	}
32971.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
32981.1Skamil
32991.13Schristos	DPRINTF("Spawn debugger\n");
33001.1Skamil	tracer = atf_utils_fork();
33011.1Skamil	if (tracer == 0) {
33021.1Skamil		/* No IPC to communicate with the child */
33031.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
33041.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
33051.1Skamil
33061.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
33071.1Skamil		FORKEE_REQUIRE_SUCCESS(
33081.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
33091.1Skamil
33101.1Skamil		forkee_status_stopped(status, SIGSTOP);
33111.1Skamil
33121.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
33131.77Skamil		    "tracee");
33141.77Skamil		FORKEE_ASSERT(
33151.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
33161.77Skamil
33171.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
33181.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
33191.77Skamil		    "si_errno=%#x\n",
33201.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
33211.77Skamil		    info.psi_siginfo.si_errno);
33221.77Skamil
33231.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
33241.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
33251.77Skamil
33261.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33271.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
33281.1Skamil		    != -1);
33291.1Skamil
33301.13Schristos		DPRINTF("Assert that there exists a thread\n");
33311.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
33321.1Skamil
33331.13Schristos		DPRINTF("Assert that lwp thread %d received event "
33341.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
33351.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
33361.1Skamil
33371.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
33381.77Skamil		    "tracee\n");
33391.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
33401.1Skamil		    != -1);
33411.1Skamil
33421.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
33431.77Skamil		    "tracee\n");
33441.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
33451.1Skamil
33461.1Skamil		/* Resume tracee with PT_CONTINUE */
33471.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
33481.1Skamil
33491.1Skamil		/* Inform parent that tracer has attached to tracee */
33501.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
33511.77Skamil
33521.1Skamil		/* Wait for parent */
33531.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
33541.1Skamil
33551.77Skamil		/* Wait for tracee and assert that it raised a signal */
33561.77Skamil		FORKEE_REQUIRE_SUCCESS(
33571.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
33581.77Skamil
33591.77Skamil		forkee_status_stopped(status, SIGINT);
33601.77Skamil
33611.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
33621.77Skamil		    "child");
33631.77Skamil		FORKEE_ASSERT(
33641.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
33651.77Skamil
33661.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
33671.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
33681.77Skamil		    "si_errno=%#x\n",
33691.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
33701.77Skamil		    info.psi_siginfo.si_errno);
33711.77Skamil
33721.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
33731.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
33741.77Skamil
33751.77Skamil		memset(&lwp, 0, sizeof(lwp));
33761.77Skamil
33771.77Skamil		for (n = 0; n <= threads; n++) {
33781.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
33791.77Skamil			    "child\n");
33801.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
33811.77Skamil			    sizeof(lwp)) != -1);
33821.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
33831.77Skamil
33841.77Skamil			DPRINTF("Assert that the thread exists\n");
33851.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
33861.77Skamil
33871.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
33881.77Skamil			    "event\n", lwp.pl_lwpid);
33891.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
33901.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
33911.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
33921.77Skamil		}
33931.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
33941.77Skamil		    "tracee\n");
33951.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
33961.77Skamil		    != -1);
33971.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
33981.77Skamil
33991.77Skamil		DPRINTF("Assert that there are no more threads\n");
34001.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
34011.77Skamil
34021.77Skamil		DPRINTF("Before resuming the child process where it left off "
34031.77Skamil		    "and without signal to be sent\n");
34041.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
34051.77Skamil		    != -1);
34061.77Skamil
34071.1Skamil		/* Wait for tracee and assert that it exited */
34081.1Skamil		FORKEE_REQUIRE_SUCCESS(
34091.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
34101.1Skamil
34111.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
34121.1Skamil
34131.13Schristos		DPRINTF("Before exiting of the tracer process\n");
34141.1Skamil		_exit(exitval_tracer);
34151.1Skamil	}
34161.1Skamil
34171.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
34181.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
34191.1Skamil
34201.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
34211.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
34221.77Skamil
34231.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
34241.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
34251.1Skamil
34261.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
34271.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
34281.1Skamil
34291.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
34301.1Skamil	    TWAIT_FNAME);
34311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
34321.1Skamil	    tracer);
34331.1Skamil
34341.1Skamil	validate_status_exited(status, exitval_tracer);
34351.1Skamil
34361.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
34371.1Skamil	    TWAIT_FNAME);
34381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
34391.1Skamil	    tracee);
34401.1Skamil
34411.77Skamil	validate_status_signaled(status, SIGKILL, 0);
34421.1Skamil
34431.1Skamil	msg_close(&parent_tracer);
34441.1Skamil	msg_close(&parent_tracee);
34451.1Skamil}
34461.77Skamil
34471.77Skamil#define ATTACH_LWPINFO(test, threads)					\
34481.77SkamilATF_TC(test);								\
34491.77SkamilATF_TC_HEAD(test, tc)							\
34501.77Skamil{									\
34511.77Skamil	atf_tc_set_md_var(tc, "descr",					\
34521.77Skamil	    "Verify LWPINFO with the child with " #threads		\
34531.77Skamil	    " spawned extra threads (tracer is not the original "	\
34541.77Skamil	    "parent)");							\
34551.77Skamil}									\
34561.77Skamil									\
34571.77SkamilATF_TC_BODY(test, tc)							\
34581.77Skamil{									\
34591.77Skamil									\
34601.77Skamil	attach_lwpinfo(threads);					\
34611.77Skamil}
34621.77Skamil
34631.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
34641.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
34651.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
34661.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
34671.1Skamil#endif
34681.1Skamil
34691.77Skamil/// ----------------------------------------------------------------------------
34701.77Skamil
34711.1Skamilstatic void
34721.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
34731.1Skamil{
34741.1Skamil	const int exitval = 5;
34751.1Skamil	const int sigval = SIGINT;
34761.1Skamil	const int sigfaked = SIGTRAP;
34771.1Skamil	const int sicodefaked = TRAP_BRKPT;
34781.1Skamil	pid_t child, wpid;
34791.1Skamil	struct sigaction sa;
34801.1Skamil#if defined(TWAIT_HAVE_STATUS)
34811.1Skamil	int status;
34821.1Skamil#endif
34831.1Skamil	struct ptrace_siginfo info;
34841.1Skamil	memset(&info, 0, sizeof(info));
34851.1Skamil
34861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34881.1Skamil	if (child == 0) {
34891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34911.1Skamil
34921.79Skamil		sa.sa_sigaction = sah;
34931.1Skamil		sa.sa_flags = SA_SIGINFO;
34941.1Skamil		sigemptyset(&sa.sa_mask);
34951.1Skamil
34961.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
34971.79Skamil		    != -1);
34981.1Skamil
34991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35011.1Skamil
35021.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
35031.1Skamil
35041.13Schristos		DPRINTF("Before exiting of the child process\n");
35051.1Skamil		_exit(exitval);
35061.1Skamil	}
35071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35081.1Skamil
35091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35111.1Skamil
35121.1Skamil	validate_status_stopped(status, sigval);
35131.1Skamil
35141.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35151.61Skre	SYSCALL_REQUIRE(
35161.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35171.1Skamil
35181.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35191.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35201.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35211.1Skamil	    info.psi_siginfo.si_errno);
35221.1Skamil
35231.79Skamil	if (faked) {
35241.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
35251.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
35261.79Skamil		info.psi_siginfo.si_signo = sigfaked;
35271.79Skamil		info.psi_siginfo.si_code = sicodefaked;
35281.79Skamil	}
35291.1Skamil
35301.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
35311.61Skre	SYSCALL_REQUIRE(
35321.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
35331.1Skamil
35341.79Skamil	if (faked) {
35351.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
35361.79Skamil		    "child\n");
35371.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
35381.79Skamil		    sizeof(info)) != -1);
35391.1Skamil
35401.79Skamil		DPRINTF("Before checking siginfo_t\n");
35411.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
35421.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
35431.79Skamil	}
35441.1Skamil
35451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35461.1Skamil	    "without signal to be sent\n");
35471.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
35481.79Skamil	    faked ? sigfaked : sigval) != -1);
35491.1Skamil
35501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35521.1Skamil
35531.1Skamil	validate_status_exited(status, exitval);
35541.1Skamil
35551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35561.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35571.1Skamil}
35581.1Skamil
35591.79Skamil#define PTRACE_SIGINFO(test, faked)					\
35601.79SkamilATF_TC(test);								\
35611.79SkamilATF_TC_HEAD(test, tc)							\
35621.79Skamil{									\
35631.79Skamil	atf_tc_set_md_var(tc, "descr",					\
35641.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
35651.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
35661.79Skamil}									\
35671.79Skamil									\
35681.79Skamilstatic int test##_caught = 0;						\
35691.79Skamil									\
35701.79Skamilstatic void								\
35711.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
35721.79Skamil{									\
35731.79Skamil	if (faked) {							\
35741.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
35751.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
35761.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
35771.79Skamil	} else {							\
35781.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
35791.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
35801.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
35811.79Skamil	}								\
35821.79Skamil									\
35831.79Skamil	++ test##_caught;						\
35841.79Skamil}									\
35851.79Skamil									\
35861.79SkamilATF_TC_BODY(test, tc)							\
35871.79Skamil{									\
35881.79Skamil									\
35891.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
35901.79Skamil}
35911.79Skamil
35921.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
35931.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
35941.79Skamil
35951.79Skamil/// ----------------------------------------------------------------------------
35961.79Skamil
35971.82SkamilATF_TC(traceme_exec);
35981.82SkamilATF_TC_HEAD(traceme_exec, tc)
35991.1Skamil{
36001.1Skamil	atf_tc_set_md_var(tc, "descr",
36011.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
36021.1Skamil}
36031.1Skamil
36041.82SkamilATF_TC_BODY(traceme_exec, tc)
36051.1Skamil{
36061.1Skamil	const int sigval = SIGTRAP;
36071.1Skamil	pid_t child, wpid;
36081.1Skamil#if defined(TWAIT_HAVE_STATUS)
36091.1Skamil	int status;
36101.1Skamil#endif
36111.1Skamil
36121.1Skamil	struct ptrace_siginfo info;
36131.1Skamil	memset(&info, 0, sizeof(info));
36141.1Skamil
36151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36171.1Skamil	if (child == 0) {
36181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36201.1Skamil
36211.13Schristos		DPRINTF("Before calling execve(2) from child\n");
36221.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
36231.1Skamil
36241.1Skamil		FORKEE_ASSERT(0 && "Not reached");
36251.1Skamil	}
36261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36271.1Skamil
36281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36301.1Skamil
36311.1Skamil	validate_status_stopped(status, sigval);
36321.1Skamil
36331.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36341.61Skre	SYSCALL_REQUIRE(
36351.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36361.1Skamil
36371.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36381.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
36391.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36401.1Skamil	    info.psi_siginfo.si_errno);
36411.1Skamil
36421.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
36431.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
36441.1Skamil
36451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36461.1Skamil	    "without signal to be sent\n");
36471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36481.1Skamil
36491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36511.1Skamil
36521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36531.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36541.1Skamil}
36551.1Skamil
36561.82Skamil/// ----------------------------------------------------------------------------
36571.82Skamil
36581.83Skamilstatic volatile int done;
36591.1Skamil
36601.83Skamilstatic void *
36611.83Skamiltrace_threads_cb(void *arg __unused)
36621.1Skamil{
36631.1Skamil
36641.83Skamil	done++;
36651.83Skamil
36661.83Skamil	while (done < 3)
36671.83Skamil		continue;
36681.83Skamil
36691.83Skamil	return NULL;
36701.1Skamil}
36711.1Skamil
36721.83Skamilstatic void
36731.83Skamiltrace_threads(bool trace_create, bool trace_exit)
36741.1Skamil{
36751.1Skamil	const int sigval = SIGSTOP;
36761.1Skamil	pid_t child, wpid;
36771.1Skamil#if defined(TWAIT_HAVE_STATUS)
36781.1Skamil	int status;
36791.1Skamil#endif
36801.1Skamil	ptrace_state_t state;
36811.1Skamil	const int slen = sizeof(state);
36821.1Skamil	ptrace_event_t event;
36831.1Skamil	const int elen = sizeof(event);
36841.83Skamil	struct ptrace_siginfo info;
36851.83Skamil
36861.83Skamil	pthread_t t[3];
36871.83Skamil	int rv;
36881.83Skamil	size_t n;
36891.1Skamil	lwpid_t lid;
36901.83Skamil
36911.83Skamil	/* Track created and exited threads */
36921.83Skamil	bool traced_lwps[__arraycount(t)];
36931.83Skamil
36941.83Skamil	atf_tc_skip("PR kern/51995");
36951.1Skamil
36961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36981.1Skamil	if (child == 0) {
36991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37011.1Skamil
37021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37041.1Skamil
37051.83Skamil		for (n = 0; n < __arraycount(t); n++) {
37061.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
37071.83Skamil			    NULL);
37081.83Skamil			FORKEE_ASSERT(rv == 0);
37091.83Skamil		}
37101.1Skamil
37111.83Skamil		for (n = 0; n < __arraycount(t); n++) {
37121.83Skamil			rv = pthread_join(t[n], NULL);
37131.83Skamil			FORKEE_ASSERT(rv == 0);
37141.83Skamil		}
37151.1Skamil
37161.83Skamil		/*
37171.83Skamil		 * There is race between _exit() and pthread_join() detaching
37181.83Skamil		 * a thread. For simplicity kill the process after detecting
37191.83Skamil		 * LWP events.
37201.83Skamil		 */
37211.83Skamil		while (true)
37221.83Skamil			continue;
37231.1Skamil
37241.83Skamil		FORKEE_ASSERT(0 && "Not reached");
37251.1Skamil	}
37261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37271.1Skamil
37281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37301.1Skamil
37311.1Skamil	validate_status_stopped(status, sigval);
37321.1Skamil
37331.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37341.83Skamil	SYSCALL_REQUIRE(
37351.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37361.1Skamil
37371.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37381.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
37391.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37401.83Skamil	    info.psi_siginfo.si_errno);
37411.1Skamil
37421.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
37431.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
37441.1Skamil
37451.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
37461.83Skamil	memset(&event, 0, sizeof(event));
37471.83Skamil	if (trace_create)
37481.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
37491.83Skamil	if (trace_exit)
37501.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
37511.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
37521.1Skamil
37531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37541.1Skamil	    "without signal to be sent\n");
37551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37561.1Skamil
37571.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
37581.1Skamil
37591.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
37601.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
37611.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
37621.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
37631.83Skamil		    child);
37641.1Skamil
37651.83Skamil		validate_status_stopped(status, SIGTRAP);
37661.1Skamil
37671.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
37681.83Skamil		    "child\n");
37691.83Skamil		SYSCALL_REQUIRE(
37701.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37711.1Skamil
37721.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37731.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
37741.83Skamil		    "si_errno=%#x\n",
37751.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37761.83Skamil		    info.psi_siginfo.si_errno);
37771.1Skamil
37781.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
37791.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
37801.1Skamil
37811.83Skamil		SYSCALL_REQUIRE(
37821.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
37831.1Skamil
37841.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
37851.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
37861.1Skamil
37871.83Skamil		lid = state.pe_lwp;
37881.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
37891.1Skamil
37901.83Skamil		traced_lwps[lid - 1] = true;
37911.1Skamil
37921.83Skamil		DPRINTF("Before resuming the child process where it left off "
37931.83Skamil		    "and without signal to be sent\n");
37941.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37951.83Skamil	}
37961.1Skamil
37971.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
37981.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
37991.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
38001.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
38011.83Skamil		    child);
38021.1Skamil
38031.83Skamil		validate_status_stopped(status, SIGTRAP);
38041.1Skamil
38051.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
38061.83Skamil		    "child\n");
38071.83Skamil		SYSCALL_REQUIRE(
38081.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38091.1Skamil
38101.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
38111.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
38121.83Skamil		    "si_errno=%#x\n",
38131.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
38141.83Skamil		    info.psi_siginfo.si_errno);
38151.1Skamil
38161.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
38171.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
38181.1Skamil
38191.83Skamil		SYSCALL_REQUIRE(
38201.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
38211.1Skamil
38221.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
38231.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
38241.1Skamil
38251.83Skamil		lid = state.pe_lwp;
38261.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
38271.1Skamil
38281.83Skamil		if (trace_create) {
38291.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
38301.83Skamil			traced_lwps[lid - 1] = false;
38311.83Skamil		}
38321.1Skamil
38331.83Skamil		DPRINTF("Before resuming the child process where it left off "
38341.83Skamil		    "and without signal to be sent\n");
38351.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38361.83Skamil	}
38371.1Skamil
38381.83Skamil	kill(child, SIGKILL);
38391.1Skamil
38401.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
38411.1Skamil	    TWAIT_FNAME);
38421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38431.1Skamil
38441.83Skamil	validate_status_signaled(status, SIGKILL, 0);
38451.1Skamil
38461.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
38471.1Skamil	    TWAIT_FNAME);
38481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38491.1Skamil}
38501.1Skamil
38511.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
38521.83SkamilATF_TC(test);								\
38531.83SkamilATF_TC_HEAD(test, tc)							\
38541.83Skamil{									\
38551.83Skamil        atf_tc_set_md_var(tc, "descr",					\
38561.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
38571.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
38581.83Skamil	    trace_exit ? "" : "out");					\
38591.83Skamil}									\
38601.83Skamil									\
38611.83SkamilATF_TC_BODY(test, tc)							\
38621.83Skamil{									\
38631.83Skamil									\
38641.83Skamil        trace_threads(trace_create, trace_exit);			\
38651.83Skamil}
38661.83Skamil
38671.83SkamilTRACE_THREADS(trace_thread1, false, false)
38681.83SkamilTRACE_THREADS(trace_thread2, false, true)
38691.83SkamilTRACE_THREADS(trace_thread3, true, false)
38701.83SkamilTRACE_THREADS(trace_thread4, true, true)
38711.83Skamil
38721.83Skamil/// ----------------------------------------------------------------------------
38731.83Skamil
38741.84SkamilATF_TC(signal_mask_unrelated);
38751.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
38761.1Skamil{
38771.1Skamil	atf_tc_set_md_var(tc, "descr",
38781.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
38791.1Skamil	    "from catching other signals");
38801.1Skamil}
38811.1Skamil
38821.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
38831.1Skamil{
38841.1Skamil	const int exitval = 5;
38851.1Skamil	const int sigval = SIGSTOP;
38861.1Skamil	const int sigmasked = SIGTRAP;
38871.1Skamil	const int signotmasked = SIGINT;
38881.1Skamil	pid_t child, wpid;
38891.1Skamil#if defined(TWAIT_HAVE_STATUS)
38901.1Skamil	int status;
38911.1Skamil#endif
38921.1Skamil	sigset_t intmask;
38931.1Skamil
38941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38961.1Skamil	if (child == 0) {
38971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38991.1Skamil
39001.1Skamil		sigemptyset(&intmask);
39011.1Skamil		sigaddset(&intmask, sigmasked);
39021.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
39031.1Skamil
39041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39061.1Skamil
39071.13Schristos		DPRINTF("Before raising %s from child\n",
39081.1Skamil		    strsignal(signotmasked));
39091.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
39101.1Skamil
39111.13Schristos		DPRINTF("Before exiting of the child process\n");
39121.1Skamil		_exit(exitval);
39131.1Skamil	}
39141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39151.1Skamil
39161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39181.1Skamil
39191.1Skamil	validate_status_stopped(status, sigval);
39201.1Skamil
39211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39221.1Skamil	    "without signal to be sent\n");
39231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39241.1Skamil
39251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39271.1Skamil
39281.1Skamil	validate_status_stopped(status, signotmasked);
39291.1Skamil
39301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39311.1Skamil	    "without signal to be sent\n");
39321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39331.1Skamil
39341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39361.1Skamil
39371.1Skamil	validate_status_exited(status, exitval);
39381.1Skamil
39391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39411.1Skamil}
39421.1Skamil
39431.84Skamil/// ----------------------------------------------------------------------------
39441.84Skamil
39451.1SkamilATF_TC(signal3);
39461.1SkamilATF_TC_HEAD(signal3, tc)
39471.1Skamil{
39481.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
39491.1Skamil	atf_tc_set_md_var(tc, "descr",
39501.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
39511.1Skamil	    "catching software breakpoints");
39521.1Skamil}
39531.1Skamil
39541.1SkamilATF_TC_BODY(signal3, tc)
39551.1Skamil{
39561.1Skamil	const int exitval = 5;
39571.1Skamil	const int sigval = SIGSTOP;
39581.1Skamil	const int sigmasked = SIGTRAP;
39591.1Skamil	pid_t child, wpid;
39601.1Skamil#if defined(TWAIT_HAVE_STATUS)
39611.1Skamil	int status;
39621.1Skamil#endif
39631.1Skamil	sigset_t intmask;
39641.1Skamil
39651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39671.1Skamil	if (child == 0) {
39681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39701.1Skamil
39711.1Skamil		sigemptyset(&intmask);
39721.1Skamil		sigaddset(&intmask, sigmasked);
39731.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
39741.1Skamil
39751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39771.1Skamil
39781.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
39791.52Skamil		trigger_trap();
39801.1Skamil
39811.13Schristos		DPRINTF("Before exiting of the child process\n");
39821.1Skamil		_exit(exitval);
39831.1Skamil	}
39841.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39851.1Skamil
39861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39881.1Skamil
39891.1Skamil	validate_status_stopped(status, sigval);
39901.1Skamil
39911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39921.1Skamil	    "without signal to be sent\n");
39931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39941.1Skamil
39951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39971.1Skamil
39981.1Skamil	validate_status_stopped(status, sigmasked);
39991.1Skamil
40001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40011.1Skamil	    "without signal to be sent\n");
40021.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
40031.1Skamil
40041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40061.1Skamil
40071.49Skamil	validate_status_signaled(status, SIGKILL, 0);
40081.1Skamil
40091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40111.1Skamil}
40121.1Skamil
40131.1Skamil#if defined(PT_STEP)
40141.1SkamilATF_TC(signal4);
40151.1SkamilATF_TC_HEAD(signal4, tc)
40161.1Skamil{
40171.1Skamil	atf_tc_set_md_var(tc, "descr",
40181.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
40191.1Skamil	    "catching single step trap");
40201.1Skamil}
40211.1Skamil
40221.1SkamilATF_TC_BODY(signal4, tc)
40231.1Skamil{
40241.1Skamil	const int exitval = 5;
40251.1Skamil	const int sigval = SIGSTOP;
40261.1Skamil	const int sigmasked = SIGTRAP;
40271.1Skamil	pid_t child, wpid;
40281.1Skamil#if defined(TWAIT_HAVE_STATUS)
40291.1Skamil	int status;
40301.1Skamil#endif
40311.1Skamil	sigset_t intmask;
40321.1Skamil	int happy;
40331.1Skamil
40341.1Skamil#if defined(__arm__)
40351.5Skamil	/* PT_STEP not supported on arm 32-bit */
40361.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
40371.1Skamil#endif
40381.1Skamil
40391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40411.1Skamil	if (child == 0) {
40421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40441.1Skamil
40451.1Skamil		happy = check_happy(100);
40461.1Skamil
40471.1Skamil		sigemptyset(&intmask);
40481.1Skamil		sigaddset(&intmask, sigmasked);
40491.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
40501.1Skamil
40511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40531.1Skamil
40541.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
40551.1Skamil
40561.13Schristos		DPRINTF("Before exiting of the child process\n");
40571.1Skamil		_exit(exitval);
40581.1Skamil	}
40591.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40601.1Skamil
40611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40631.1Skamil
40641.1Skamil	validate_status_stopped(status, sigval);
40651.1Skamil
40661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40671.1Skamil	    "without signal to be sent\n");
40681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
40691.1Skamil
40701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40721.1Skamil
40731.1Skamil	validate_status_stopped(status, sigmasked);
40741.1Skamil
40751.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40761.1Skamil	    "without signal to be sent\n");
40771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40781.1Skamil
40791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40811.1Skamil
40821.1Skamil	validate_status_exited(status, exitval);
40831.1Skamil
40841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40851.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40861.1Skamil}
40871.1Skamil#endif
40881.1Skamil
40891.1SkamilATF_TC(signal5);
40901.1SkamilATF_TC_HEAD(signal5, tc)
40911.1Skamil{
40921.1Skamil	atf_tc_set_md_var(tc, "descr",
40931.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
40941.1Skamil	    "catching exec() breakpoint");
40951.1Skamil}
40961.1Skamil
40971.1SkamilATF_TC_BODY(signal5, tc)
40981.1Skamil{
40991.1Skamil	const int sigval = SIGSTOP;
41001.1Skamil	const int sigmasked = SIGTRAP;
41011.1Skamil	pid_t child, wpid;
41021.1Skamil#if defined(TWAIT_HAVE_STATUS)
41031.1Skamil	int status;
41041.1Skamil#endif
41051.58Skamil	struct ptrace_siginfo info;
41061.1Skamil	sigset_t intmask;
41071.1Skamil
41081.58Skamil	memset(&info, 0, sizeof(info));
41091.14Schristos
41101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41121.1Skamil	if (child == 0) {
41131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41151.1Skamil
41161.1Skamil		sigemptyset(&intmask);
41171.1Skamil		sigaddset(&intmask, sigmasked);
41181.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
41191.1Skamil
41201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41221.1Skamil
41231.13Schristos		DPRINTF("Before calling execve(2) from child\n");
41241.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
41251.1Skamil
41261.58Skamil		/* NOTREACHED */
41271.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
41281.1Skamil	}
41291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41301.1Skamil
41311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41331.1Skamil
41341.1Skamil	validate_status_stopped(status, sigval);
41351.1Skamil
41361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41371.1Skamil	    "without signal to be sent\n");
41381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41391.1Skamil
41401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41421.1Skamil
41431.1Skamil	validate_status_stopped(status, sigmasked);
41441.1Skamil
41451.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
41461.61Skre	SYSCALL_REQUIRE(
41471.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41481.58Skamil
41491.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
41501.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
41511.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41521.58Skamil	    info.psi_siginfo.si_errno);
41531.58Skamil
41541.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
41551.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
41561.58Skamil
41571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41581.1Skamil	    "without signal to be sent\n");
41591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41601.1Skamil
41611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41631.1Skamil
41641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41661.1Skamil}
41671.1Skamil
41681.1Skamil#if defined(TWAIT_HAVE_PID)
41691.1SkamilATF_TC(signal6);
41701.1SkamilATF_TC_HEAD(signal6, tc)
41711.1Skamil{
41721.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
41731.1Skamil	atf_tc_set_md_var(tc, "descr",
41741.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
41751.1Skamil	    "catching PTRACE_FORK breakpoint");
41761.1Skamil}
41771.1Skamil
41781.1SkamilATF_TC_BODY(signal6, tc)
41791.1Skamil{
41801.1Skamil	const int exitval = 5;
41811.1Skamil	const int exitval2 = 15;
41821.1Skamil	const int sigval = SIGSTOP;
41831.1Skamil	const int sigmasked = SIGTRAP;
41841.1Skamil	pid_t child, child2, wpid;
41851.1Skamil#if defined(TWAIT_HAVE_STATUS)
41861.1Skamil	int status;
41871.1Skamil#endif
41881.1Skamil	sigset_t intmask;
41891.1Skamil	ptrace_state_t state;
41901.1Skamil	const int slen = sizeof(state);
41911.1Skamil	ptrace_event_t event;
41921.1Skamil	const int elen = sizeof(event);
41931.1Skamil
41941.38Skamil	atf_tc_expect_fail("PR kern/51918");
41951.14Schristos
41961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41981.1Skamil	if (child == 0) {
41991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42011.1Skamil
42021.1Skamil		sigemptyset(&intmask);
42031.1Skamil		sigaddset(&intmask, sigmasked);
42041.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
42051.1Skamil
42061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42081.1Skamil
42091.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
42101.1Skamil
42111.1Skamil		if (child2 == 0)
42121.1Skamil			_exit(exitval2);
42131.1Skamil
42141.1Skamil		FORKEE_REQUIRE_SUCCESS
42151.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
42161.1Skamil
42171.1Skamil		forkee_status_exited(status, exitval2);
42181.1Skamil
42191.13Schristos		DPRINTF("Before exiting of the child process\n");
42201.1Skamil		_exit(exitval);
42211.1Skamil	}
42221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42231.1Skamil
42241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42261.1Skamil
42271.1Skamil	validate_status_stopped(status, sigval);
42281.1Skamil
42291.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
42301.1Skamil	event.pe_set_event = PTRACE_FORK;
42311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
42321.1Skamil
42331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42341.1Skamil	    "without signal to be sent\n");
42351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42361.1Skamil
42371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42391.1Skamil
42401.1Skamil	validate_status_stopped(status, sigmasked);
42411.1Skamil
42421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
42431.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
42441.1Skamil
42451.1Skamil	child2 = state.pe_other_pid;
42461.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
42471.1Skamil
42481.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
42491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
42501.1Skamil	    child2);
42511.1Skamil
42521.1Skamil	validate_status_stopped(status, SIGTRAP);
42531.1Skamil
42541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
42551.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
42561.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
42571.1Skamil
42581.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
42591.1Skamil	    "without signal to be sent\n");
42601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
42611.1Skamil
42621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42631.1Skamil	    "without signal to be sent\n");
42641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42651.1Skamil
42661.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
42671.1Skamil	    TWAIT_FNAME);
42681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
42691.57Skamil	    child2);
42701.1Skamil
42711.1Skamil	validate_status_exited(status, exitval2);
42721.1Skamil
42731.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
42741.1Skamil	    TWAIT_FNAME);
42751.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
42761.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
42771.1Skamil
42781.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
42791.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
42801.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42811.1Skamil
42821.1Skamil	validate_status_stopped(status, SIGCHLD);
42831.1Skamil
42841.57Skamil	DPRINTF("Before resuming the child process where it left off and "
42851.1Skamil	    "without signal to be sent\n");
42861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42871.1Skamil
42881.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
42891.1Skamil	    TWAIT_FNAME);
42901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42911.1Skamil
42921.1Skamil	validate_status_exited(status, exitval);
42931.1Skamil
42941.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
42951.57Skamil	    TWAIT_FNAME);
42961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42971.1Skamil}
42981.1Skamil#endif
42991.1Skamil
43001.1Skamil#if defined(TWAIT_HAVE_PID)
43011.1SkamilATF_TC(signal7);
43021.1SkamilATF_TC_HEAD(signal7, tc)
43031.1Skamil{
43041.1Skamil	atf_tc_set_md_var(tc, "descr",
43051.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43061.1Skamil	    "catching PTRACE_VFORK breakpoint");
43071.1Skamil}
43081.1Skamil
43091.1SkamilATF_TC_BODY(signal7, tc)
43101.1Skamil{
43111.1Skamil	const int exitval = 5;
43121.1Skamil	const int exitval2 = 15;
43131.1Skamil	const int sigval = SIGSTOP;
43141.1Skamil	const int sigmasked = SIGTRAP;
43151.1Skamil	pid_t child, child2, wpid;
43161.1Skamil#if defined(TWAIT_HAVE_STATUS)
43171.1Skamil	int status;
43181.1Skamil#endif
43191.1Skamil	sigset_t intmask;
43201.1Skamil	ptrace_state_t state;
43211.1Skamil	const int slen = sizeof(state);
43221.1Skamil	ptrace_event_t event;
43231.1Skamil	const int elen = sizeof(event);
43241.1Skamil
43251.38Skamil	atf_tc_expect_fail("PR kern/51918");
43261.14Schristos
43271.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43281.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43291.1Skamil	if (child == 0) {
43301.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43311.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43321.1Skamil
43331.1Skamil		sigemptyset(&intmask);
43341.1Skamil		sigaddset(&intmask, sigmasked);
43351.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43361.1Skamil
43371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43391.1Skamil
43401.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
43411.1Skamil
43421.1Skamil		if (child2 == 0)
43431.1Skamil			_exit(exitval2);
43441.1Skamil
43451.1Skamil		FORKEE_REQUIRE_SUCCESS
43461.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
43471.1Skamil
43481.1Skamil		forkee_status_exited(status, exitval2);
43491.1Skamil
43501.13Schristos		DPRINTF("Before exiting of the child process\n");
43511.1Skamil		_exit(exitval);
43521.1Skamil	}
43531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43541.1Skamil
43551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43571.1Skamil
43581.1Skamil	validate_status_stopped(status, sigval);
43591.1Skamil
43601.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
43611.1Skamil	event.pe_set_event = PTRACE_VFORK;
43621.61Skre	SYSCALL_REQUIRE(
43631.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
43641.61Skre	    errno == ENOTSUP);
43651.1Skamil
43661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43671.1Skamil	    "without signal to be sent\n");
43681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43691.1Skamil
43701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43721.1Skamil
43731.1Skamil	validate_status_stopped(status, sigmasked);
43741.1Skamil
43751.61Skre	SYSCALL_REQUIRE(
43761.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
43771.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
43781.1Skamil
43791.1Skamil	child2 = state.pe_other_pid;
43801.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
43811.1Skamil
43821.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
43831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
43841.1Skamil	    child2);
43851.1Skamil
43861.1Skamil	validate_status_stopped(status, SIGTRAP);
43871.1Skamil
43881.61Skre	SYSCALL_REQUIRE(
43891.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
43901.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
43911.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
43921.1Skamil
43931.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
43941.1Skamil	    "without signal to be sent\n");
43951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
43961.1Skamil
43971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43981.1Skamil	    "without signal to be sent\n");
43991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44001.1Skamil
44011.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
44021.1Skamil	    TWAIT_FNAME);
44031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
44041.57Skamil	    child2);
44051.1Skamil
44061.1Skamil	validate_status_exited(status, exitval2);
44071.1Skamil
44081.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
44091.1Skamil	    TWAIT_FNAME);
44101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
44111.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
44121.1Skamil
44131.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
44141.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
44151.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44161.1Skamil
44171.1Skamil	validate_status_stopped(status, SIGCHLD);
44181.1Skamil
44191.57Skamil	DPRINTF("Before resuming the child process where it left off and "
44201.1Skamil	    "without signal to be sent\n");
44211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44221.1Skamil
44231.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
44241.1Skamil	    TWAIT_FNAME);
44251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44261.1Skamil
44271.1Skamil	validate_status_exited(status, exitval);
44281.1Skamil
44291.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
44301.57Skamil	    TWAIT_FNAME);
44311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44321.1Skamil}
44331.1Skamil#endif
44341.1Skamil
44351.1SkamilATF_TC(signal8);
44361.1SkamilATF_TC_HEAD(signal8, tc)
44371.1Skamil{
44381.1Skamil	atf_tc_set_md_var(tc, "descr",
44391.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44401.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
44411.1Skamil}
44421.1Skamil
44431.1SkamilATF_TC_BODY(signal8, tc)
44441.1Skamil{
44451.1Skamil	const int exitval = 5;
44461.1Skamil	const int exitval2 = 15;
44471.1Skamil	const int sigval = SIGSTOP;
44481.1Skamil	const int sigmasked = SIGTRAP;
44491.1Skamil	pid_t child, child2, wpid;
44501.1Skamil#if defined(TWAIT_HAVE_STATUS)
44511.1Skamil	int status;
44521.1Skamil#endif
44531.1Skamil	sigset_t intmask;
44541.1Skamil	ptrace_state_t state;
44551.1Skamil	const int slen = sizeof(state);
44561.1Skamil	ptrace_event_t event;
44571.1Skamil	const int elen = sizeof(event);
44581.1Skamil
44591.14Schristos	atf_tc_expect_fail("PR kern/51918");
44601.14Schristos
44611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44631.1Skamil	if (child == 0) {
44641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44661.1Skamil
44671.1Skamil		sigemptyset(&intmask);
44681.1Skamil		sigaddset(&intmask, sigmasked);
44691.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44701.1Skamil
44711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44731.1Skamil
44741.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
44751.1Skamil
44761.1Skamil		if (child2 == 0)
44771.1Skamil			_exit(exitval2);
44781.1Skamil
44791.1Skamil		FORKEE_REQUIRE_SUCCESS
44801.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
44811.1Skamil
44821.1Skamil		forkee_status_exited(status, exitval2);
44831.1Skamil
44841.13Schristos		DPRINTF("Before exiting of the child process\n");
44851.1Skamil		_exit(exitval);
44861.1Skamil	}
44871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44881.1Skamil
44891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44911.1Skamil
44921.1Skamil	validate_status_stopped(status, sigval);
44931.1Skamil
44941.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
44951.1Skamil	    child);
44961.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
44971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
44981.1Skamil
44991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45001.1Skamil	    "without signal to be sent\n");
45011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45021.1Skamil
45031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45051.1Skamil
45061.1Skamil	validate_status_stopped(status, sigmasked);
45071.1Skamil
45081.61Skre	SYSCALL_REQUIRE(
45091.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
45101.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
45111.1Skamil
45121.1Skamil	child2 = state.pe_other_pid;
45131.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
45141.1Skamil
45151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45161.1Skamil	    "without signal to be sent\n");
45171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45181.1Skamil
45191.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
45201.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
45211.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45221.1Skamil
45231.1Skamil	validate_status_stopped(status, SIGCHLD);
45241.1Skamil
45251.57Skamil	DPRINTF("Before resuming the child process where it left off and "
45261.1Skamil	    "without signal to be sent\n");
45271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45281.1Skamil
45291.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
45301.1Skamil	    TWAIT_FNAME);
45311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45321.1Skamil
45331.1Skamil	validate_status_exited(status, exitval);
45341.1Skamil
45351.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
45361.57Skamil	    TWAIT_FNAME);
45371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45381.1Skamil}
45391.1Skamil
45401.83Skamilvolatile lwpid_t the_lwp_id = 0;
45411.83Skamil
45421.83Skamilstatic void
45431.83Skamillwp_main_func(void *arg)
45441.83Skamil{
45451.83Skamil	the_lwp_id = _lwp_self();
45461.83Skamil	_lwp_exit();
45471.83Skamil}
45481.83Skamil
45491.1SkamilATF_TC(signal9);
45501.1SkamilATF_TC_HEAD(signal9, tc)
45511.1Skamil{
45521.1Skamil	atf_tc_set_md_var(tc, "descr",
45531.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45541.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
45551.1Skamil}
45561.1Skamil
45571.1SkamilATF_TC_BODY(signal9, tc)
45581.1Skamil{
45591.1Skamil	const int exitval = 5;
45601.1Skamil	const int sigval = SIGSTOP;
45611.1Skamil	const int sigmasked = SIGTRAP;
45621.1Skamil	pid_t child, wpid;
45631.1Skamil#if defined(TWAIT_HAVE_STATUS)
45641.1Skamil	int status;
45651.1Skamil#endif
45661.1Skamil	sigset_t intmask;
45671.1Skamil	ptrace_state_t state;
45681.1Skamil	const int slen = sizeof(state);
45691.1Skamil	ptrace_event_t event;
45701.1Skamil	const int elen = sizeof(event);
45711.1Skamil	ucontext_t uc;
45721.1Skamil	lwpid_t lid;
45731.1Skamil	static const size_t ssize = 16*1024;
45741.1Skamil	void *stack;
45751.1Skamil
45761.14Schristos	atf_tc_expect_fail("PR kern/51918");
45771.14Schristos
45781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45801.1Skamil	if (child == 0) {
45811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45831.1Skamil
45841.1Skamil		sigemptyset(&intmask);
45851.1Skamil		sigaddset(&intmask, sigmasked);
45861.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45871.1Skamil
45881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45901.1Skamil
45911.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
45921.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
45931.1Skamil
45941.13Schristos		DPRINTF("Before making context for new lwp in child\n");
45951.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
45961.1Skamil
45971.13Schristos		DPRINTF("Before creating new in child\n");
45981.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
45991.1Skamil
46001.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
46011.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
46021.1Skamil
46031.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
46041.1Skamil		    "are the same\n", lid, the_lwp_id);
46051.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
46061.1Skamil
46071.13Schristos		DPRINTF("Before exiting of the child process\n");
46081.1Skamil		_exit(exitval);
46091.1Skamil	}
46101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46111.1Skamil
46121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46141.1Skamil
46151.1Skamil	validate_status_stopped(status, sigval);
46161.1Skamil
46171.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
46181.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
46191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
46201.1Skamil
46211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46221.1Skamil	    "without signal to be sent\n");
46231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46241.1Skamil
46251.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
46261.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
46271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46281.1Skamil
46291.1Skamil	validate_status_stopped(status, sigmasked);
46301.1Skamil
46311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
46321.1Skamil
46331.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
46341.1Skamil
46351.1Skamil	lid = state.pe_lwp;
46361.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
46371.1Skamil
46381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46391.1Skamil	    "without signal to be sent\n");
46401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46411.1Skamil
46421.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
46431.1Skamil	    TWAIT_FNAME);
46441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46451.1Skamil
46461.1Skamil	validate_status_exited(status, exitval);
46471.1Skamil
46481.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
46491.1Skamil	    TWAIT_FNAME);
46501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46511.1Skamil}
46521.1Skamil
46531.1SkamilATF_TC(signal10);
46541.1SkamilATF_TC_HEAD(signal10, tc)
46551.1Skamil{
46561.1Skamil	atf_tc_set_md_var(tc, "descr",
46571.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
46581.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
46591.1Skamil}
46601.1Skamil
46611.1SkamilATF_TC_BODY(signal10, tc)
46621.1Skamil{
46631.1Skamil	const int exitval = 5;
46641.1Skamil	const int sigval = SIGSTOP;
46651.1Skamil	const int sigmasked = SIGTRAP;
46661.1Skamil	pid_t child, wpid;
46671.1Skamil#if defined(TWAIT_HAVE_STATUS)
46681.1Skamil	int status;
46691.1Skamil#endif
46701.1Skamil	sigset_t intmask;
46711.1Skamil	ptrace_state_t state;
46721.1Skamil	const int slen = sizeof(state);
46731.1Skamil	ptrace_event_t event;
46741.1Skamil	const int elen = sizeof(event);
46751.1Skamil	ucontext_t uc;
46761.1Skamil	lwpid_t lid;
46771.1Skamil	static const size_t ssize = 16*1024;
46781.1Skamil	void *stack;
46791.1Skamil
46801.14Schristos	atf_tc_expect_fail("PR kern/51918");
46811.14Schristos
46821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46841.1Skamil	if (child == 0) {
46851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46871.1Skamil
46881.1Skamil		sigemptyset(&intmask);
46891.1Skamil		sigaddset(&intmask, sigmasked);
46901.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46911.1Skamil
46921.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46931.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46941.1Skamil
46951.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
46961.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
46971.1Skamil
46981.13Schristos		DPRINTF("Before making context for new lwp in child\n");
46991.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
47001.1Skamil
47011.13Schristos		DPRINTF("Before creating new in child\n");
47021.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
47031.1Skamil
47041.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
47051.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
47061.1Skamil
47071.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
47081.1Skamil		    "are the same\n", lid, the_lwp_id);
47091.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
47101.1Skamil
47111.13Schristos		DPRINTF("Before exiting of the child process\n");
47121.1Skamil		_exit(exitval);
47131.1Skamil	}
47141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47151.1Skamil
47161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47181.1Skamil
47191.1Skamil	validate_status_stopped(status, sigval);
47201.1Skamil
47211.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
47221.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
47231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
47241.1Skamil
47251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47261.1Skamil	    "without signal to be sent\n");
47271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47281.1Skamil
47291.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
47301.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
47311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47321.1Skamil
47331.1Skamil	validate_status_stopped(status, sigmasked);
47341.1Skamil
47351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
47361.1Skamil
47371.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
47381.1Skamil
47391.1Skamil	lid = state.pe_lwp;
47401.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
47411.1Skamil
47421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47431.1Skamil	    "without signal to be sent\n");
47441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47451.1Skamil
47461.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
47471.1Skamil	    TWAIT_FNAME);
47481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47491.1Skamil
47501.1Skamil	validate_status_exited(status, exitval);
47511.1Skamil
47521.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
47531.1Skamil	    TWAIT_FNAME);
47541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47551.1Skamil}
47561.1Skamil
47571.1Skamilstatic void
47581.1Skamillwp_main_stop(void *arg)
47591.1Skamil{
47601.1Skamil	the_lwp_id = _lwp_self();
47611.1Skamil
47621.1Skamil	raise(SIGTRAP);
47631.1Skamil
47641.1Skamil	_lwp_exit();
47651.1Skamil}
47661.1Skamil
47671.1SkamilATF_TC(suspend1);
47681.1SkamilATF_TC_HEAD(suspend1, tc)
47691.1Skamil{
47701.1Skamil	atf_tc_set_md_var(tc, "descr",
47711.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
47721.1Skamil	    "resumed by a tracee");
47731.1Skamil}
47741.1Skamil
47751.1SkamilATF_TC_BODY(suspend1, tc)
47761.1Skamil{
47771.1Skamil	const int exitval = 5;
47781.1Skamil	const int sigval = SIGSTOP;
47791.1Skamil	pid_t child, wpid;
47801.1Skamil#if defined(TWAIT_HAVE_STATUS)
47811.1Skamil	int status;
47821.1Skamil#endif
47831.1Skamil	ucontext_t uc;
47841.1Skamil	lwpid_t lid;
47851.1Skamil	static const size_t ssize = 16*1024;
47861.1Skamil	void *stack;
47871.1Skamil	struct ptrace_lwpinfo pl;
47881.1Skamil	struct ptrace_siginfo psi;
47891.1Skamil	volatile int go = 0;
47901.1Skamil
47911.17Skamil	// Feature pending for refactoring
47921.17Skamil	atf_tc_expect_fail("PR kern/51995");
47931.17Skamil
47941.16Skamil	// Hangs with qemu
47951.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
47961.16Skamil
47971.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47981.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47991.1Skamil	if (child == 0) {
48001.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48011.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48021.1Skamil
48031.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48041.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48051.1Skamil
48061.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
48071.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
48081.1Skamil
48091.13Schristos		DPRINTF("Before making context for new lwp in child\n");
48101.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
48111.1Skamil
48121.13Schristos		DPRINTF("Before creating new in child\n");
48131.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
48141.1Skamil
48151.1Skamil		while (go == 0)
48161.1Skamil			continue;
48171.1Skamil
48181.1Skamil		raise(SIGINT);
48191.1Skamil
48201.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
48211.1Skamil
48221.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
48231.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
48241.1Skamil
48251.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
48261.1Skamil		    "are the same\n", lid, the_lwp_id);
48271.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
48281.1Skamil
48291.13Schristos		DPRINTF("Before exiting of the child process\n");
48301.1Skamil		_exit(exitval);
48311.1Skamil	}
48321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48331.1Skamil
48341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48361.1Skamil
48371.1Skamil	validate_status_stopped(status, sigval);
48381.1Skamil
48391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48401.1Skamil	    "without signal to be sent\n");
48411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48421.1Skamil
48431.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48441.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
48451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48461.1Skamil
48471.1Skamil	validate_status_stopped(status, SIGTRAP);
48481.1Skamil
48491.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
48501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
48511.1Skamil
48521.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
48531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
48541.1Skamil
48551.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
48561.1Skamil	    child, getpid());
48571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
48581.1Skamil
48591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48601.1Skamil	    "without signal to be sent\n");
48611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48621.1Skamil
48631.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48641.1Skamil	    "SIGINT\n", TWAIT_FNAME);
48651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48661.1Skamil
48671.1Skamil	validate_status_stopped(status, SIGINT);
48681.1Skamil
48691.1Skamil	pl.pl_lwpid = 0;
48701.1Skamil
48711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
48721.1Skamil	while (pl.pl_lwpid != 0) {
48731.1Skamil
48741.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
48751.1Skamil		switch (pl.pl_lwpid) {
48761.1Skamil		case 1:
48771.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
48781.1Skamil			break;
48791.1Skamil		case 2:
48801.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
48811.1Skamil			break;
48821.1Skamil		}
48831.1Skamil	}
48841.1Skamil
48851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48861.1Skamil	    "without signal to be sent\n");
48871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48881.1Skamil
48891.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48901.1Skamil	    TWAIT_FNAME);
48911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48921.1Skamil
48931.1Skamil	validate_status_exited(status, exitval);
48941.1Skamil
48951.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48961.1Skamil	    TWAIT_FNAME);
48971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48981.1Skamil}
48991.1Skamil
49001.1SkamilATF_TC(suspend2);
49011.1SkamilATF_TC_HEAD(suspend2, tc)
49021.1Skamil{
49031.1Skamil	atf_tc_set_md_var(tc, "descr",
49041.1Skamil	    "Verify that the while the only thread within a process is "
49051.1Skamil	    "suspended, the whole process cannot be unstopped");
49061.1Skamil}
49071.1Skamil
49081.1SkamilATF_TC_BODY(suspend2, tc)
49091.1Skamil{
49101.1Skamil	const int exitval = 5;
49111.1Skamil	const int sigval = SIGSTOP;
49121.1Skamil	pid_t child, wpid;
49131.1Skamil#if defined(TWAIT_HAVE_STATUS)
49141.1Skamil	int status;
49151.1Skamil#endif
49161.1Skamil	struct ptrace_siginfo psi;
49171.1Skamil
49181.17Skamil	// Feature pending for refactoring
49191.17Skamil	atf_tc_expect_fail("PR kern/51995");
49201.17Skamil
49211.16Skamil	// Hangs with qemu
49221.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
49231.16Skamil
49241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49261.1Skamil	if (child == 0) {
49271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49291.1Skamil
49301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49321.1Skamil
49331.13Schristos		DPRINTF("Before exiting of the child process\n");
49341.1Skamil		_exit(exitval);
49351.1Skamil	}
49361.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49371.1Skamil
49381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49401.1Skamil
49411.1Skamil	validate_status_stopped(status, sigval);
49421.1Skamil
49431.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
49441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
49451.1Skamil
49461.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
49471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
49481.1Skamil
49491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49501.1Skamil	    "without signal to be sent\n");
49511.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
49521.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
49531.1Skamil
49541.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
49551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
49561.1Skamil
49571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49581.1Skamil	    "without signal to be sent\n");
49591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49601.1Skamil
49611.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49621.1Skamil	    TWAIT_FNAME);
49631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49641.1Skamil
49651.1Skamil	validate_status_exited(status, exitval);
49661.1Skamil
49671.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49681.1Skamil	    TWAIT_FNAME);
49691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49701.1Skamil}
49711.1Skamil
49721.1SkamilATF_TC(resume1);
49731.1SkamilATF_TC_HEAD(resume1, tc)
49741.1Skamil{
49751.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
49761.1Skamil	atf_tc_set_md_var(tc, "descr",
49771.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
49781.1Skamil	    "resumed by the debugger");
49791.1Skamil}
49801.1Skamil
49811.1SkamilATF_TC_BODY(resume1, tc)
49821.1Skamil{
49831.1Skamil	struct msg_fds fds;
49841.1Skamil	const int exitval = 5;
49851.1Skamil	const int sigval = SIGSTOP;
49861.1Skamil	pid_t child, wpid;
49871.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
49881.1Skamil#if defined(TWAIT_HAVE_STATUS)
49891.1Skamil	int status;
49901.1Skamil#endif
49911.1Skamil	ucontext_t uc;
49921.1Skamil	lwpid_t lid;
49931.1Skamil	static const size_t ssize = 16*1024;
49941.1Skamil	void *stack;
49951.1Skamil	struct ptrace_lwpinfo pl;
49961.1Skamil	struct ptrace_siginfo psi;
49971.1Skamil
49981.17Skamil	// Feature pending for refactoring
49991.17Skamil	atf_tc_expect_fail("PR kern/51995");
50001.17Skamil
50011.15Schristos	// Hangs with qemu
50021.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
50031.1Skamil
50041.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
50051.1Skamil
50061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50081.1Skamil	if (child == 0) {
50091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50111.1Skamil
50121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50141.1Skamil
50151.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
50161.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
50171.1Skamil
50181.13Schristos		DPRINTF("Before making context for new lwp in child\n");
50191.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
50201.1Skamil
50211.13Schristos		DPRINTF("Before creating new in child\n");
50221.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
50231.1Skamil
50241.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
50251.1Skamil
50261.1Skamil		raise(SIGINT);
50271.1Skamil
50281.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
50291.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
50301.1Skamil
50311.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
50321.1Skamil		    "are the same\n", lid, the_lwp_id);
50331.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
50341.1Skamil
50351.13Schristos		DPRINTF("Before exiting of the child process\n");
50361.1Skamil		_exit(exitval);
50371.1Skamil	}
50381.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50391.1Skamil
50401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50421.1Skamil
50431.1Skamil	validate_status_stopped(status, sigval);
50441.1Skamil
50451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50461.1Skamil	    "without signal to be sent\n");
50471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50481.1Skamil
50491.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50501.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
50511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50521.1Skamil
50531.1Skamil	validate_status_stopped(status, SIGTRAP);
50541.1Skamil
50551.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
50561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
50571.1Skamil
50581.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
50591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
50601.1Skamil
50611.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
50621.1Skamil
50631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50641.1Skamil	    "without signal to be sent\n");
50651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50661.1Skamil
50671.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50681.1Skamil	    "SIGINT\n", TWAIT_FNAME);
50691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50701.1Skamil
50711.1Skamil	validate_status_stopped(status, SIGINT);
50721.1Skamil
50731.1Skamil	pl.pl_lwpid = 0;
50741.1Skamil
50751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
50761.1Skamil	while (pl.pl_lwpid != 0) {
50771.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
50781.1Skamil		switch (pl.pl_lwpid) {
50791.1Skamil		case 1:
50801.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
50811.1Skamil			break;
50821.1Skamil		case 2:
50831.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
50841.1Skamil			break;
50851.1Skamil		}
50861.1Skamil	}
50871.1Skamil
50881.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
50891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
50901.1Skamil
50911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50921.1Skamil	    "without signal to be sent\n");
50931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50941.1Skamil
50951.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
50961.1Skamil	    TWAIT_FNAME);
50971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50981.1Skamil
50991.1Skamil	validate_status_exited(status, exitval);
51001.1Skamil
51011.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51021.1Skamil	    TWAIT_FNAME);
51031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51041.1Skamil
51051.1Skamil	msg_close(&fds);
51061.1Skamil
51071.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
51081.1Skamil	sleep(10);
51091.1Skamil}
51101.1Skamil
51111.1SkamilATF_TC(syscall1);
51121.1SkamilATF_TC_HEAD(syscall1, tc)
51131.1Skamil{
51141.1Skamil	atf_tc_set_md_var(tc, "descr",
51151.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
51161.1Skamil}
51171.1Skamil
51181.1SkamilATF_TC_BODY(syscall1, tc)
51191.1Skamil{
51201.1Skamil	const int exitval = 5;
51211.1Skamil	const int sigval = SIGSTOP;
51221.1Skamil	pid_t child, wpid;
51231.1Skamil#if defined(TWAIT_HAVE_STATUS)
51241.1Skamil	int status;
51251.1Skamil#endif
51261.1Skamil	struct ptrace_siginfo info;
51271.1Skamil	memset(&info, 0, sizeof(info));
51281.1Skamil
51291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51311.1Skamil	if (child == 0) {
51321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51341.1Skamil
51351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51371.1Skamil
51381.1Skamil		syscall(SYS_getpid);
51391.1Skamil
51401.13Schristos		DPRINTF("Before exiting of the child process\n");
51411.1Skamil		_exit(exitval);
51421.1Skamil	}
51431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51441.1Skamil
51451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51471.1Skamil
51481.1Skamil	validate_status_stopped(status, sigval);
51491.1Skamil
51501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51511.1Skamil	    "without signal to be sent\n");
51521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51531.1Skamil
51541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51561.1Skamil
51571.1Skamil	validate_status_stopped(status, SIGTRAP);
51581.1Skamil
51591.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51611.1Skamil
51621.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
51631.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
51641.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51651.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
51661.1Skamil
51671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51681.1Skamil	    "without signal to be sent\n");
51691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51701.1Skamil
51711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51731.1Skamil
51741.1Skamil	validate_status_stopped(status, SIGTRAP);
51751.1Skamil
51761.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51781.1Skamil
51791.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
51801.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
51811.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51821.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
51831.1Skamil
51841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51851.1Skamil	    "without signal to be sent\n");
51861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51871.1Skamil
51881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51901.1Skamil
51911.1Skamil	validate_status_exited(status, exitval);
51921.1Skamil
51931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51951.1Skamil}
51961.1Skamil
51971.1SkamilATF_TC(syscallemu1);
51981.1SkamilATF_TC_HEAD(syscallemu1, tc)
51991.1Skamil{
52001.1Skamil	atf_tc_set_md_var(tc, "descr",
52011.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
52021.1Skamil}
52031.1Skamil
52041.1SkamilATF_TC_BODY(syscallemu1, tc)
52051.1Skamil{
52061.1Skamil	const int exitval = 5;
52071.1Skamil	const int sigval = SIGSTOP;
52081.1Skamil	pid_t child, wpid;
52091.1Skamil#if defined(TWAIT_HAVE_STATUS)
52101.1Skamil	int status;
52111.1Skamil#endif
52121.1Skamil
52131.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
52141.6Skamil	/* syscallemu does not work on sparc (32-bit) */
52151.6Skamil	atf_tc_expect_fail("PR kern/52166");
52161.6Skamil#endif
52171.6Skamil
52181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52201.1Skamil	if (child == 0) {
52211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52231.1Skamil
52241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52261.1Skamil
52271.1Skamil		syscall(SYS_exit, 100);
52281.1Skamil
52291.13Schristos		DPRINTF("Before exiting of the child process\n");
52301.1Skamil		_exit(exitval);
52311.1Skamil	}
52321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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_stopped(status, sigval);
52381.1Skamil
52391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52401.1Skamil	    "without signal to be sent\n");
52411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
52421.1Skamil
52431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52451.1Skamil
52461.1Skamil	validate_status_stopped(status, SIGTRAP);
52471.1Skamil
52481.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
52491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
52501.1Skamil
52511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52521.1Skamil	    "without signal to be sent\n");
52531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
52541.1Skamil
52551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52571.1Skamil
52581.1Skamil	validate_status_stopped(status, SIGTRAP);
52591.1Skamil
52601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52611.1Skamil	    "without signal to be sent\n");
52621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52631.1Skamil
52641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52661.1Skamil
52671.1Skamil	validate_status_exited(status, exitval);
52681.1Skamil
52691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52711.1Skamil}
52721.1Skamil
52731.1Skamil#include "t_ptrace_amd64_wait.h"
52741.1Skamil#include "t_ptrace_i386_wait.h"
52751.1Skamil#include "t_ptrace_x86_wait.h"
52761.1Skamil
52771.1SkamilATF_TP_ADD_TCS(tp)
52781.1Skamil{
52791.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
52801.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
52811.33Skamil
52821.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
52831.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
52841.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
52851.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
52861.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
52871.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
52881.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
52891.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
52901.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
52911.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
52921.33Skamil
52931.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
52941.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
52951.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
52961.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
52971.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
52981.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
52991.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
53001.86Skamil	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
53011.86Skamil
53021.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
53031.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
53041.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
53051.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
53061.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
53071.59Skamil
53081.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
53091.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
53101.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
53111.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
53121.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
53131.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
53141.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
53151.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
53161.50Skamil
53171.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
53181.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
53191.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
53201.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
53211.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
53221.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
53231.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
53241.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
53251.50Skamil
53261.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
53271.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
53281.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
53291.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
53301.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
53311.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
53321.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
53331.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
53341.50Skamil
53351.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
53361.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
53371.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
53381.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
53391.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
53401.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
53411.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
53421.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
53431.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
53441.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
53451.1Skamil
53461.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
53471.37Skamil
53481.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
53491.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
53501.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
53511.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
53521.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
53531.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
53541.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
53551.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
53561.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
53571.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
53581.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
53591.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
53601.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
53611.40Skamil
53621.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
53631.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
53641.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
53651.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
53661.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
53671.41Skamil
53681.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
53691.43Skamil
53701.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
53711.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
53721.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
53731.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
53741.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
53751.59Skamil
53761.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
53771.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
53781.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
53791.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
53801.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
53811.51Skamil
53821.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
53831.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
53841.51Skamil
53851.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
53861.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
53871.51Skamil
53881.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
53891.51Skamil		tracee_sees_its_original_parent_getppid);
53901.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
53911.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
53921.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
53931.51Skamil		tracee_sees_its_original_parent_procfs_status);
53941.1Skamil
53951.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
53961.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
53971.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
53981.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
53991.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
54001.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
54011.1Skamil
54021.31Skamil	ATF_TP_ADD_TC(tp, fork1);
54031.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
54041.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
54051.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
54061.31Skamil	ATF_TP_ADD_TC(tp, fork5);
54071.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
54081.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
54091.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
54101.31Skamil
54111.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
54121.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
54131.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
54141.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
54151.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
54161.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
54171.64Smartin// thes tests hang on SMP machines, disable them for now
54181.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
54191.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
54201.1Skamil
54211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
54221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
54231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
54241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
54251.54Skamil
54261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
54271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
54281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
54291.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
54301.54Skamil
54311.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
54321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
54331.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
54341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
54351.54Skamil
54361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
54371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
54381.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
54391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
54401.54Skamil
54411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
54421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
54431.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
54441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
54451.54Skamil
54461.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
54471.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
54481.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
54491.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
54501.54Skamil
54511.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
54521.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
54531.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
54541.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
54551.54Skamil
54561.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
54571.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
54581.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
54591.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
54601.54Skamil
54611.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
54621.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
54631.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
54641.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
54651.54Skamil
54661.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
54671.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
54681.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
54691.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
54701.1Skamil
54711.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
54721.1Skamil
54731.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
54741.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
54751.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
54761.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
54771.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
54781.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
54791.1Skamil
54801.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
54811.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
54821.1Skamil
54831.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
54841.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
54851.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
54861.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
54871.1Skamil
54881.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
54891.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
54901.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
54911.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
54921.2Skamil
54931.1Skamil	ATF_TP_ADD_TC(tp, kill1);
54941.1Skamil	ATF_TP_ADD_TC(tp, kill2);
54951.75Skamil	ATF_TP_ADD_TC(tp, kill3);
54961.1Skamil
54971.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
54981.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
54991.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
55001.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
55011.77Skamil
55021.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
55031.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
55041.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
55051.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
55061.1Skamil
55071.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
55081.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
55091.79Skamil
55101.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
55111.1Skamil
55121.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
55131.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
55141.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
55151.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
55161.1Skamil
55171.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
55181.84Skamil
55191.1Skamil	ATF_TP_ADD_TC(tp, signal3);
55201.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
55211.1Skamil	ATF_TP_ADD_TC(tp, signal5);
55221.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
55231.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
55241.1Skamil	ATF_TP_ADD_TC(tp, signal8);
55251.1Skamil	ATF_TP_ADD_TC(tp, signal9);
55261.1Skamil	ATF_TP_ADD_TC(tp, signal10);
55271.1Skamil
55281.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
55291.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
55301.1Skamil
55311.1Skamil	ATF_TP_ADD_TC(tp, resume1);
55321.1Skamil
55331.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
55341.1Skamil
55351.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
55361.1Skamil
55371.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
55381.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
55391.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
55401.1Skamil
55411.1Skamil	return atf_no_error();
55421.1Skamil}
5543