t_ptrace_wait.c revision 1.84
11.84Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.84 2019/02/12 21:35:35 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc.
51.1Skamil * All rights reserved.
61.1Skamil *
71.1Skamil * Redistribution and use in source and binary forms, with or without
81.1Skamil * modification, are permitted provided that the following conditions
91.1Skamil * are met:
101.1Skamil * 1. Redistributions of source code must retain the above copyright
111.1Skamil *    notice, this list of conditions and the following disclaimer.
121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright
131.1Skamil *    notice, this list of conditions and the following disclaimer in the
141.1Skamil *    documentation and/or other materials provided with the distribution.
151.1Skamil *
161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Skamil * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Skamil * POSSIBILITY OF SUCH DAMAGE.
271.1Skamil */
281.1Skamil
291.1Skamil#include <sys/cdefs.h>
301.84Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.84 2019/02/12 21:35:35 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.77Skamil#include <pthread.h>
471.1Skamil#include <sched.h>
481.1Skamil#include <signal.h>
491.1Skamil#include <stdint.h>
501.1Skamil#include <stdio.h>
511.1Skamil#include <stdlib.h>
521.1Skamil#include <strings.h>
531.26Skamil#include <time.h>
541.1Skamil#include <unistd.h>
551.1Skamil
561.1Skamil#include <atf-c.h>
571.1Skamil
581.1Skamil#include "h_macros.h"
591.1Skamil
601.1Skamil#include "t_ptrace_wait.h"
611.1Skamil#include "msg.h"
621.1Skamil
631.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
641.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
651.61Skre	sizeof(msg)) == 0)
661.1Skamil
671.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
681.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
691.61Skre	sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
721.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
731.61Skre	sizeof(msg)) == 0)
741.1Skamil
751.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
761.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
771.61Skre	sizeof(msg)) == 0)
781.13Schristos
791.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
801.13Schristos    strerror(errno))
811.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
821.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
831.13Schristos
841.13Schristosstatic int debug = 0;
851.13Schristos
861.13Schristos#define DPRINTF(a, ...)	do  \
871.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
881.13Schristos    while (/*CONSTCOND*/0)
891.1Skamil
901.34Skamil/// ----------------------------------------------------------------------------
911.34Skamil
921.33Skamilstatic void
931.33Skamiltraceme_raise(int sigval)
941.1Skamil{
951.1Skamil	const int exitval = 5;
961.1Skamil	pid_t child, wpid;
971.1Skamil#if defined(TWAIT_HAVE_STATUS)
981.1Skamil	int status;
991.1Skamil#endif
1001.1Skamil
1011.45Skamil	struct ptrace_siginfo info;
1021.45Skamil	memset(&info, 0, sizeof(info));
1031.45Skamil
1041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1061.1Skamil	if (child == 0) {
1071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1091.1Skamil
1101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1121.1Skamil
1131.36Skamil		switch (sigval) {
1141.36Skamil		case SIGKILL:
1151.36Skamil			/* NOTREACHED */
1161.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1171.70Smrg			__unreachable();
1181.36Skamil		default:
1191.36Skamil			DPRINTF("Before exiting of the child process\n");
1201.36Skamil			_exit(exitval);
1211.36Skamil		}
1221.1Skamil	}
1231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1241.1Skamil
1251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1271.1Skamil
1281.36Skamil	switch (sigval) {
1291.36Skamil	case SIGKILL:
1301.36Skamil		validate_status_signaled(status, sigval, 0);
1311.36Skamil		break;
1321.36Skamil	default:
1331.36Skamil		validate_status_stopped(status, sigval);
1341.1Skamil
1351.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1361.61Skre			"child\n");
1371.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1381.61Skre			sizeof(info)) != -1);
1391.45Skamil
1401.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1411.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1421.61Skre			"si_errno=%#x\n",
1431.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1441.61Skre			info.psi_siginfo.si_errno);
1451.45Skamil
1461.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1471.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1481.45Skamil
1491.36Skamil		DPRINTF("Before resuming the child process where it left off "
1501.36Skamil		    "and without signal to be sent\n");
1511.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1521.1Skamil
1531.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1541.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1551.61Skre		    child);
1561.36Skamil		break;
1571.36Skamil	}
1581.1Skamil
1591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1611.1Skamil}
1621.1Skamil
1631.61Skre#define TRACEME_RAISE(test, sig)					\
1641.61SkreATF_TC(test);								\
1651.61SkreATF_TC_HEAD(test, tc)							\
1661.61Skre{									\
1671.61Skre	atf_tc_set_md_var(tc, "descr",					\
1681.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1691.61Skre}									\
1701.61Skre									\
1711.61SkreATF_TC_BODY(test, tc)							\
1721.61Skre{									\
1731.61Skre									\
1741.61Skre	traceme_raise(sig);						\
1751.33Skamil}
1761.33Skamil
1771.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1781.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1791.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1801.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1811.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1821.33Skamil
1831.34Skamil/// ----------------------------------------------------------------------------
1841.1Skamil
1851.1Skamilstatic void
1861.59Skamiltraceme_crash(int sig)
1871.59Skamil{
1881.59Skamil	pid_t child, wpid;
1891.59Skamil#if defined(TWAIT_HAVE_STATUS)
1901.59Skamil	int status;
1911.59Skamil#endif
1921.59Skamil	struct ptrace_siginfo info;
1931.61Skre
1941.71Skamil#ifndef PTRACE_ILLEGAL_ASM
1951.71Skamil	if (sig == SIGILL)
1961.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
1971.71Skamil#endif
1981.71Skamil
1991.59Skamil	memset(&info, 0, sizeof(info));
2001.59Skamil
2011.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2021.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2031.59Skamil	if (child == 0) {
2041.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2051.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2061.59Skamil
2071.59Skamil		DPRINTF("Before executing a trap\n");
2081.59Skamil		switch (sig) {
2091.59Skamil		case SIGTRAP:
2101.59Skamil			trigger_trap();
2111.59Skamil			break;
2121.59Skamil		case SIGSEGV:
2131.59Skamil			trigger_segv();
2141.59Skamil			break;
2151.59Skamil		case SIGILL:
2161.59Skamil			trigger_ill();
2171.59Skamil			break;
2181.59Skamil		case SIGFPE:
2191.59Skamil			trigger_fpe();
2201.59Skamil			break;
2211.59Skamil		case SIGBUS:
2221.59Skamil			trigger_bus();
2231.59Skamil			break;
2241.59Skamil		default:
2251.59Skamil			/* NOTREACHED */
2261.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2271.59Skamil		}
2281.59Skamil
2291.59Skamil		/* NOTREACHED */
2301.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
2311.59Skamil	}
2321.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2331.59Skamil
2341.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2351.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2361.59Skamil
2371.59Skamil	validate_status_stopped(status, sig);
2381.59Skamil
2391.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
2401.61Skre	SYSCALL_REQUIRE(
2411.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2421.59Skamil
2431.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2441.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2451.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2461.61Skre	    info.psi_siginfo.si_errno);
2471.59Skamil
2481.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
2491.59Skamil	switch (sig) {
2501.59Skamil	case SIGTRAP:
2511.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
2521.59Skamil		break;
2531.59Skamil	case SIGSEGV:
2541.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
2551.59Skamil		break;
2561.71Skamil	case SIGILL:
2571.71Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
2581.71Skamil		break;
2591.59Skamil	case SIGFPE:
2601.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
2611.59Skamil		break;
2621.59Skamil	case SIGBUS:
2631.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
2641.59Skamil		break;
2651.59Skamil	}
2661.59Skamil
2671.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
2681.59Skamil
2691.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2701.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2711.59Skamil
2721.59Skamil	validate_status_signaled(status, SIGKILL, 0);
2731.59Skamil
2741.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2751.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2761.59Skamil}
2771.59Skamil
2781.61Skre#define TRACEME_CRASH(test, sig)					\
2791.61SkreATF_TC(test);								\
2801.61SkreATF_TC_HEAD(test, tc)							\
2811.61Skre{									\
2821.61Skre	atf_tc_set_md_var(tc, "descr",					\
2831.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
2841.61Skre}									\
2851.61Skre									\
2861.61SkreATF_TC_BODY(test, tc)							\
2871.61Skre{									\
2881.61Skre									\
2891.61Skre	traceme_crash(sig);						\
2901.59Skamil}
2911.59Skamil
2921.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
2931.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
2941.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
2951.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
2961.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
2971.59Skamil
2981.59Skamil/// ----------------------------------------------------------------------------
2991.59Skamil
3001.59Skamilstatic void
3011.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
3021.1Skamil{
3031.1Skamil	const int exitval = 5;
3041.34Skamil	const int sigval = SIGSTOP;
3051.1Skamil	pid_t child, wpid;
3061.1Skamil	struct sigaction sa;
3071.1Skamil#if defined(TWAIT_HAVE_STATUS)
3081.1Skamil	int status;
3091.1Skamil#endif
3101.61Skre	struct ptrace_siginfo info;
3111.1Skamil
3121.45Skamil	memset(&info, 0, sizeof(info));
3131.45Skamil
3141.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
3151.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
3161.1Skamil	if (child == 0) {
3171.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3181.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3191.1Skamil
3201.34Skamil		sa.sa_handler = sah;
3211.1Skamil		sa.sa_flags = SA_SIGINFO;
3221.1Skamil		sigemptyset(&sa.sa_mask);
3231.1Skamil
3241.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
3251.1Skamil
3261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3281.1Skamil
3291.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
3301.1Skamil
3311.13Schristos		DPRINTF("Before exiting of the child process\n");
3321.1Skamil		_exit(exitval);
3331.1Skamil	}
3341.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3351.1Skamil
3361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3381.1Skamil
3391.1Skamil	validate_status_stopped(status, sigval);
3401.1Skamil
3411.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3421.61Skre	SYSCALL_REQUIRE(
3431.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3441.45Skamil
3451.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3461.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3471.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3481.45Skamil	    info.psi_siginfo.si_errno);
3491.45Skamil
3501.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3511.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3521.45Skamil
3531.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
3541.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
3551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
3561.1Skamil
3571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3591.1Skamil
3601.1Skamil	validate_status_exited(status, exitval);
3611.1Skamil
3621.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3641.1Skamil}
3651.1Skamil
3661.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
3671.61SkreATF_TC(test);								\
3681.61SkreATF_TC_HEAD(test, tc)							\
3691.61Skre{									\
3701.61Skre	atf_tc_set_md_var(tc, "descr",					\
3711.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
3721.61Skre	    "handled correctly and caught by a signal handler");	\
3731.61Skre}									\
3741.61Skre									\
3751.61Skrestatic int test##_caught = 0;						\
3761.61Skre									\
3771.61Skrestatic void								\
3781.61Skretest##_sighandler(int arg)						\
3791.61Skre{									\
3801.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
3811.61Skre									\
3821.61Skre	++ test##_caught;						\
3831.61Skre}									\
3841.61Skre									\
3851.61SkreATF_TC_BODY(test, tc)							\
3861.61Skre{									\
3871.61Skre									\
3881.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
3891.34Skamil}
3901.34Skamil
3911.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
3921.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
3931.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
3941.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
3951.34Skamil
3961.34Skamil/// ----------------------------------------------------------------------------
3971.34Skamil
3981.35Skamilstatic void
3991.50Skamiltraceme_sendsignal_masked(int sigsent)
4001.50Skamil{
4011.50Skamil	const int exitval = 5;
4021.50Skamil	const int sigval = SIGSTOP;
4031.50Skamil	pid_t child, wpid;
4041.50Skamil	sigset_t set;
4051.50Skamil#if defined(TWAIT_HAVE_STATUS)
4061.50Skamil	int status;
4071.50Skamil#endif
4081.61Skre	struct ptrace_siginfo info;
4091.50Skamil
4101.50Skamil	memset(&info, 0, sizeof(info));
4111.50Skamil
4121.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4131.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4141.50Skamil	if (child == 0) {
4151.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4161.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4171.50Skamil
4181.50Skamil		sigemptyset(&set);
4191.50Skamil		sigaddset(&set, sigsent);
4201.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
4211.50Skamil
4221.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4231.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4241.50Skamil
4251.50Skamil		_exit(exitval);
4261.50Skamil	}
4271.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4281.50Skamil
4291.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4301.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4311.50Skamil
4321.50Skamil	validate_status_stopped(status, sigval);
4331.50Skamil
4341.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4351.61Skre	SYSCALL_REQUIRE(
4361.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4371.50Skamil
4381.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4391.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4401.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4411.50Skamil	    info.psi_siginfo.si_errno);
4421.50Skamil
4431.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4441.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4451.50Skamil
4461.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
4471.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4481.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4491.50Skamil
4501.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4511.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4521.50Skamil
4531.50Skamil	validate_status_exited(status, exitval);
4541.50Skamil
4551.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
4561.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4571.50Skamil}
4581.50Skamil
4591.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
4601.61SkreATF_TC(test);								\
4611.61SkreATF_TC_HEAD(test, tc)							\
4621.61Skre{									\
4631.61Skre	atf_tc_set_md_var(tc, "descr",					\
4641.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
4651.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
4661.61Skre}									\
4671.61Skre									\
4681.61SkreATF_TC_BODY(test, tc)							\
4691.61Skre{									\
4701.61Skre									\
4711.61Skre	traceme_sendsignal_masked(sig);					\
4721.50Skamil}
4731.50Skamil
4741.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4751.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
4761.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
4771.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
4781.50Skamil
4791.50Skamil/// ----------------------------------------------------------------------------
4801.50Skamil
4811.50Skamilstatic void
4821.50Skamiltraceme_sendsignal_ignored(int sigsent)
4831.50Skamil{
4841.50Skamil	const int exitval = 5;
4851.50Skamil	const int sigval = SIGSTOP;
4861.50Skamil	pid_t child, wpid;
4871.50Skamil	struct sigaction sa;
4881.50Skamil#if defined(TWAIT_HAVE_STATUS)
4891.50Skamil	int status;
4901.50Skamil#endif
4911.61Skre	struct ptrace_siginfo info;
4921.50Skamil
4931.50Skamil	memset(&info, 0, sizeof(info));
4941.50Skamil
4951.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4961.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4971.50Skamil	if (child == 0) {
4981.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4991.61Skre
5001.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5011.50Skamil
5021.50Skamil		memset(&sa, 0, sizeof(sa));
5031.50Skamil		sa.sa_handler = SIG_IGN;
5041.50Skamil		sigemptyset(&sa.sa_mask);
5051.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
5061.50Skamil
5071.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5081.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5091.50Skamil
5101.50Skamil		_exit(exitval);
5111.50Skamil	}
5121.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5131.50Skamil
5141.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5151.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5161.50Skamil
5171.50Skamil	validate_status_stopped(status, sigval);
5181.50Skamil
5191.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5201.61Skre	SYSCALL_REQUIRE(
5211.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5221.50Skamil
5231.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5241.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5251.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5261.50Skamil	    info.psi_siginfo.si_errno);
5271.50Skamil
5281.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5291.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5301.50Skamil
5311.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
5321.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
5331.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
5341.50Skamil
5351.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5361.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5371.50Skamil
5381.50Skamil	validate_status_exited(status, exitval);
5391.50Skamil
5401.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5411.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5421.50Skamil}
5431.50Skamil
5441.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
5451.61SkreATF_TC(test);								\
5461.61SkreATF_TC_HEAD(test, tc)							\
5471.61Skre{									\
5481.61Skre	atf_tc_set_md_var(tc, "descr",					\
5491.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
5501.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
5511.61Skre}									\
5521.61Skre									\
5531.61SkreATF_TC_BODY(test, tc)							\
5541.61Skre{									\
5551.61Skre									\
5561.61Skre	traceme_sendsignal_ignored(sig);				\
5571.50Skamil}
5581.50Skamil
5591.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
5601.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
5611.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
5621.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
5631.50Skamil
5641.50Skamil/// ----------------------------------------------------------------------------
5651.50Skamil
5661.50Skamilstatic void
5671.50Skamiltraceme_sendsignal_simple(int sigsent)
5681.1Skamil{
5691.35Skamil	const int sigval = SIGSTOP;
5701.35Skamil	int exitval = 0;
5711.1Skamil	pid_t child, wpid;
5721.1Skamil#if defined(TWAIT_HAVE_STATUS)
5731.1Skamil	int status;
5741.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
5751.1Skamil#endif
5761.61Skre	struct ptrace_siginfo info;
5771.1Skamil
5781.45Skamil	memset(&info, 0, sizeof(info));
5791.45Skamil
5801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
5811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
5821.1Skamil	if (child == 0) {
5831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5851.1Skamil
5861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5881.1Skamil
5891.35Skamil		switch (sigsent) {
5901.35Skamil		case SIGCONT:
5911.48Skamil		case SIGSTOP:
5921.35Skamil			_exit(exitval);
5931.35Skamil		default:
5941.35Skamil			/* NOTREACHED */
5951.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5961.35Skamil		}
5971.1Skamil	}
5981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5991.1Skamil
6001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6021.1Skamil
6031.1Skamil	validate_status_stopped(status, sigval);
6041.1Skamil
6051.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6061.61Skre	SYSCALL_REQUIRE(
6071.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6081.45Skamil
6091.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6101.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6111.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6121.45Skamil	    info.psi_siginfo.si_errno);
6131.45Skamil
6141.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6151.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6161.45Skamil
6171.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
6181.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
6191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
6201.1Skamil
6211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6231.1Skamil
6241.35Skamil	switch (sigsent) {
6251.48Skamil	case SIGSTOP:
6261.48Skamil		validate_status_stopped(status, sigsent);
6271.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
6281.61Skre		    "child\n");
6291.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
6301.61Skre		    sizeof(info)) != -1);
6311.48Skamil
6321.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6331.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
6341.61Skre		    "si_errno=%#x\n",
6351.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6361.61Skre		    info.psi_siginfo.si_errno);
6371.48Skamil
6381.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6391.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6401.48Skamil
6411.48Skamil		DPRINTF("Before resuming the child process where it left off "
6421.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
6431.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6441.48Skamil
6451.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6461.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
6471.61Skre		    child);
6481.48Skamil		/* FALLTHROUGH */
6491.35Skamil	case SIGCONT:
6501.35Skamil		validate_status_exited(status, exitval);
6511.35Skamil		break;
6521.35Skamil	default:
6531.35Skamil		validate_status_signaled(status, sigsent, expect_core);
6541.35Skamil		break;
6551.35Skamil	}
6561.1Skamil
6571.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
6581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6591.1Skamil}
6601.1Skamil
6611.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
6621.61SkreATF_TC(test);								\
6631.61SkreATF_TC_HEAD(test, tc)							\
6641.61Skre{									\
6651.61Skre	atf_tc_set_md_var(tc, "descr",					\
6661.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
6671.61Skre	    "handled correctly in a child without a signal handler");	\
6681.61Skre}									\
6691.61Skre									\
6701.61SkreATF_TC_BODY(test, tc)							\
6711.61Skre{									\
6721.61Skre									\
6731.61Skre	traceme_sendsignal_simple(sig);					\
6741.35Skamil}
6751.35Skamil
6761.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
6771.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
6781.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
6791.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
6801.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
6811.35Skamil
6821.35Skamil/// ----------------------------------------------------------------------------
6831.35Skamil
6841.37SkamilATF_TC(traceme_pid1_parent);
6851.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
6861.37Skamil{
6871.37Skamil	atf_tc_set_md_var(tc, "descr",
6881.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
6891.37Skamil}
6901.37Skamil
6911.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
6921.37Skamil{
6931.37Skamil	struct msg_fds parent_child;
6941.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
6951.37Skamil	pid_t child1, child2, wpid;
6961.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6971.37Skamil#if defined(TWAIT_HAVE_STATUS)
6981.37Skamil	int status;
6991.37Skamil#endif
7001.37Skamil
7011.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
7021.37Skamil
7031.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7041.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
7051.37Skamil	if (child1 == 0) {
7061.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
7071.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
7081.37Skamil		if (child2 != 0) {
7091.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
7101.61Skre			    getpid(), child2);
7111.37Skamil			_exit(exitval_child1);
7121.37Skamil		}
7131.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
7141.37Skamil
7151.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
7161.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
7171.37Skamil
7181.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7191.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
7201.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
7211.37Skamil
7221.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
7231.37Skamil
7241.37Skamil		_exit(exitval_child2);
7251.37Skamil	}
7261.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
7271.37Skamil
7281.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7291.61Skre	TWAIT_REQUIRE_SUCCESS(
7301.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
7311.37Skamil
7321.37Skamil	validate_status_exited(status, exitval_child1);
7331.37Skamil
7341.37Skamil	DPRINTF("Notify that child1 is dead\n");
7351.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
7361.37Skamil
7371.37Skamil	DPRINTF("Wait for exiting of child2\n");
7381.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
7391.37Skamil}
7401.37Skamil
7411.37Skamil/// ----------------------------------------------------------------------------
7421.37Skamil
7431.40Skamilstatic void
7441.40Skamiltraceme_vfork_raise(int sigval)
7451.40Skamil{
7461.46Skamil	const int exitval = 5, exitval_watcher = 10;
7471.46Skamil	pid_t child, parent, watcher, wpid;
7481.46Skamil	int rv;
7491.40Skamil#if defined(TWAIT_HAVE_STATUS)
7501.40Skamil	int status;
7511.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
7521.40Skamil#endif
7531.40Skamil
7541.46Skamil	/*
7551.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
7561.46Skamil	 * the SIGKILL signal to it.
7571.46Skamil	 *
7581.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
7591.46Skamil	 * simpler to reparent this process to initproc and forget about it.
7601.46Skamil	 */
7611.46Skamil	if (sigval == SIGSTOP) {
7621.46Skamil		parent = getpid();
7631.46Skamil
7641.46Skamil		watcher = fork();
7651.46Skamil		ATF_REQUIRE(watcher != 1);
7661.46Skamil		if (watcher == 0) {
7671.46Skamil			/* Double fork(2) trick to reparent to initproc */
7681.46Skamil			watcher = fork();
7691.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
7701.46Skamil			if (watcher != 0)
7711.46Skamil				_exit(exitval_watcher);
7721.46Skamil
7731.46Skamil			child = await_stopped_child(parent);
7741.46Skamil
7751.46Skamil			errno = 0;
7761.46Skamil			rv = kill(child, SIGKILL);
7771.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
7781.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
7791.46Skamil
7801.46Skamil			/* This exit value will be collected by initproc */
7811.46Skamil			_exit(0);
7821.46Skamil		}
7831.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7841.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
7851.61Skre		    watcher);
7861.46Skamil
7871.46Skamil		validate_status_exited(status, exitval_watcher);
7881.46Skamil
7891.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7901.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
7911.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
7921.46Skamil	}
7931.46Skamil
7941.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7951.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
7961.40Skamil	if (child == 0) {
7971.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7981.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7991.40Skamil
8001.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
8011.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
8021.40Skamil
8031.40Skamil		switch (sigval) {
8041.46Skamil		case SIGSTOP:
8051.40Skamil		case SIGKILL:
8061.40Skamil		case SIGABRT:
8071.40Skamil		case SIGHUP:
8081.40Skamil			/* NOTREACHED */
8091.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
8101.70Smrg			__unreachable();
8111.40Skamil		default:
8121.40Skamil			DPRINTF("Before exiting of the child process\n");
8131.40Skamil			_exit(exitval);
8141.40Skamil		}
8151.40Skamil	}
8161.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8171.40Skamil
8181.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8191.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8201.40Skamil
8211.40Skamil	switch (sigval) {
8221.40Skamil	case SIGKILL:
8231.40Skamil	case SIGABRT:
8241.40Skamil	case SIGHUP:
8251.40Skamil		validate_status_signaled(status, sigval, expect_core);
8261.40Skamil		break;
8271.40Skamil	case SIGSTOP:
8281.46Skamil		validate_status_signaled(status, SIGKILL, 0);
8291.46Skamil		break;
8301.40Skamil	case SIGCONT:
8311.47Skamil	case SIGTSTP:
8321.47Skamil	case SIGTTIN:
8331.47Skamil	case SIGTTOU:
8341.40Skamil		validate_status_exited(status, exitval);
8351.40Skamil		break;
8361.40Skamil	default:
8371.40Skamil		/* NOTREACHED */
8381.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
8391.40Skamil		break;
8401.40Skamil	}
8411.40Skamil
8421.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8431.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8441.40Skamil}
8451.40Skamil
8461.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
8471.61SkreATF_TC(test);								\
8481.61SkreATF_TC_HEAD(test, tc)							\
8491.61Skre{									\
8501.61Skre	atf_tc_set_md_var(tc, "descr",					\
8511.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
8521.61Skre	    "vfork(2)ed child");					\
8531.61Skre}									\
8541.61Skre									\
8551.61SkreATF_TC_BODY(test, tc)							\
8561.61Skre{									\
8571.61Skre									\
8581.61Skre	traceme_vfork_raise(sig);					\
8591.40Skamil}
8601.40Skamil
8611.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
8621.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
8631.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
8641.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
8651.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
8661.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
8671.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
8681.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
8691.40Skamil
8701.40Skamil/// ----------------------------------------------------------------------------
8711.40Skamil
8721.52Skamilstatic void
8731.52Skamiltraceme_vfork_crash(int sig)
8741.41Skamil{
8751.41Skamil	pid_t child, wpid;
8761.41Skamil#if defined(TWAIT_HAVE_STATUS)
8771.41Skamil	int status;
8781.41Skamil#endif
8791.41Skamil
8801.71Skamil#ifndef PTRACE_ILLEGAL_ASM
8811.71Skamil	if (sig == SIGILL)
8821.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
8831.71Skamil#endif
8841.71Skamil
8851.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8861.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
8871.41Skamil	if (child == 0) {
8881.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8891.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8901.41Skamil
8911.52Skamil		DPRINTF("Before executing a trap\n");
8921.52Skamil		switch (sig) {
8931.52Skamil		case SIGTRAP:
8941.52Skamil			trigger_trap();
8951.52Skamil			break;
8961.52Skamil		case SIGSEGV:
8971.52Skamil			trigger_segv();
8981.52Skamil			break;
8991.52Skamil		case SIGILL:
9001.52Skamil			trigger_ill();
9011.52Skamil			break;
9021.52Skamil		case SIGFPE:
9031.52Skamil			trigger_fpe();
9041.52Skamil			break;
9051.52Skamil		case SIGBUS:
9061.52Skamil			trigger_bus();
9071.52Skamil			break;
9081.52Skamil		default:
9091.52Skamil			/* NOTREACHED */
9101.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
9111.52Skamil		}
9121.41Skamil
9131.41Skamil		/* NOTREACHED */
9141.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
9151.41Skamil	}
9161.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9171.41Skamil
9181.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9191.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9201.41Skamil
9211.52Skamil	validate_status_signaled(status, sig, 1);
9221.41Skamil
9231.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9241.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9251.41Skamil}
9261.41Skamil
9271.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
9281.61SkreATF_TC(test);								\
9291.61SkreATF_TC_HEAD(test, tc)							\
9301.61Skre{									\
9311.61Skre	atf_tc_set_md_var(tc, "descr",					\
9321.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
9331.61Skre	    "vfork(2)ed child");					\
9341.61Skre}									\
9351.61Skre									\
9361.61SkreATF_TC_BODY(test, tc)							\
9371.61Skre{									\
9381.61Skre									\
9391.61Skre	traceme_vfork_crash(sig);					\
9401.52Skamil}
9411.52Skamil
9421.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
9431.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
9441.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
9451.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
9461.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
9471.52Skamil
9481.41Skamil/// ----------------------------------------------------------------------------
9491.41Skamil
9501.43SkamilATF_TC(traceme_vfork_exec);
9511.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
9521.43Skamil{
9531.43Skamil	atf_tc_set_md_var(tc, "descr",
9541.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
9551.43Skamil}
9561.43Skamil
9571.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
9581.43Skamil{
9591.43Skamil	const int sigval = SIGTRAP;
9601.43Skamil	pid_t child, wpid;
9611.43Skamil#if defined(TWAIT_HAVE_STATUS)
9621.43Skamil	int status;
9631.43Skamil#endif
9641.61Skre	struct ptrace_siginfo info;
9651.43Skamil
9661.43Skamil	memset(&info, 0, sizeof(info));
9671.43Skamil
9681.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9691.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
9701.43Skamil	if (child == 0) {
9711.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9721.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9731.43Skamil
9741.43Skamil		DPRINTF("Before calling execve(2) from child\n");
9751.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
9761.43Skamil
9771.43Skamil		/* NOTREACHED */
9781.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
9791.43Skamil	}
9801.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9811.43Skamil
9821.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9831.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9841.43Skamil
9851.43Skamil	validate_status_stopped(status, sigval);
9861.43Skamil
9871.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9881.61Skre	SYSCALL_REQUIRE(
9891.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9901.43Skamil
9911.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9921.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9931.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9941.43Skamil	    info.psi_siginfo.si_errno);
9951.43Skamil
9961.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9971.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
9981.43Skamil
9991.43Skamil	DPRINTF("Before resuming the child process where it left off and "
10001.43Skamil	    "without signal to be sent\n");
10011.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
10021.43Skamil
10031.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10041.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10051.43Skamil
10061.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10071.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10081.43Skamil}
10091.43Skamil
10101.43Skamil/// ----------------------------------------------------------------------------
10111.43Skamil
10121.1Skamil#if defined(TWAIT_HAVE_PID)
10131.51Skamilstatic void
10141.59Skamilunrelated_tracer_sees_crash(int sig)
10151.59Skamil{
10161.59Skamil	struct msg_fds parent_tracee, parent_tracer;
10171.59Skamil	const int exitval = 10;
10181.59Skamil	pid_t tracee, tracer, wpid;
10191.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10201.59Skamil#if defined(TWAIT_HAVE_STATUS)
10211.59Skamil	int status;
10221.59Skamil#endif
10231.59Skamil	struct ptrace_siginfo info;
10241.61Skre
10251.71Skamil#ifndef PTRACE_ILLEGAL_ASM
10261.71Skamil	if (sig == SIGILL)
10271.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
10281.71Skamil#endif
10291.71Skamil
10301.59Skamil	memset(&info, 0, sizeof(info));
10311.59Skamil
10321.59Skamil	DPRINTF("Spawn tracee\n");
10331.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10341.59Skamil	tracee = atf_utils_fork();
10351.59Skamil	if (tracee == 0) {
10361.59Skamil		// Wait for parent to let us crash
10371.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
10381.61Skre
10391.59Skamil		DPRINTF("Before executing a trap\n");
10401.59Skamil		switch (sig) {
10411.59Skamil		case SIGTRAP:
10421.59Skamil			trigger_trap();
10431.59Skamil			break;
10441.59Skamil		case SIGSEGV:
10451.59Skamil			trigger_segv();
10461.59Skamil			break;
10471.59Skamil		case SIGILL:
10481.59Skamil			trigger_ill();
10491.59Skamil			break;
10501.59Skamil		case SIGFPE:
10511.59Skamil			trigger_fpe();
10521.59Skamil			break;
10531.59Skamil		case SIGBUS:
10541.59Skamil			trigger_bus();
10551.59Skamil			break;
10561.59Skamil		default:
10571.59Skamil			/* NOTREACHED */
10581.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
10591.59Skamil		}
10601.59Skamil
10611.59Skamil		/* NOTREACHED */
10621.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
10631.59Skamil	}
10641.59Skamil
10651.59Skamil	DPRINTF("Spawn debugger\n");
10661.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
10671.59Skamil	tracer = atf_utils_fork();
10681.59Skamil	if (tracer == 0) {
10691.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
10701.59Skamil		tracer = atf_utils_fork();
10711.59Skamil		if (tracer != 0)
10721.61Skre			_exit(exitval);
10731.59Skamil
10741.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10751.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10761.59Skamil
10771.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10781.59Skamil		FORKEE_REQUIRE_SUCCESS(
10791.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10801.59Skamil
10811.59Skamil		forkee_status_stopped(status, SIGSTOP);
10821.59Skamil
10831.59Skamil		/* Resume tracee with PT_CONTINUE */
10841.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10851.59Skamil
10861.59Skamil		/* Inform parent that tracer has attached to tracee */
10871.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
10881.59Skamil
10891.59Skamil		/* Wait for parent to tell use that tracee should have exited */
10901.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
10911.59Skamil
10921.59Skamil		/* Wait for tracee and assert that it exited */
10931.59Skamil		FORKEE_REQUIRE_SUCCESS(
10941.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10951.59Skamil
10961.59Skamil		validate_status_stopped(status, sig);
10971.59Skamil
10981.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
10991.61Skre		    "traced process\n");
11001.61Skre		SYSCALL_REQUIRE(
11011.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
11021.59Skamil
11031.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11041.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
11051.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
11061.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
11071.59Skamil
11081.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
11091.59Skamil		switch (sig) {
11101.59Skamil		case SIGTRAP:
11111.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
11121.59Skamil			break;
11131.59Skamil		case SIGSEGV:
11141.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
11151.59Skamil			break;
11161.71Skamil		case SIGILL:
11171.71Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
11181.71Skamil			break;
11191.59Skamil		case SIGFPE:
11201.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
11211.59Skamil			break;
11221.59Skamil		case SIGBUS:
11231.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
11241.59Skamil			break;
11251.59Skamil		}
11261.59Skamil
11271.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
11281.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
11291.61Skre		TWAIT_REQUIRE_SUCCESS(
11301.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11311.59Skamil
11321.59Skamil		validate_status_signaled(status, SIGKILL, 0);
11331.59Skamil
11341.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
11351.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
11361.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
11371.59Skamil
11381.71Skamil		/* Inform parent that tracer is exiting normally */
11391.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
11401.71Skamil
11411.59Skamil		DPRINTF("Before exiting of the tracer process\n");
11421.59Skamil		_exit(0 /* collect by initproc */);
11431.59Skamil	}
11441.59Skamil
11451.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
11461.59Skamil	    "calling %s()\n", TWAIT_FNAME);
11471.59Skamil	TWAIT_REQUIRE_SUCCESS(
11481.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
11491.59Skamil
11501.59Skamil	validate_status_exited(status, exitval);
11511.59Skamil
11521.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
11531.59Skamil	    TWAIT_FNAME);
11541.59Skamil	TWAIT_REQUIRE_SUCCESS(
11551.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
11561.59Skamil
11571.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
11581.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
11591.59Skamil
11601.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
11611.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
11621.59Skamil
11631.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
11641.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11651.59Skamil
11661.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11671.59Skamil	    TWAIT_FNAME);
11681.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11691.59Skamil
11701.59Skamil	validate_status_signaled(status, SIGKILL, 0);
11711.59Skamil
11721.71Skamil	DPRINTF("Await normal exit of tracer\n");
11731.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
11741.71Skamil
11751.59Skamil	msg_close(&parent_tracer);
11761.59Skamil	msg_close(&parent_tracee);
11771.59Skamil}
11781.59Skamil
11791.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
11801.61SkreATF_TC(test);								\
11811.61SkreATF_TC_HEAD(test, tc)							\
11821.61Skre{									\
11831.61Skre	atf_tc_set_md_var(tc, "descr",					\
11841.61Skre	    "Assert that an unrelated tracer sees crash signal from the " \
11851.61Skre	    "debuggee");						\
11861.61Skre}									\
11871.61Skre									\
11881.61SkreATF_TC_BODY(test, tc)							\
11891.61Skre{									\
11901.61Skre									\
11911.61Skre	unrelated_tracer_sees_crash(sig);				\
11921.59Skamil}
11931.59Skamil
11941.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
11951.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
11961.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
11971.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
11981.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
11991.59Skamil#endif
12001.59Skamil
12011.59Skamil/// ----------------------------------------------------------------------------
12021.59Skamil
12031.59Skamil#if defined(TWAIT_HAVE_PID)
12041.59Skamilstatic void
12051.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
12061.67Skamil                                             bool stopped)
12071.1Skamil{
12081.51Skamil	/*
12091.51Skamil	 * notimeout - disable timeout in await zombie function
12101.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
12111.67Skamil	 * stopped - attach to a stopped process
12121.51Skamil	 */
12131.1Skamil
12141.1Skamil	struct msg_fds parent_tracee, parent_tracer;
12151.1Skamil	const int exitval_tracee = 5;
12161.1Skamil	const int exitval_tracer = 10;
12171.1Skamil	pid_t tracee, tracer, wpid;
12181.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
12191.1Skamil#if defined(TWAIT_HAVE_STATUS)
12201.1Skamil	int status;
12211.1Skamil#endif
12221.1Skamil
12231.67Skamil	/*
12241.67Skamil	 * Only a subset of options are supported.
12251.67Skamil	 */
12261.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
12271.67Skamil	            (!notimeout && unrelated && !stopped) ||
12281.67Skamil	            (notimeout && !unrelated && !stopped) ||
12291.67Skamil	            (!notimeout && unrelated && stopped));
12301.67Skamil
12311.13Schristos	DPRINTF("Spawn tracee\n");
12321.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
12331.1Skamil	tracee = atf_utils_fork();
12341.1Skamil	if (tracee == 0) {
12351.67Skamil		if (stopped) {
12361.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
12371.67Skamil			raise(SIGSTOP);
12381.67Skamil		}
12391.67Skamil
12401.1Skamil		// Wait for parent to let us exit
12411.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
12421.1Skamil		_exit(exitval_tracee);
12431.1Skamil	}
12441.1Skamil
12451.13Schristos	DPRINTF("Spawn debugger\n");
12461.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
12471.1Skamil	tracer = atf_utils_fork();
12481.1Skamil	if (tracer == 0) {
12491.51Skamil		if(unrelated) {
12501.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
12511.51Skamil			tracer = atf_utils_fork();
12521.51Skamil			if (tracer != 0)
12531.51Skamil				_exit(exitval_tracer);
12541.51Skamil		}
12551.51Skamil
12561.67Skamil		if (stopped) {
12571.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
12581.67Skamil			await_stopped(tracee);
12591.67Skamil		}
12601.67Skamil
12611.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
12621.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
12631.1Skamil
12641.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
12651.1Skamil		FORKEE_REQUIRE_SUCCESS(
12661.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12671.1Skamil
12681.1Skamil		forkee_status_stopped(status, SIGSTOP);
12691.1Skamil
12701.1Skamil		/* Resume tracee with PT_CONTINUE */
12711.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
12721.1Skamil
12731.1Skamil		/* Inform parent that tracer has attached to tracee */
12741.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
12751.1Skamil
12761.1Skamil		/* Wait for parent to tell use that tracee should have exited */
12771.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12781.1Skamil
12791.1Skamil		/* Wait for tracee and assert that it exited */
12801.1Skamil		FORKEE_REQUIRE_SUCCESS(
12811.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12821.1Skamil
12831.1Skamil		forkee_status_exited(status, exitval_tracee);
12841.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
12851.1Skamil
12861.13Schristos		DPRINTF("Before exiting of the tracer process\n");
12871.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
12881.51Skamil	}
12891.51Skamil
12901.51Skamil	if (unrelated) {
12911.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
12921.51Skamil		    "calling %s()\n", TWAIT_FNAME);
12931.51Skamil		TWAIT_REQUIRE_SUCCESS(
12941.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
12951.51Skamil
12961.51Skamil		validate_status_exited(status, exitval_tracer);
12971.51Skamil
12981.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
12991.51Skamil		    TWAIT_FNAME);
13001.51Skamil		TWAIT_REQUIRE_SUCCESS(
13011.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
13021.1Skamil	}
13031.1Skamil
13041.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
13051.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
13061.1Skamil
13071.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
13081.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
13091.1Skamil
13101.13Schristos	DPRINTF("Detect that tracee is zombie\n");
13111.51Skamil	if (notimeout)
13121.26Skamil		await_zombie_raw(tracee, 0);
13131.26Skamil	else
13141.26Skamil		await_zombie(tracee);
13151.1Skamil
13161.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
13171.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
13181.1Skamil	    TWAIT_FNAME);
13191.1Skamil	TWAIT_REQUIRE_SUCCESS(
13201.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
13211.1Skamil
13221.51Skamil	if (unrelated) {
13231.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
13241.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
13251.51Skamil	} else {
13261.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
13271.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
13281.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
13291.59Skamil			"%s()\n", TWAIT_FNAME);
13301.51Skamil
13311.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
13321.59Skamil			"tracee\n");
13331.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
13341.51Skamil		    tracer);
13351.1Skamil
13361.51Skamil		validate_status_exited(status, exitval_tracer);
13371.51Skamil	}
13381.1Skamil
13391.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
13401.1Skamil	    TWAIT_FNAME);
13411.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13421.1Skamil
13431.1Skamil	validate_status_exited(status, exitval_tracee);
13441.1Skamil
13451.1Skamil	msg_close(&parent_tracer);
13461.1Skamil	msg_close(&parent_tracee);
13471.1Skamil}
13481.26Skamil
13491.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
13501.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
13511.51Skamil{
13521.51Skamil	atf_tc_set_md_var(tc, "descr",
13531.51Skamil	    "Assert that tracer sees process termination before the parent");
13541.51Skamil}
13551.51Skamil
13561.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
13571.26Skamil{
13581.26Skamil
13591.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
13601.26Skamil}
13611.26Skamil
13621.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
13631.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
13641.1Skamil{
13651.1Skamil	atf_tc_set_md_var(tc, "descr",
13661.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
13671.51Skamil	    "process and no other error is reported");
13681.1Skamil}
13691.1Skamil
13701.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
13711.1Skamil{
13721.51Skamil	time_t start, end;
13731.51Skamil	double diff;
13741.51Skamil	unsigned long N = 0;
13751.1Skamil
13761.51Skamil	/*
13771.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
13781.51Skamil	 * This test body isn't specific to this race, however it's just good
13791.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
13801.51Skamil	 */
13811.1Skamil
13821.51Skamil	start = time(NULL);
13831.51Skamil	while (true) {
13841.51Skamil		DPRINTF("Step: %lu\n", N);
13851.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
13861.67Skamil		                                             false);
13871.51Skamil		end = time(NULL);
13881.51Skamil		diff = difftime(end, start);
13891.51Skamil		if (diff >= 5.0)
13901.51Skamil			break;
13911.51Skamil		++N;
13921.1Skamil	}
13931.51Skamil	DPRINTF("Iterations: %lu\n", N);
13941.51Skamil}
13951.1Skamil
13961.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
13971.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
13981.51Skamil{
13991.51Skamil	atf_tc_set_md_var(tc, "descr",
14001.51Skamil	    "Assert that tracer sees process termination before the parent");
14011.51Skamil}
14021.1Skamil
14031.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
14041.51Skamil{
14051.1Skamil
14061.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
14071.67Skamil}
14081.67Skamil
14091.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
14101.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
14111.67Skamil{
14121.67Skamil	atf_tc_set_md_var(tc, "descr",
14131.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
14141.67Skamil}
14151.67Skamil
14161.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
14171.67Skamil{
14181.67Skamil
14191.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
14201.1Skamil}
14211.1Skamil#endif
14221.1Skamil
14231.51Skamil/// ----------------------------------------------------------------------------
14241.51Skamil
14251.66Skamilstatic void
14261.66Skamilparent_attach_to_its_child(bool stopped)
14271.1Skamil{
14281.1Skamil	struct msg_fds parent_tracee;
14291.1Skamil	const int exitval_tracee = 5;
14301.1Skamil	pid_t tracee, wpid;
14311.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
14321.1Skamil#if defined(TWAIT_HAVE_STATUS)
14331.1Skamil	int status;
14341.1Skamil#endif
14351.1Skamil
14361.13Schristos	DPRINTF("Spawn tracee\n");
14371.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
14381.1Skamil	tracee = atf_utils_fork();
14391.1Skamil	if (tracee == 0) {
14401.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
14411.13Schristos		DPRINTF("Parent should now attach to tracee\n");
14421.1Skamil
14431.66Skamil		if (stopped) {
14441.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
14451.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
14461.66Skamil		}
14471.66Skamil
14481.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
14491.1Skamil		/* Wait for message from the parent */
14501.1Skamil		_exit(exitval_tracee);
14511.1Skamil	}
14521.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
14531.57Skamil
14541.66Skamil	if (stopped) {
14551.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
14561.66Skamil		await_stopped(tracee);
14571.66Skamil	}
14581.66Skamil
14591.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
14601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
14611.1Skamil
14621.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
14631.1Skamil	    TWAIT_FNAME);
14641.1Skamil	TWAIT_REQUIRE_SUCCESS(
14651.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14661.1Skamil
14671.1Skamil	validate_status_stopped(status, SIGSTOP);
14681.1Skamil
14691.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
14701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
14711.1Skamil
14721.13Schristos	DPRINTF("Let the tracee exit now\n");
14731.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
14741.1Skamil
14751.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
14761.1Skamil	TWAIT_REQUIRE_SUCCESS(
14771.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14781.1Skamil
14791.1Skamil	validate_status_exited(status, exitval_tracee);
14801.1Skamil
14811.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
14821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
14831.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
14841.1Skamil
14851.1Skamil	msg_close(&parent_tracee);
14861.1Skamil}
14871.1Skamil
14881.66SkamilATF_TC(parent_attach_to_its_child);
14891.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
14901.66Skamil{
14911.66Skamil	atf_tc_set_md_var(tc, "descr",
14921.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
14931.66Skamil}
14941.66Skamil
14951.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
14961.66Skamil{
14971.66Skamil
14981.66Skamil	parent_attach_to_its_child(false);
14991.66Skamil}
15001.66Skamil
15011.66SkamilATF_TC(parent_attach_to_its_stopped_child);
15021.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
15031.66Skamil{
15041.66Skamil	atf_tc_set_md_var(tc, "descr",
15051.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
15061.66Skamil}
15071.66Skamil
15081.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
15091.66Skamil{
15101.66Skamil
15111.66Skamil	parent_attach_to_its_child(true);
15121.66Skamil}
15131.66Skamil
15141.51Skamil/// ----------------------------------------------------------------------------
15151.51Skamil
15161.65Skamilstatic void
15171.65Skamilchild_attach_to_its_parent(bool stopped)
15181.1Skamil{
15191.1Skamil	struct msg_fds parent_tracee;
15201.1Skamil	const int exitval_tracer = 5;
15211.1Skamil	pid_t tracer, wpid;
15221.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15231.1Skamil#if defined(TWAIT_HAVE_STATUS)
15241.1Skamil	int status;
15251.1Skamil#endif
15261.1Skamil
15271.13Schristos	DPRINTF("Spawn tracer\n");
15281.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15291.1Skamil	tracer = atf_utils_fork();
15301.1Skamil	if (tracer == 0) {
15311.1Skamil		/* Wait for message from the parent */
15321.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
15331.1Skamil
15341.65Skamil		if (stopped) {
15351.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
15361.65Skamil			        getppid());
15371.65Skamil			await_stopped(getppid());
15381.65Skamil		}
15391.65Skamil
15401.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
15411.1Skamil		    getppid());
15421.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
15431.1Skamil
15441.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
15451.1Skamil		    TWAIT_FNAME);
15461.1Skamil		FORKEE_REQUIRE_SUCCESS(
15471.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
15481.1Skamil
15491.1Skamil		forkee_status_stopped(status, SIGSTOP);
15501.1Skamil
15511.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
15521.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
15531.1Skamil		    != -1);
15541.1Skamil
15551.1Skamil		/* Tell parent we are ready */
15561.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
15571.1Skamil
15581.1Skamil		_exit(exitval_tracer);
15591.1Skamil	}
15601.1Skamil
15611.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
15621.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
15631.65Skamil
15641.65Skamil	if (stopped) {
15651.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
15661.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
15671.65Skamil	}
15681.65Skamil
15691.13Schristos	DPRINTF("Allow the tracer to exit now\n");
15701.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
15711.1Skamil
15721.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
15731.1Skamil	TWAIT_REQUIRE_SUCCESS(
15741.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
15751.1Skamil
15761.1Skamil	validate_status_exited(status, exitval_tracer);
15771.1Skamil
15781.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
15791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
15801.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
15811.1Skamil
15821.1Skamil	msg_close(&parent_tracee);
15831.1Skamil}
15841.1Skamil
15851.65SkamilATF_TC(child_attach_to_its_parent);
15861.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
15871.65Skamil{
15881.65Skamil	atf_tc_set_md_var(tc, "descr",
15891.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
15901.65Skamil}
15911.65Skamil
15921.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
15931.65Skamil{
15941.65Skamil
15951.65Skamil	child_attach_to_its_parent(false);
15961.65Skamil}
15971.65Skamil
15981.65SkamilATF_TC(child_attach_to_its_stopped_parent);
15991.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
16001.65Skamil{
16011.65Skamil	atf_tc_set_md_var(tc, "descr",
16021.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
16031.65Skamil}
16041.65Skamil
16051.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
16061.65Skamil{
16071.65Skamil	/*
16081.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
16091.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
16101.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
16111.65Skamil	 *
16121.65Skamil	 * As a workaround spawn this test as a subprocess.
16131.65Skamil	 */
16141.65Skamil
16151.65Skamil	const int exitval = 15;
16161.65Skamil	pid_t child, wpid;
16171.65Skamil#if defined(TWAIT_HAVE_STATUS)
16181.65Skamil	int status;
16191.65Skamil#endif
16201.65Skamil
16211.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
16221.65Skamil	if (child == 0) {
16231.65Skamil		child_attach_to_its_parent(true);
16241.65Skamil		_exit(exitval);
16251.65Skamil	} else {
16261.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16271.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16281.65Skamil
16291.65Skamil		validate_status_exited(status, exitval);
16301.65Skamil
16311.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
16321.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16331.65Skamil	}
16341.65Skamil}
16351.65Skamil
16361.51Skamil/// ----------------------------------------------------------------------------
16371.51Skamil
16381.1Skamil#if defined(TWAIT_HAVE_PID)
16391.1Skamil
16401.51Skamilenum tracee_sees_its_original_parent_type {
16411.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
16421.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
16431.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
16441.51Skamil};
16451.51Skamil
16461.51Skamilstatic void
16471.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
16481.1Skamil{
16491.1Skamil	struct msg_fds parent_tracer, parent_tracee;
16501.1Skamil	const int exitval_tracee = 5;
16511.1Skamil	const int exitval_tracer = 10;
16521.1Skamil	pid_t parent, tracee, tracer, wpid;
16531.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
16541.1Skamil#if defined(TWAIT_HAVE_STATUS)
16551.1Skamil	int status;
16561.1Skamil#endif
16571.51Skamil	/* sysctl(3) - kinfo_proc2 */
16581.51Skamil	int name[CTL_MAXNAME];
16591.51Skamil	struct kinfo_proc2 kp;
16601.51Skamil	size_t len = sizeof(kp);
16611.51Skamil	unsigned int namelen;
16621.51Skamil
16631.51Skamil	/* procfs - status  */
16641.51Skamil	FILE *fp;
16651.51Skamil	struct stat st;
16661.51Skamil	const char *fname = "/proc/curproc/status";
16671.51Skamil	char s_executable[MAXPATHLEN];
16681.51Skamil	int s_pid, s_ppid;
16691.51Skamil	int rv;
16701.51Skamil
16711.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
16721.61Skre		SYSCALL_REQUIRE(
16731.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
16741.61Skre		if (rv != 0)
16751.51Skamil			atf_tc_skip("/proc/curproc/status not found");
16761.51Skamil	}
16771.1Skamil
16781.13Schristos	DPRINTF("Spawn tracee\n");
16791.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
16801.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
16811.1Skamil	tracee = atf_utils_fork();
16821.1Skamil	if (tracee == 0) {
16831.1Skamil		parent = getppid();
16841.1Skamil
16851.1Skamil		/* Emit message to the parent */
16861.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
16871.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
16881.1Skamil
16891.51Skamil		switch (type) {
16901.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
16911.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
16921.51Skamil			break;
16931.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
16941.51Skamil			namelen = 0;
16951.51Skamil			name[namelen++] = CTL_KERN;
16961.51Skamil			name[namelen++] = KERN_PROC2;
16971.51Skamil			name[namelen++] = KERN_PROC_PID;
16981.51Skamil			name[namelen++] = getpid();
16991.51Skamil			name[namelen++] = len;
17001.51Skamil			name[namelen++] = 1;
17011.51Skamil
17021.61Skre			FORKEE_ASSERT_EQ(
17031.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
17041.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
17051.51Skamil			break;
17061.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
17071.51Skamil			/*
17081.51Skamil			 * Format:
17091.51Skamil			 *  EXECUTABLE PID PPID ...
17101.51Skamil			 */
17111.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
17121.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
17131.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
17141.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
17151.51Skamil			break;
17161.51Skamil		}
17171.1Skamil
17181.1Skamil		_exit(exitval_tracee);
17191.1Skamil	}
17201.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
17211.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
17221.1Skamil
17231.13Schristos	DPRINTF("Spawn debugger\n");
17241.1Skamil	tracer = atf_utils_fork();
17251.1Skamil	if (tracer == 0) {
17261.1Skamil		/* No IPC to communicate with the child */
17271.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
17281.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
17291.1Skamil
17301.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
17311.1Skamil		FORKEE_REQUIRE_SUCCESS(
17321.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17331.1Skamil
17341.1Skamil		forkee_status_stopped(status, SIGSTOP);
17351.1Skamil
17361.1Skamil		/* Resume tracee with PT_CONTINUE */
17371.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
17381.1Skamil
17391.1Skamil		/* Inform parent that tracer has attached to tracee */
17401.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
17411.1Skamil
17421.1Skamil		/* Wait for parent to tell use that tracee should have exited */
17431.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
17441.1Skamil
17451.1Skamil		/* Wait for tracee and assert that it exited */
17461.1Skamil		FORKEE_REQUIRE_SUCCESS(
17471.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17481.1Skamil
17491.1Skamil		forkee_status_exited(status, exitval_tracee);
17501.1Skamil
17511.13Schristos		DPRINTF("Before exiting of the tracer process\n");
17521.1Skamil		_exit(exitval_tracer);
17531.1Skamil	}
17541.1Skamil
17551.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
17561.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
17571.1Skamil
17581.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
17591.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
17601.1Skamil
17611.13Schristos	DPRINTF("Detect that tracee is zombie\n");
17621.1Skamil	await_zombie(tracee);
17631.1Skamil
17641.13Schristos	DPRINTF("Assert that there is no status about tracee - "
17651.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
17661.1Skamil	TWAIT_REQUIRE_SUCCESS(
17671.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
17681.1Skamil
17691.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
17701.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
17711.1Skamil
17721.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
17731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
17741.1Skamil	    tracer);
17751.1Skamil
17761.1Skamil	validate_status_exited(status, exitval_tracer);
17771.1Skamil
17781.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
17791.1Skamil	    TWAIT_FNAME);
17801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
17811.1Skamil	    tracee);
17821.1Skamil
17831.1Skamil	validate_status_exited(status, exitval_tracee);
17841.1Skamil
17851.1Skamil	msg_close(&parent_tracer);
17861.1Skamil	msg_close(&parent_tracee);
17871.1Skamil}
17881.1Skamil
17891.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
17901.61SkreATF_TC(test);								\
17911.61SkreATF_TC_HEAD(test, tc)							\
17921.61Skre{									\
17931.61Skre	atf_tc_set_md_var(tc, "descr",					\
17941.61Skre	    "Assert that tracee sees its original parent when being traced " \
17951.61Skre	    "(check " descr ")");					\
17961.61Skre}									\
17971.61Skre									\
17981.61SkreATF_TC_BODY(test, tc)							\
17991.61Skre{									\
18001.61Skre									\
18011.61Skre	tracee_sees_its_original_parent(type);				\
18021.1Skamil}
18031.1Skamil
18041.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18051.51Skamil	tracee_sees_its_original_parent_getppid,
18061.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
18071.51Skamil	"getppid(2)");
18081.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18091.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
18101.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
18111.51Skamil	"sysctl(3) and kinfo_proc2");
18121.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18131.51Skamil	tracee_sees_its_original_parent_procfs_status,
18141.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
18151.51Skamil	"the status file in procfs");
18161.1Skamil#endif
18171.1Skamil
18181.51Skamil/// ----------------------------------------------------------------------------
18191.1Skamil
18201.53Skamilstatic void
18211.53Skamileventmask_preserved(int event)
18221.1Skamil{
18231.1Skamil	const int exitval = 5;
18241.1Skamil	const int sigval = SIGSTOP;
18251.1Skamil	pid_t child, wpid;
18261.1Skamil#if defined(TWAIT_HAVE_STATUS)
18271.1Skamil	int status;
18281.1Skamil#endif
18291.1Skamil	ptrace_event_t set_event, get_event;
18301.1Skamil	const int len = sizeof(ptrace_event_t);
18311.1Skamil
18321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18341.1Skamil	if (child == 0) {
18351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18371.1Skamil
18381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18401.1Skamil
18411.13Schristos		DPRINTF("Before exiting of the child process\n");
18421.1Skamil		_exit(exitval);
18431.1Skamil	}
18441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18451.1Skamil
18461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18481.1Skamil
18491.1Skamil	validate_status_stopped(status, sigval);
18501.1Skamil
18511.53Skamil	set_event.pe_set_event = event;
18521.61Skre	SYSCALL_REQUIRE(
18531.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
18541.61Skre	SYSCALL_REQUIRE(
18551.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
18561.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
18571.1Skamil
18581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18591.1Skamil	    "without signal to be sent\n");
18601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18611.1Skamil
18621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18641.1Skamil
18651.1Skamil	validate_status_exited(status, exitval);
18661.1Skamil
18671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18691.1Skamil}
18701.1Skamil
18711.61Skre#define EVENTMASK_PRESERVED(test, event)				\
18721.61SkreATF_TC(test);								\
18731.61SkreATF_TC_HEAD(test, tc)							\
18741.61Skre{									\
18751.61Skre	atf_tc_set_md_var(tc, "descr",					\
18761.61Skre	    "Verify that eventmask " #event " is preserved");		\
18771.61Skre}									\
18781.61Skre									\
18791.61SkreATF_TC_BODY(test, tc)							\
18801.61Skre{									\
18811.61Skre									\
18821.61Skre	eventmask_preserved(event);					\
18831.1Skamil}
18841.1Skamil
18851.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
18861.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
18871.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
18881.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
18891.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
18901.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
18911.1Skamil
18921.53Skamil/// ----------------------------------------------------------------------------
18931.1Skamil
18941.28Skamilstatic void
18951.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
18961.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
18971.1Skamil{
18981.1Skamil	const int exitval = 5;
18991.1Skamil	const int exitval2 = 15;
19001.1Skamil	const int sigval = SIGSTOP;
19011.31Skamil	pid_t child, child2 = 0, wpid;
19021.1Skamil#if defined(TWAIT_HAVE_STATUS)
19031.1Skamil	int status;
19041.1Skamil#endif
19051.1Skamil	ptrace_state_t state;
19061.1Skamil	const int slen = sizeof(state);
19071.1Skamil	ptrace_event_t event;
19081.1Skamil	const int elen = sizeof(event);
19091.1Skamil
19101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19121.1Skamil	if (child == 0) {
19131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19151.1Skamil
19161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19181.1Skamil
19191.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
19201.1Skamil
19211.1Skamil		if (child2 == 0)
19221.1Skamil			_exit(exitval2);
19231.1Skamil
19241.1Skamil		FORKEE_REQUIRE_SUCCESS
19251.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
19261.1Skamil
19271.1Skamil		forkee_status_exited(status, exitval2);
19281.1Skamil
19291.13Schristos		DPRINTF("Before exiting of the child process\n");
19301.1Skamil		_exit(exitval);
19311.1Skamil	}
19321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19331.1Skamil
19341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19361.1Skamil
19371.1Skamil	validate_status_stopped(status, sigval);
19381.1Skamil
19391.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
19401.61Skre	    trackfork ? "|PTRACE_FORK" : "",
19411.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
19421.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
19431.30Skamil	event.pe_set_event = 0;
19441.30Skamil	if (trackfork)
19451.30Skamil		event.pe_set_event |= PTRACE_FORK;
19461.30Skamil	if (trackvfork)
19471.30Skamil		event.pe_set_event |= PTRACE_VFORK;
19481.30Skamil	if (trackvforkdone)
19491.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
19501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
19511.1Skamil
19521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19531.1Skamil	    "without signal to be sent\n");
19541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19551.1Skamil
19561.29Skamil#if defined(TWAIT_HAVE_PID)
19571.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
19581.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
19591.61Skre		    child);
19601.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
19611.61Skre		    child);
19621.1Skamil
19631.29Skamil		validate_status_stopped(status, SIGTRAP);
19641.1Skamil
19651.61Skre		SYSCALL_REQUIRE(
19661.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
19671.31Skamil		if (trackfork && fn == fork) {
19681.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
19691.30Skamil			       PTRACE_FORK);
19701.30Skamil		}
19711.31Skamil		if (trackvfork && fn == vfork) {
19721.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
19731.30Skamil			       PTRACE_VFORK);
19741.30Skamil		}
19751.29Skamil
19761.29Skamil		child2 = state.pe_other_pid;
19771.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
19781.29Skamil
19791.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
19801.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
19811.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
19821.29Skamil		    child2);
19831.1Skamil
19841.29Skamil		validate_status_stopped(status, SIGTRAP);
19851.1Skamil
19861.61Skre		SYSCALL_REQUIRE(
19871.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
19881.31Skamil		if (trackfork && fn == fork) {
19891.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
19901.30Skamil			       PTRACE_FORK);
19911.30Skamil		}
19921.31Skamil		if (trackvfork && fn == vfork) {
19931.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
19941.30Skamil			       PTRACE_VFORK);
19951.30Skamil		}
19961.30Skamil
19971.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
19981.29Skamil
19991.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
20001.29Skamil		    "and without signal to be sent\n");
20011.61Skre		SYSCALL_REQUIRE(
20021.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
20031.29Skamil
20041.29Skamil		DPRINTF("Before resuming the child process where it left off "
20051.61Skre		    "and without signal to be sent\n");
20061.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20071.30Skamil	}
20081.30Skamil#endif
20091.30Skamil
20101.31Skamil	if (trackvforkdone && fn == vfork) {
20111.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
20121.61Skre		    child);
20131.61Skre		TWAIT_REQUIRE_SUCCESS(
20141.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
20151.30Skamil
20161.30Skamil		validate_status_stopped(status, SIGTRAP);
20171.30Skamil
20181.61Skre		SYSCALL_REQUIRE(
20191.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
20201.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
20211.30Skamil
20221.30Skamil		child2 = state.pe_other_pid;
20231.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
20241.61Skre		    child2);
20251.30Skamil
20261.30Skamil		DPRINTF("Before resuming the child process where it left off "
20271.61Skre		    "and without signal to be sent\n");
20281.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20291.30Skamil	}
20301.29Skamil
20311.30Skamil#if defined(TWAIT_HAVE_PID)
20321.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
20331.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
20341.61Skre		    "\n", TWAIT_FNAME);
20351.61Skre		TWAIT_REQUIRE_SUCCESS(
20361.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
20371.29Skamil
20381.29Skamil		validate_status_exited(status, exitval2);
20391.29Skamil
20401.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
20411.61Skre		    "process\n", TWAIT_FNAME);
20421.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
20431.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
20441.29Skamil	}
20451.29Skamil#endif
20461.1Skamil
20471.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
20481.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
20491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20501.1Skamil
20511.1Skamil	validate_status_stopped(status, SIGCHLD);
20521.1Skamil
20531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20541.1Skamil	    "without signal to be sent\n");
20551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20561.1Skamil
20571.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
20581.1Skamil	    TWAIT_FNAME);
20591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20601.1Skamil
20611.1Skamil	validate_status_exited(status, exitval);
20621.1Skamil
20631.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
20641.1Skamil	    TWAIT_FNAME);
20651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20661.1Skamil}
20671.28Skamil
20681.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
20691.61SkreATF_TC(name);								\
20701.61SkreATF_TC_HEAD(name, tc)							\
20711.61Skre{									\
20721.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
20731.61Skre}									\
20741.61Skre									\
20751.61SkreATF_TC_BODY(name, tc)							\
20761.61Skre{									\
20771.61Skre									\
20781.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
20791.32Skamil}
20801.32Skamil
20811.32Skamil#define F false
20821.32Skamil#define T true
20831.32Skamil
20841.32Skamil#define F_IF__0(x)
20851.32Skamil#define F_IF__1(x) x
20861.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
20871.32Skamil#define F_IF_(x,y) F_IF__(x,y)
20881.32Skamil#define F_IF(x,y) F_IF_(x,y)
20891.32Skamil
20901.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
20911.61Skre	"Verify " #function "(2) called with 0"				\
20921.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
20931.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
20941.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
20951.61Skre	" in EVENT_MASK."						\
20961.61Skre	F_IF(dchildbit," Detach child in this test.")			\
20971.61Skre	F_IF(dparentbit," Detach parent in this test.")
20981.1Skamil
20991.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
21001.31Skamil#if defined(TWAIT_HAVE_PID)
21011.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
21021.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
21031.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
21041.31Skamil#endif
21051.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
21061.31Skamil#if defined(TWAIT_HAVE_PID)
21071.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
21081.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
21091.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
21101.31Skamil#endif
21111.1Skamil
21121.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
21131.31Skamil#if defined(TWAIT_HAVE_PID)
21141.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
21151.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
21161.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
21171.31Skamil#endif
21181.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
21191.31Skamil#if defined(TWAIT_HAVE_PID)
21201.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
21211.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
21221.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
21231.31Skamil#endif
21241.31Skamil
21251.54Skamil/// ----------------------------------------------------------------------------
21261.31Skamil
21271.54Skamilenum bytes_transfer_type {
21281.54Skamil	BYTES_TRANSFER_DATA,
21291.54Skamil	BYTES_TRANSFER_DATAIO,
21301.54Skamil	BYTES_TRANSFER_TEXT,
21311.54Skamil	BYTES_TRANSFER_TEXTIO,
21321.54Skamil	BYTES_TRANSFER_AUXV
21331.54Skamil};
21341.31Skamil
21351.54Skamilstatic int __used
21361.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
21371.54Skamil{
21381.54Skamil	int e, f, g, h;
21391.1Skamil
21401.54Skamil	a *= 4;
21411.54Skamil	b += 3;
21421.54Skamil	c -= 2;
21431.54Skamil	d /= 1;
21441.1Skamil
21451.54Skamil	e = strtol("10", NULL, 10);
21461.54Skamil	f = strtol("20", NULL, 10);
21471.54Skamil	g = strtol("30", NULL, 10);
21481.54Skamil	h = strtol("40", NULL, 10);
21491.1Skamil
21501.54Skamil	return (a + b * c - d) + (e * f - g / h);
21511.1Skamil}
21521.1Skamil
21531.54Skamilstatic void
21541.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
21551.1Skamil{
21561.1Skamil	const int exitval = 5;
21571.1Skamil	const int sigval = SIGSTOP;
21581.1Skamil	pid_t child, wpid;
21591.54Skamil	bool skip = false;
21601.1Skamil
21611.54Skamil	int lookup_me = 0;
21621.54Skamil	uint8_t lookup_me8 = 0;
21631.54Skamil	uint16_t lookup_me16 = 0;
21641.54Skamil	uint32_t lookup_me32 = 0;
21651.54Skamil	uint64_t lookup_me64 = 0;
21661.1Skamil
21671.54Skamil	int magic = 0x13579246;
21681.54Skamil	uint8_t magic8 = 0xab;
21691.54Skamil	uint16_t magic16 = 0x1234;
21701.54Skamil	uint32_t magic32 = 0x98765432;
21711.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
21721.1Skamil
21731.54Skamil	struct ptrace_io_desc io;
21741.1Skamil#if defined(TWAIT_HAVE_STATUS)
21751.1Skamil	int status;
21761.1Skamil#endif
21771.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
21781.60Skre	AuxInfo ai[513], *aip;
21791.55Schristos
21801.55Schristos	ATF_REQUIRE(size < sizeof(ai));
21811.1Skamil
21821.54Skamil	/* Prepare variables for .TEXT transfers */
21831.54Skamil	switch (type) {
21841.54Skamil	case BYTES_TRANSFER_TEXT:
21851.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
21861.54Skamil		break;
21871.54Skamil	case BYTES_TRANSFER_TEXTIO:
21881.54Skamil		switch (size) {
21891.54Skamil		case 8:
21901.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
21911.54Skamil			break;
21921.54Skamil		case 16:
21931.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
21941.54Skamil			break;
21951.54Skamil		case 32:
21961.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
21971.54Skamil			break;
21981.54Skamil		case 64:
21991.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
22001.54Skamil			break;
22011.54Skamil		}
22021.54Skamil		break;
22031.54Skamil	default:
22041.54Skamil		break;
22051.54Skamil	}
22061.1Skamil
22071.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
22081.54Skamil	switch (type) {
22091.54Skamil	case BYTES_TRANSFER_TEXTIO:
22101.54Skamil	case BYTES_TRANSFER_DATAIO:
22111.54Skamil		io.piod_op = operation;
22121.54Skamil		switch (size) {
22131.54Skamil		case 8:
22141.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22151.54Skamil			               (void *)bytes_transfer_dummy :
22161.54Skamil			               &lookup_me8;
22171.54Skamil			io.piod_addr = &lookup_me8;
22181.54Skamil			io.piod_len = sizeof(lookup_me8);
22191.54Skamil			break;
22201.54Skamil		case 16:
22211.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22221.54Skamil			               (void *)bytes_transfer_dummy :
22231.54Skamil			               &lookup_me16;
22241.54Skamil			io.piod_addr = &lookup_me16;
22251.54Skamil			io.piod_len = sizeof(lookup_me16);
22261.54Skamil			break;
22271.54Skamil		case 32:
22281.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22291.54Skamil			               (void *)bytes_transfer_dummy :
22301.54Skamil			               &lookup_me32;
22311.54Skamil			io.piod_addr = &lookup_me32;
22321.54Skamil			io.piod_len = sizeof(lookup_me32);
22331.54Skamil			break;
22341.54Skamil		case 64:
22351.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22361.54Skamil			               (void *)bytes_transfer_dummy :
22371.54Skamil			               &lookup_me64;
22381.54Skamil			io.piod_addr = &lookup_me64;
22391.54Skamil			io.piod_len = sizeof(lookup_me64);
22401.54Skamil			break;
22411.54Skamil		default:
22421.54Skamil			break;
22431.54Skamil		}
22441.54Skamil		break;
22451.54Skamil	case BYTES_TRANSFER_AUXV:
22461.54Skamil		io.piod_op = operation;
22471.54Skamil		io.piod_offs = 0;
22481.54Skamil		io.piod_addr = ai;
22491.54Skamil		io.piod_len = size;
22501.54Skamil		break;
22511.54Skamil	default:
22521.54Skamil		break;
22531.1Skamil	}
22541.1Skamil
22551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22571.1Skamil	if (child == 0) {
22581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22601.1Skamil
22611.54Skamil		switch (type) {
22621.54Skamil		case BYTES_TRANSFER_DATA:
22631.54Skamil			switch (operation) {
22641.54Skamil			case PT_READ_D:
22651.54Skamil			case PT_READ_I:
22661.54Skamil				lookup_me = magic;
22671.54Skamil				break;
22681.54Skamil			default:
22691.54Skamil				break;
22701.54Skamil			}
22711.54Skamil			break;
22721.54Skamil		case BYTES_TRANSFER_DATAIO:
22731.54Skamil			switch (operation) {
22741.54Skamil			case PIOD_READ_D:
22751.54Skamil			case PIOD_READ_I:
22761.54Skamil				switch (size) {
22771.54Skamil				case 8:
22781.54Skamil					lookup_me8 = magic8;
22791.54Skamil					break;
22801.54Skamil				case 16:
22811.54Skamil					lookup_me16 = magic16;
22821.54Skamil					break;
22831.54Skamil				case 32:
22841.54Skamil					lookup_me32 = magic32;
22851.54Skamil					break;
22861.54Skamil				case 64:
22871.54Skamil					lookup_me64 = magic64;
22881.54Skamil					break;
22891.54Skamil				default:
22901.54Skamil					break;
22911.54Skamil				}
22921.54Skamil				break;
22931.54Skamil			default:
22941.54Skamil				break;
22951.54Skamil			}
22961.54Skamil		default:
22971.54Skamil			break;
22981.54Skamil		}
22991.54Skamil
23001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23021.1Skamil
23031.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
23041.54Skamil		switch (type) {
23051.54Skamil		case BYTES_TRANSFER_DATA:
23061.54Skamil			switch (operation) {
23071.54Skamil			case PT_WRITE_D:
23081.54Skamil			case PT_WRITE_I:
23091.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
23101.54Skamil				break;
23111.54Skamil			default:
23121.54Skamil				break;
23131.54Skamil			}
23141.54Skamil			break;
23151.54Skamil		case BYTES_TRANSFER_DATAIO:
23161.54Skamil			switch (operation) {
23171.54Skamil			case PIOD_WRITE_D:
23181.54Skamil			case PIOD_WRITE_I:
23191.54Skamil				switch (size) {
23201.54Skamil				case 8:
23211.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
23221.54Skamil					break;
23231.54Skamil				case 16:
23241.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
23251.54Skamil					break;
23261.54Skamil				case 32:
23271.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
23281.54Skamil					break;
23291.54Skamil				case 64:
23301.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
23311.54Skamil					break;
23321.54Skamil				default:
23331.54Skamil					break;
23341.54Skamil				}
23351.54Skamil				break;
23361.54Skamil			default:
23371.54Skamil				break;
23381.54Skamil			}
23391.54Skamil			break;
23401.54Skamil		case BYTES_TRANSFER_TEXT:
23411.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
23421.54Skamil			                     sizeof(magic)) == 0);
23431.54Skamil			break;
23441.54Skamil		case BYTES_TRANSFER_TEXTIO:
23451.54Skamil			switch (size) {
23461.54Skamil			case 8:
23471.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
23481.54Skamil				                     bytes_transfer_dummy,
23491.54Skamil				                     sizeof(magic8)) == 0);
23501.54Skamil				break;
23511.54Skamil			case 16:
23521.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
23531.54Skamil				                     bytes_transfer_dummy,
23541.54Skamil				                     sizeof(magic16)) == 0);
23551.54Skamil				break;
23561.54Skamil			case 32:
23571.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
23581.54Skamil				                     bytes_transfer_dummy,
23591.54Skamil				                     sizeof(magic32)) == 0);
23601.54Skamil				break;
23611.54Skamil			case 64:
23621.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
23631.54Skamil				                     bytes_transfer_dummy,
23641.54Skamil				                     sizeof(magic64)) == 0);
23651.54Skamil				break;
23661.54Skamil			}
23671.54Skamil			break;
23681.54Skamil		default:
23691.54Skamil			break;
23701.54Skamil		}
23711.54Skamil
23721.13Schristos		DPRINTF("Before exiting of the child process\n");
23731.1Skamil		_exit(exitval);
23741.1Skamil	}
23751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23761.1Skamil
23771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23791.1Skamil
23801.1Skamil	validate_status_stopped(status, sigval);
23811.1Skamil
23821.54Skamil	/* Check PaX MPROTECT */
23831.54Skamil	if (!can_we_write_to_text(child)) {
23841.54Skamil		switch (type) {
23851.54Skamil		case BYTES_TRANSFER_TEXTIO:
23861.54Skamil			switch (operation) {
23871.54Skamil			case PIOD_WRITE_D:
23881.54Skamil			case PIOD_WRITE_I:
23891.54Skamil				skip = true;
23901.54Skamil				break;
23911.54Skamil			default:
23921.54Skamil				break;
23931.54Skamil			}
23941.54Skamil			break;
23951.54Skamil		case BYTES_TRANSFER_TEXT:
23961.54Skamil			switch (operation) {
23971.54Skamil			case PT_WRITE_D:
23981.54Skamil			case PT_WRITE_I:
23991.54Skamil				skip = true;
24001.54Skamil				break;
24011.54Skamil			default:
24021.54Skamil				break;
24031.54Skamil			}
24041.54Skamil			break;
24051.54Skamil		default:
24061.54Skamil			break;
24071.54Skamil		}
24081.54Skamil	}
24091.1Skamil
24101.54Skamil	/* Bailout cleanly killing the child process */
24111.54Skamil	if (skip) {
24121.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
24131.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24141.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
24151.54Skamil		                      child);
24161.1Skamil
24171.54Skamil		validate_status_signaled(status, SIGKILL, 0);
24181.1Skamil
24191.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
24201.54Skamil	}
24211.1Skamil
24221.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
24231.54Skamil	       "parent=%d\n", child, getpid());
24241.1Skamil
24251.54Skamil	switch (type) {
24261.54Skamil	case BYTES_TRANSFER_TEXTIO:
24271.54Skamil	case BYTES_TRANSFER_DATAIO:
24281.54Skamil	case BYTES_TRANSFER_AUXV:
24291.54Skamil		switch (operation) {
24301.54Skamil		case PIOD_WRITE_D:
24311.54Skamil		case PIOD_WRITE_I:
24321.54Skamil			switch (size) {
24331.54Skamil			case 8:
24341.54Skamil				lookup_me8 = magic8;
24351.54Skamil				break;
24361.54Skamil			case 16:
24371.54Skamil				lookup_me16 = magic16;
24381.54Skamil				break;
24391.54Skamil			case 32:
24401.54Skamil				lookup_me32 = magic32;
24411.54Skamil				break;
24421.54Skamil			case 64:
24431.54Skamil				lookup_me64 = magic64;
24441.54Skamil				break;
24451.54Skamil			default:
24461.54Skamil				break;
24471.54Skamil			}
24481.54Skamil			break;
24491.54Skamil		default:
24501.54Skamil			break;
24511.54Skamil		}
24521.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
24531.54Skamil		switch (operation) {
24541.54Skamil		case PIOD_READ_D:
24551.54Skamil		case PIOD_READ_I:
24561.54Skamil			switch (size) {
24571.54Skamil			case 8:
24581.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
24591.54Skamil				break;
24601.54Skamil			case 16:
24611.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
24621.54Skamil				break;
24631.54Skamil			case 32:
24641.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
24651.54Skamil				break;
24661.54Skamil			case 64:
24671.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
24681.54Skamil				break;
24691.54Skamil			default:
24701.54Skamil				break;
24711.54Skamil			}
24721.54Skamil			break;
24731.54Skamil		case PIOD_READ_AUXV:
24741.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
24751.54Skamil			        io.piod_len);
24761.54Skamil			ATF_REQUIRE(io.piod_len > 0);
24771.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
24781.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
24791.54Skamil				    (long long int)aip->a_type,
24801.54Skamil				    (long long int)aip->a_v);
24811.54Skamil			break;
24821.54Skamil		default:
24831.54Skamil			break;
24841.54Skamil		}
24851.54Skamil		break;
24861.54Skamil	case BYTES_TRANSFER_TEXT:
24871.54Skamil		switch (operation) {
24881.54Skamil		case PT_READ_D:
24891.54Skamil		case PT_READ_I:
24901.54Skamil			errno = 0;
24911.54Skamil			lookup_me = ptrace(operation, child,
24921.54Skamil			                   bytes_transfer_dummy, 0);
24931.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
24941.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
24951.54Skamil			break;
24961.54Skamil		case PT_WRITE_D:
24971.54Skamil		case PT_WRITE_I:
24981.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
24991.54Skamil			                       bytes_transfer_dummy, magic)
25001.54Skamil			                != -1);
25011.54Skamil			break;
25021.54Skamil		default:
25031.54Skamil			break;
25041.54Skamil		}
25051.54Skamil		break;
25061.54Skamil	case BYTES_TRANSFER_DATA:
25071.54Skamil		switch (operation) {
25081.54Skamil		case PT_READ_D:
25091.54Skamil		case PT_READ_I:
25101.54Skamil			errno = 0;
25111.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
25121.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
25131.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
25141.54Skamil			break;
25151.54Skamil		case PT_WRITE_D:
25161.54Skamil		case PT_WRITE_I:
25171.54Skamil			lookup_me = magic;
25181.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
25191.54Skamil			                       magic) != -1);
25201.54Skamil			break;
25211.54Skamil		default:
25221.54Skamil			break;
25231.54Skamil		}
25241.54Skamil		break;
25251.54Skamil	default:
25261.54Skamil		break;
25271.54Skamil	}
25281.1Skamil
25291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25301.1Skamil	    "without signal to be sent\n");
25311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25321.1Skamil
25331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25351.1Skamil
25361.1Skamil	validate_status_exited(status, exitval);
25371.1Skamil
25381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25401.1Skamil}
25411.1Skamil
25421.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
25431.61SkreATF_TC(test);								\
25441.61SkreATF_TC_HEAD(test, tc)							\
25451.61Skre{									\
25461.61Skre	atf_tc_set_md_var(tc, "descr",					\
25471.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
25481.61Skre	    " of type " #type);						\
25491.61Skre}									\
25501.61Skre									\
25511.61SkreATF_TC_BODY(test, tc)							\
25521.61Skre{									\
25531.61Skre									\
25541.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
25551.1Skamil}
25561.1Skamil
25571.54Skamil// DATA
25581.1Skamil
25591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
25601.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
25611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
25621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
25631.54Skamil
25641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
25651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
25661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
25671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
25681.54Skamil
25691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
25701.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
25711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
25721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
25731.54Skamil
25741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
25751.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
25761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
25771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
25781.54Skamil
25791.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
25801.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
25811.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
25821.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
25831.54Skamil
25841.54Skamil// TEXT
25851.54Skamil
25861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
25871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
25881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
25891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
25901.54Skamil
25911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
25921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
25931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
25941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
25951.54Skamil
25961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
25971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
25981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
25991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
26001.54Skamil
26011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
26021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
26031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
26041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
26051.54Skamil
26061.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
26071.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
26081.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
26091.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
26101.1Skamil
26111.54Skamil// AUXV
26121.1Skamil
26131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
26141.1Skamil
26151.54Skamil/// ----------------------------------------------------------------------------
26161.1Skamil
26171.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
26181.72Skamilstatic void
26191.72Skamilaccess_regs(const char *regset, const char *aux)
26201.1Skamil{
26211.1Skamil	const int exitval = 5;
26221.1Skamil	const int sigval = SIGSTOP;
26231.1Skamil	pid_t child, wpid;
26241.1Skamil#if defined(TWAIT_HAVE_STATUS)
26251.1Skamil	int status;
26261.1Skamil#endif
26271.72Skamil#if defined(HAVE_GPREGS)
26281.72Skamil	struct reg gpr;
26291.76Sscole	register_t rgstr;
26301.1Skamil#endif
26311.72Skamil#if defined(HAVE_FPREGS)
26321.72Skamil	struct fpreg fpr;
26331.1Skamil#endif
26341.76Sscole
26351.72Skamil#if !defined(HAVE_GPREGS)
26361.72Skamil	if (strcmp(regset, "regs") == 0)
26371.72Skamil		atf_tc_fail("Impossible test scenario!");
26381.1Skamil#endif
26391.1Skamil
26401.72Skamil#if !defined(HAVE_FPREGS)
26411.72Skamil	if (strcmp(regset, "fpregs") == 0)
26421.72Skamil		atf_tc_fail("Impossible test scenario!");
26431.1Skamil#endif
26441.1Skamil
26451.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26461.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26471.1Skamil	if (child == 0) {
26481.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26491.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26501.1Skamil
26511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26531.1Skamil
26541.13Schristos		DPRINTF("Before exiting of the child process\n");
26551.1Skamil		_exit(exitval);
26561.1Skamil	}
26571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26581.1Skamil
26591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26611.1Skamil
26621.1Skamil	validate_status_stopped(status, sigval);
26631.1Skamil
26641.1Skamil#if defined(HAVE_GPREGS)
26651.72Skamil	if (strcmp(regset, "regs") == 0) {
26661.72Skamil		DPRINTF("Call GETREGS for the child process\n");
26671.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
26681.72Skamil
26691.72Skamil		if (strcmp(aux, "none") == 0) {
26701.72Skamil			DPRINTF("Retrieved registers\n");
26711.72Skamil		} else if (strcmp(aux, "pc") == 0) {
26721.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
26731.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
26741.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
26751.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
26761.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
26771.72Skamil		} else if (strcmp(aux, "sp") == 0) {
26781.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
26791.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
26801.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
26811.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
26821.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
26831.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
26841.72Skamil			DPRINTF("Call SETREGS for the child process\n");
26851.72Skamil			SYSCALL_REQUIRE(
26861.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
26871.72Skamil		}
26881.72Skamil	}
26891.1Skamil#endif
26901.1Skamil
26911.72Skamil#if defined(HAVE_FPREGS)
26921.72Skamil	if (strcmp(regset, "fpregs") == 0) {
26931.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
26941.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
26951.72Skamil
26961.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
26971.72Skamil			DPRINTF("Retrieved FP registers\n");
26981.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
26991.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
27001.72Skamil			SYSCALL_REQUIRE(
27011.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
27021.72Skamil		}
27031.1Skamil	}
27041.1Skamil#endif
27051.1Skamil
27061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27071.1Skamil	    "without signal to be sent\n");
27081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27091.1Skamil
27101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27121.1Skamil
27131.1Skamil	validate_status_exited(status, exitval);
27141.1Skamil
27151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27171.1Skamil}
27181.1Skamil
27191.72Skamil#define ACCESS_REGS(test, regset, aux)					\
27201.72SkamilATF_TC(test);								\
27211.72SkamilATF_TC_HEAD(test, tc)							\
27221.72Skamil{									\
27231.72Skamil        atf_tc_set_md_var(tc, "descr",					\
27241.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
27251.72Skamil}									\
27261.72Skamil									\
27271.72SkamilATF_TC_BODY(test, tc)							\
27281.72Skamil{									\
27291.72Skamil									\
27301.72Skamil        access_regs(regset, aux);					\
27311.1Skamil}
27321.1Skamil#endif
27331.1Skamil
27341.72Skamil#if defined(HAVE_GPREGS)
27351.72SkamilACCESS_REGS(access_regs1, "regs", "none")
27361.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
27371.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
27381.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
27391.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
27401.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
27411.1Skamil#endif
27421.1Skamil#if defined(HAVE_FPREGS)
27431.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
27441.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
27451.1Skamil#endif
27461.1Skamil
27471.72Skamil/// ----------------------------------------------------------------------------
27481.1Skamil
27491.1Skamil#if defined(PT_STEP)
27501.1Skamilstatic void
27511.2Skamilptrace_step(int N, int setstep)
27521.1Skamil{
27531.1Skamil	const int exitval = 5;
27541.1Skamil	const int sigval = SIGSTOP;
27551.1Skamil	pid_t child, wpid;
27561.1Skamil#if defined(TWAIT_HAVE_STATUS)
27571.1Skamil	int status;
27581.1Skamil#endif
27591.1Skamil	int happy;
27601.81Skamil	struct ptrace_siginfo info;
27611.1Skamil
27621.1Skamil#if defined(__arm__)
27631.1Skamil	/* PT_STEP not supported on arm 32-bit */
27641.1Skamil	atf_tc_expect_fail("PR kern/52119");
27651.1Skamil#endif
27661.1Skamil
27671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27691.1Skamil	if (child == 0) {
27701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27721.1Skamil
27731.1Skamil		happy = check_happy(999);
27741.1Skamil
27751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27771.1Skamil
27781.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
27791.1Skamil
27801.13Schristos		DPRINTF("Before exiting of the child process\n");
27811.1Skamil		_exit(exitval);
27821.1Skamil	}
27831.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27841.1Skamil
27851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27871.1Skamil
27881.1Skamil	validate_status_stopped(status, sigval);
27891.1Skamil
27901.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
27911.81Skamil	SYSCALL_REQUIRE(
27921.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
27931.81Skamil
27941.81Skamil	DPRINTF("Before checking siginfo_t\n");
27951.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
27961.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
27971.81Skamil
27981.1Skamil	while (N --> 0) {
27991.2Skamil		if (setstep) {
28001.13Schristos			DPRINTF("Before resuming the child process where it "
28011.2Skamil			    "left off and without signal to be sent (use "
28021.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
28031.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
28041.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
28051.2Skamil			    != -1);
28061.2Skamil		} else {
28071.13Schristos			DPRINTF("Before resuming the child process where it "
28081.2Skamil			    "left off and without signal to be sent (use "
28091.2Skamil			    "PT_STEP)\n");
28101.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
28111.2Skamil			    != -1);
28121.2Skamil		}
28131.1Skamil
28141.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28151.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
28161.1Skamil		    child);
28171.1Skamil
28181.1Skamil		validate_status_stopped(status, SIGTRAP);
28191.2Skamil
28201.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
28211.81Skamil		SYSCALL_REQUIRE(
28221.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
28231.81Skamil
28241.81Skamil		DPRINTF("Before checking siginfo_t\n");
28251.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
28261.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
28271.81Skamil
28281.2Skamil		if (setstep) {
28291.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
28301.2Skamil		}
28311.1Skamil	}
28321.1Skamil
28331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28341.1Skamil	    "without signal to be sent\n");
28351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28361.1Skamil
28371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28391.1Skamil
28401.1Skamil	validate_status_exited(status, exitval);
28411.1Skamil
28421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28441.1Skamil}
28451.1Skamil
28461.73Skamil#define PTRACE_STEP(test, N, setstep)					\
28471.73SkamilATF_TC(test);								\
28481.73SkamilATF_TC_HEAD(test, tc)							\
28491.73Skamil{									\
28501.73Skamil        atf_tc_set_md_var(tc, "descr",					\
28511.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
28521.73Skamil}									\
28531.73Skamil									\
28541.73SkamilATF_TC_BODY(test, tc)							\
28551.73Skamil{									\
28561.73Skamil									\
28571.73Skamil        ptrace_step(N, setstep);					\
28581.1Skamil}
28591.1Skamil
28601.73SkamilPTRACE_STEP(step1, 1, 0)
28611.73SkamilPTRACE_STEP(step2, 2, 0)
28621.73SkamilPTRACE_STEP(step3, 3, 0)
28631.73SkamilPTRACE_STEP(step4, 4, 0)
28641.73SkamilPTRACE_STEP(setstep1, 1, 1)
28651.73SkamilPTRACE_STEP(setstep2, 2, 1)
28661.73SkamilPTRACE_STEP(setstep3, 3, 1)
28671.73SkamilPTRACE_STEP(setstep4, 4, 1)
28681.1Skamil#endif
28691.1Skamil
28701.73Skamil/// ----------------------------------------------------------------------------
28711.1Skamil
28721.75Skamilstatic void
28731.75Skamilptrace_kill(const char *type)
28741.1Skamil{
28751.75Skamil	const int sigval = SIGSTOP;
28761.1Skamil	pid_t child, wpid;
28771.1Skamil#if defined(TWAIT_HAVE_STATUS)
28781.1Skamil	int status;
28791.1Skamil#endif
28801.1Skamil
28811.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28821.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28831.1Skamil	if (child == 0) {
28841.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28851.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28861.1Skamil
28871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28891.1Skamil
28901.1Skamil		/* NOTREACHED */
28911.1Skamil		FORKEE_ASSERTX(0 &&
28921.1Skamil		    "Child should be terminated by a signal from its parent");
28931.1Skamil	}
28941.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28951.1Skamil
28961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28981.1Skamil
28991.1Skamil	validate_status_stopped(status, sigval);
29001.1Skamil
29011.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
29021.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
29031.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
29041.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
29051.75Skamil		kill(child, SIGKILL);
29061.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
29071.75Skamil		setpgid(child, 0);
29081.75Skamil		killpg(getpgid(child), SIGKILL);
29091.75Skamil	}
29101.1Skamil
29111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29131.1Skamil
29141.75Skamil	validate_status_signaled(status, SIGKILL, 0);
29151.1Skamil
29161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29181.1Skamil}
29191.1Skamil
29201.75Skamil#define PTRACE_KILL(test, type)						\
29211.75SkamilATF_TC(test);								\
29221.75SkamilATF_TC_HEAD(test, tc)							\
29231.75Skamil{									\
29241.75Skamil        atf_tc_set_md_var(tc, "descr",					\
29251.75Skamil            "Verify killing the child with " type);			\
29261.75Skamil}									\
29271.75Skamil									\
29281.75SkamilATF_TC_BODY(test, tc)							\
29291.75Skamil{									\
29301.75Skamil									\
29311.75Skamil        ptrace_kill(type);						\
29321.1Skamil}
29331.1Skamil
29341.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
29351.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
29361.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
29371.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
29381.1Skamil
29391.75Skamil/// ----------------------------------------------------------------------------
29401.1Skamil
29411.77Skamilstatic void
29421.77Skamiltraceme_lwpinfo(const int threads)
29431.1Skamil{
29441.1Skamil	const int sigval = SIGSTOP;
29451.77Skamil	const int sigval2 = SIGINT;
29461.1Skamil	pid_t child, wpid;
29471.1Skamil#if defined(TWAIT_HAVE_STATUS)
29481.1Skamil	int status;
29491.1Skamil#endif
29501.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
29511.77Skamil	struct ptrace_siginfo info;
29521.77Skamil
29531.77Skamil	/* Maximum number of supported threads in this test */
29541.77Skamil	pthread_t t[3];
29551.77Skamil	int n, rv;
29561.77Skamil
29571.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
29581.1Skamil
29591.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29601.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29611.1Skamil	if (child == 0) {
29621.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29631.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29641.1Skamil
29651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29671.1Skamil
29681.77Skamil		for (n = 0; n < threads; n++) {
29691.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
29701.77Skamil			FORKEE_ASSERT(rv == 0);
29711.77Skamil		}
29721.77Skamil
29731.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
29741.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
29751.77Skamil
29761.77Skamil		/* NOTREACHED */
29771.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
29781.1Skamil	}
29791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29801.1Skamil
29811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29831.1Skamil
29841.1Skamil	validate_status_stopped(status, sigval);
29851.1Skamil
29861.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
29871.77Skamil	SYSCALL_REQUIRE(
29881.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
29891.77Skamil
29901.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
29911.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
29921.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
29931.77Skamil	    info.psi_siginfo.si_errno);
29941.77Skamil
29951.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
29961.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
29971.77Skamil
29981.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
29991.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
30001.1Skamil
30011.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
30021.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
30031.1Skamil
30041.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
30051.77Skamil	    lwp.pl_lwpid);
30061.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
30071.1Skamil
30081.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
30091.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
30101.1Skamil
30111.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
30121.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
30131.1Skamil
30141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30151.1Skamil	    "without signal to be sent\n");
30161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30171.1Skamil
30181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30201.1Skamil
30211.77Skamil	validate_status_stopped(status, sigval2);
30221.77Skamil
30231.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
30241.77Skamil	SYSCALL_REQUIRE(
30251.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
30261.77Skamil
30271.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
30281.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
30291.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
30301.77Skamil	    info.psi_siginfo.si_errno);
30311.77Skamil
30321.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
30331.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
30341.77Skamil
30351.77Skamil	memset(&lwp, 0, sizeof(lwp));
30361.77Skamil
30371.77Skamil	for (n = 0; n <= threads; n++) {
30381.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
30391.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
30401.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
30411.77Skamil
30421.77Skamil		DPRINTF("Assert that the thread exists\n");
30431.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
30441.77Skamil
30451.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
30461.77Skamil		    lwp.pl_lwpid);
30471.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
30481.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
30491.77Skamil	}
30501.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
30511.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
30521.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
30531.77Skamil
30541.77Skamil	DPRINTF("Assert that there are no more threads\n");
30551.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
30561.77Skamil
30571.77Skamil	DPRINTF("Before resuming the child process where it left off and "
30581.77Skamil	    "without signal to be sent\n");
30591.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
30601.77Skamil
30611.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30621.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30631.77Skamil
30641.77Skamil	validate_status_signaled(status, SIGKILL, 0);
30651.1Skamil
30661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30681.1Skamil}
30691.1Skamil
30701.77Skamil#define TRACEME_LWPINFO(test, threads)					\
30711.77SkamilATF_TC(test);								\
30721.77SkamilATF_TC_HEAD(test, tc)							\
30731.77Skamil{									\
30741.77Skamil	atf_tc_set_md_var(tc, "descr",					\
30751.77Skamil	    "Verify LWPINFO with the child with " #threads		\
30761.77Skamil	    " spawned extra threads");					\
30771.77Skamil}									\
30781.77Skamil									\
30791.77SkamilATF_TC_BODY(test, tc)							\
30801.77Skamil{									\
30811.77Skamil									\
30821.77Skamil	traceme_lwpinfo(threads);					\
30831.1Skamil}
30841.1Skamil
30851.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
30861.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
30871.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
30881.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
30891.77Skamil
30901.77Skamil/// ----------------------------------------------------------------------------
30911.77Skamil
30921.77Skamil#if defined(TWAIT_HAVE_PID)
30931.77Skamilstatic void
30941.77Skamilattach_lwpinfo(const int threads)
30951.1Skamil{
30961.77Skamil	const int sigval = SIGINT;
30971.1Skamil	struct msg_fds parent_tracee, parent_tracer;
30981.1Skamil	const int exitval_tracer = 10;
30991.1Skamil	pid_t tracee, tracer, wpid;
31001.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
31011.1Skamil#if defined(TWAIT_HAVE_STATUS)
31021.1Skamil	int status;
31031.1Skamil#endif
31041.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
31051.77Skamil	struct ptrace_siginfo info;
31061.77Skamil
31071.77Skamil	/* Maximum number of supported threads in this test */
31081.77Skamil	pthread_t t[3];
31091.77Skamil	int n, rv;
31101.1Skamil
31111.13Schristos	DPRINTF("Spawn tracee\n");
31121.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
31131.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
31141.1Skamil	tracee = atf_utils_fork();
31151.1Skamil	if (tracee == 0) {
31161.1Skamil		/* Wait for message from the parent */
31171.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
31181.1Skamil
31191.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
31201.77Skamil
31211.77Skamil		for (n = 0; n < threads; n++) {
31221.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
31231.77Skamil			FORKEE_ASSERT(rv == 0);
31241.77Skamil		}
31251.77Skamil
31261.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
31271.77Skamil
31281.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31291.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31301.77Skamil
31311.77Skamil		/* NOTREACHED */
31321.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
31331.1Skamil	}
31341.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
31351.1Skamil
31361.13Schristos	DPRINTF("Spawn debugger\n");
31371.1Skamil	tracer = atf_utils_fork();
31381.1Skamil	if (tracer == 0) {
31391.1Skamil		/* No IPC to communicate with the child */
31401.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
31411.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
31421.1Skamil
31431.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
31441.1Skamil		FORKEE_REQUIRE_SUCCESS(
31451.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
31461.1Skamil
31471.1Skamil		forkee_status_stopped(status, SIGSTOP);
31481.1Skamil
31491.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
31501.77Skamil		    "tracee");
31511.77Skamil		FORKEE_ASSERT(
31521.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
31531.77Skamil
31541.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
31551.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
31561.77Skamil		    "si_errno=%#x\n",
31571.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
31581.77Skamil		    info.psi_siginfo.si_errno);
31591.77Skamil
31601.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
31611.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
31621.77Skamil
31631.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
31641.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
31651.1Skamil		    != -1);
31661.1Skamil
31671.13Schristos		DPRINTF("Assert that there exists a thread\n");
31681.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
31691.1Skamil
31701.13Schristos		DPRINTF("Assert that lwp thread %d received event "
31711.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
31721.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
31731.1Skamil
31741.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
31751.77Skamil		    "tracee\n");
31761.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
31771.1Skamil		    != -1);
31781.1Skamil
31791.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
31801.77Skamil		    "tracee\n");
31811.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
31821.1Skamil
31831.1Skamil		/* Resume tracee with PT_CONTINUE */
31841.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
31851.1Skamil
31861.1Skamil		/* Inform parent that tracer has attached to tracee */
31871.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
31881.77Skamil
31891.1Skamil		/* Wait for parent */
31901.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
31911.1Skamil
31921.77Skamil		/* Wait for tracee and assert that it raised a signal */
31931.77Skamil		FORKEE_REQUIRE_SUCCESS(
31941.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
31951.77Skamil
31961.77Skamil		forkee_status_stopped(status, SIGINT);
31971.77Skamil
31981.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
31991.77Skamil		    "child");
32001.77Skamil		FORKEE_ASSERT(
32011.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
32021.77Skamil
32031.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
32041.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
32051.77Skamil		    "si_errno=%#x\n",
32061.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
32071.77Skamil		    info.psi_siginfo.si_errno);
32081.77Skamil
32091.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
32101.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
32111.77Skamil
32121.77Skamil		memset(&lwp, 0, sizeof(lwp));
32131.77Skamil
32141.77Skamil		for (n = 0; n <= threads; n++) {
32151.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
32161.77Skamil			    "child\n");
32171.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
32181.77Skamil			    sizeof(lwp)) != -1);
32191.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
32201.77Skamil
32211.77Skamil			DPRINTF("Assert that the thread exists\n");
32221.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
32231.77Skamil
32241.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
32251.77Skamil			    "event\n", lwp.pl_lwpid);
32261.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
32271.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
32281.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
32291.77Skamil		}
32301.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
32311.77Skamil		    "tracee\n");
32321.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
32331.77Skamil		    != -1);
32341.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
32351.77Skamil
32361.77Skamil		DPRINTF("Assert that there are no more threads\n");
32371.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
32381.77Skamil
32391.77Skamil		DPRINTF("Before resuming the child process where it left off "
32401.77Skamil		    "and without signal to be sent\n");
32411.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
32421.77Skamil		    != -1);
32431.77Skamil
32441.1Skamil		/* Wait for tracee and assert that it exited */
32451.1Skamil		FORKEE_REQUIRE_SUCCESS(
32461.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
32471.1Skamil
32481.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
32491.1Skamil
32501.13Schristos		DPRINTF("Before exiting of the tracer process\n");
32511.1Skamil		_exit(exitval_tracer);
32521.1Skamil	}
32531.1Skamil
32541.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
32551.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
32561.1Skamil
32571.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
32581.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
32591.77Skamil
32601.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
32611.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
32621.1Skamil
32631.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
32641.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
32651.1Skamil
32661.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
32671.1Skamil	    TWAIT_FNAME);
32681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
32691.1Skamil	    tracer);
32701.1Skamil
32711.1Skamil	validate_status_exited(status, exitval_tracer);
32721.1Skamil
32731.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
32741.1Skamil	    TWAIT_FNAME);
32751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
32761.1Skamil	    tracee);
32771.1Skamil
32781.77Skamil	validate_status_signaled(status, SIGKILL, 0);
32791.1Skamil
32801.1Skamil	msg_close(&parent_tracer);
32811.1Skamil	msg_close(&parent_tracee);
32821.1Skamil}
32831.77Skamil
32841.77Skamil#define ATTACH_LWPINFO(test, threads)					\
32851.77SkamilATF_TC(test);								\
32861.77SkamilATF_TC_HEAD(test, tc)							\
32871.77Skamil{									\
32881.77Skamil	atf_tc_set_md_var(tc, "descr",					\
32891.77Skamil	    "Verify LWPINFO with the child with " #threads		\
32901.77Skamil	    " spawned extra threads (tracer is not the original "	\
32911.77Skamil	    "parent)");							\
32921.77Skamil}									\
32931.77Skamil									\
32941.77SkamilATF_TC_BODY(test, tc)							\
32951.77Skamil{									\
32961.77Skamil									\
32971.77Skamil	attach_lwpinfo(threads);					\
32981.77Skamil}
32991.77Skamil
33001.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
33011.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
33021.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
33031.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
33041.1Skamil#endif
33051.1Skamil
33061.77Skamil/// ----------------------------------------------------------------------------
33071.77Skamil
33081.1Skamilstatic void
33091.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
33101.1Skamil{
33111.1Skamil	const int exitval = 5;
33121.1Skamil	const int sigval = SIGINT;
33131.1Skamil	const int sigfaked = SIGTRAP;
33141.1Skamil	const int sicodefaked = TRAP_BRKPT;
33151.1Skamil	pid_t child, wpid;
33161.1Skamil	struct sigaction sa;
33171.1Skamil#if defined(TWAIT_HAVE_STATUS)
33181.1Skamil	int status;
33191.1Skamil#endif
33201.1Skamil	struct ptrace_siginfo info;
33211.1Skamil	memset(&info, 0, sizeof(info));
33221.1Skamil
33231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33251.1Skamil	if (child == 0) {
33261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33281.1Skamil
33291.79Skamil		sa.sa_sigaction = sah;
33301.1Skamil		sa.sa_flags = SA_SIGINFO;
33311.1Skamil		sigemptyset(&sa.sa_mask);
33321.1Skamil
33331.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
33341.79Skamil		    != -1);
33351.1Skamil
33361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33381.1Skamil
33391.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
33401.1Skamil
33411.13Schristos		DPRINTF("Before exiting of the child process\n");
33421.1Skamil		_exit(exitval);
33431.1Skamil	}
33441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33451.1Skamil
33461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33481.1Skamil
33491.1Skamil	validate_status_stopped(status, sigval);
33501.1Skamil
33511.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
33521.61Skre	SYSCALL_REQUIRE(
33531.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
33541.1Skamil
33551.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
33561.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
33571.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
33581.1Skamil	    info.psi_siginfo.si_errno);
33591.1Skamil
33601.79Skamil	if (faked) {
33611.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
33621.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
33631.79Skamil		info.psi_siginfo.si_signo = sigfaked;
33641.79Skamil		info.psi_siginfo.si_code = sicodefaked;
33651.79Skamil	}
33661.1Skamil
33671.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
33681.61Skre	SYSCALL_REQUIRE(
33691.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
33701.1Skamil
33711.79Skamil	if (faked) {
33721.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
33731.79Skamil		    "child\n");
33741.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
33751.79Skamil		    sizeof(info)) != -1);
33761.1Skamil
33771.79Skamil		DPRINTF("Before checking siginfo_t\n");
33781.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
33791.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
33801.79Skamil	}
33811.1Skamil
33821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33831.1Skamil	    "without signal to be sent\n");
33841.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
33851.79Skamil	    faked ? sigfaked : sigval) != -1);
33861.1Skamil
33871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33891.1Skamil
33901.1Skamil	validate_status_exited(status, exitval);
33911.1Skamil
33921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33941.1Skamil}
33951.1Skamil
33961.79Skamil#define PTRACE_SIGINFO(test, faked)					\
33971.79SkamilATF_TC(test);								\
33981.79SkamilATF_TC_HEAD(test, tc)							\
33991.79Skamil{									\
34001.79Skamil	atf_tc_set_md_var(tc, "descr",					\
34011.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
34021.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
34031.79Skamil}									\
34041.79Skamil									\
34051.79Skamilstatic int test##_caught = 0;						\
34061.79Skamil									\
34071.79Skamilstatic void								\
34081.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
34091.79Skamil{									\
34101.79Skamil	if (faked) {							\
34111.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
34121.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
34131.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
34141.79Skamil	} else {							\
34151.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
34161.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
34171.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
34181.79Skamil	}								\
34191.79Skamil									\
34201.79Skamil	++ test##_caught;						\
34211.79Skamil}									\
34221.79Skamil									\
34231.79SkamilATF_TC_BODY(test, tc)							\
34241.79Skamil{									\
34251.79Skamil									\
34261.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
34271.79Skamil}
34281.79Skamil
34291.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
34301.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
34311.79Skamil
34321.79Skamil/// ----------------------------------------------------------------------------
34331.79Skamil
34341.82SkamilATF_TC(traceme_exec);
34351.82SkamilATF_TC_HEAD(traceme_exec, tc)
34361.1Skamil{
34371.1Skamil	atf_tc_set_md_var(tc, "descr",
34381.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
34391.1Skamil}
34401.1Skamil
34411.82SkamilATF_TC_BODY(traceme_exec, tc)
34421.1Skamil{
34431.1Skamil	const int sigval = SIGTRAP;
34441.1Skamil	pid_t child, wpid;
34451.1Skamil#if defined(TWAIT_HAVE_STATUS)
34461.1Skamil	int status;
34471.1Skamil#endif
34481.1Skamil
34491.1Skamil	struct ptrace_siginfo info;
34501.1Skamil	memset(&info, 0, sizeof(info));
34511.1Skamil
34521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34541.1Skamil	if (child == 0) {
34551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34571.1Skamil
34581.13Schristos		DPRINTF("Before calling execve(2) from child\n");
34591.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
34601.1Skamil
34611.1Skamil		FORKEE_ASSERT(0 && "Not reached");
34621.1Skamil	}
34631.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34641.1Skamil
34651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34671.1Skamil
34681.1Skamil	validate_status_stopped(status, sigval);
34691.1Skamil
34701.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
34711.61Skre	SYSCALL_REQUIRE(
34721.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
34731.1Skamil
34741.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
34751.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
34761.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
34771.1Skamil	    info.psi_siginfo.si_errno);
34781.1Skamil
34791.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
34801.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
34811.1Skamil
34821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34831.1Skamil	    "without signal to be sent\n");
34841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34851.1Skamil
34861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34881.1Skamil
34891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34911.1Skamil}
34921.1Skamil
34931.82Skamil/// ----------------------------------------------------------------------------
34941.82Skamil
34951.83Skamilstatic volatile int done;
34961.1Skamil
34971.83Skamilstatic void *
34981.83Skamiltrace_threads_cb(void *arg __unused)
34991.1Skamil{
35001.1Skamil
35011.83Skamil	done++;
35021.83Skamil
35031.83Skamil	while (done < 3)
35041.83Skamil		continue;
35051.83Skamil
35061.83Skamil	return NULL;
35071.1Skamil}
35081.1Skamil
35091.83Skamilstatic void
35101.83Skamiltrace_threads(bool trace_create, bool trace_exit)
35111.1Skamil{
35121.1Skamil	const int sigval = SIGSTOP;
35131.1Skamil	pid_t child, wpid;
35141.1Skamil#if defined(TWAIT_HAVE_STATUS)
35151.1Skamil	int status;
35161.1Skamil#endif
35171.1Skamil	ptrace_state_t state;
35181.1Skamil	const int slen = sizeof(state);
35191.1Skamil	ptrace_event_t event;
35201.1Skamil	const int elen = sizeof(event);
35211.83Skamil	struct ptrace_siginfo info;
35221.83Skamil
35231.83Skamil	pthread_t t[3];
35241.83Skamil	int rv;
35251.83Skamil	size_t n;
35261.1Skamil	lwpid_t lid;
35271.83Skamil
35281.83Skamil	/* Track created and exited threads */
35291.83Skamil	bool traced_lwps[__arraycount(t)];
35301.83Skamil
35311.83Skamil	atf_tc_skip("PR kern/51995");
35321.1Skamil
35331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35351.1Skamil	if (child == 0) {
35361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35381.1Skamil
35391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35411.1Skamil
35421.83Skamil		for (n = 0; n < __arraycount(t); n++) {
35431.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
35441.83Skamil			    NULL);
35451.83Skamil			FORKEE_ASSERT(rv == 0);
35461.83Skamil		}
35471.1Skamil
35481.83Skamil		for (n = 0; n < __arraycount(t); n++) {
35491.83Skamil			rv = pthread_join(t[n], NULL);
35501.83Skamil			FORKEE_ASSERT(rv == 0);
35511.83Skamil		}
35521.1Skamil
35531.83Skamil		/*
35541.83Skamil		 * There is race between _exit() and pthread_join() detaching
35551.83Skamil		 * a thread. For simplicity kill the process after detecting
35561.83Skamil		 * LWP events.
35571.83Skamil		 */
35581.83Skamil		while (true)
35591.83Skamil			continue;
35601.1Skamil
35611.83Skamil		FORKEE_ASSERT(0 && "Not reached");
35621.1Skamil	}
35631.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35641.1Skamil
35651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35671.1Skamil
35681.1Skamil	validate_status_stopped(status, sigval);
35691.1Skamil
35701.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35711.83Skamil	SYSCALL_REQUIRE(
35721.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35731.1Skamil
35741.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35751.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35761.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35771.83Skamil	    info.psi_siginfo.si_errno);
35781.1Skamil
35791.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
35801.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
35811.1Skamil
35821.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
35831.83Skamil	memset(&event, 0, sizeof(event));
35841.83Skamil	if (trace_create)
35851.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
35861.83Skamil	if (trace_exit)
35871.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
35881.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
35891.1Skamil
35901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35911.1Skamil	    "without signal to be sent\n");
35921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35931.1Skamil
35941.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
35951.1Skamil
35961.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
35971.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
35981.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
35991.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
36001.83Skamil		    child);
36011.1Skamil
36021.83Skamil		validate_status_stopped(status, SIGTRAP);
36031.1Skamil
36041.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
36051.83Skamil		    "child\n");
36061.83Skamil		SYSCALL_REQUIRE(
36071.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36081.1Skamil
36091.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36101.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
36111.83Skamil		    "si_errno=%#x\n",
36121.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36131.83Skamil		    info.psi_siginfo.si_errno);
36141.1Skamil
36151.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
36161.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
36171.1Skamil
36181.83Skamil		SYSCALL_REQUIRE(
36191.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
36201.1Skamil
36211.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
36221.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
36231.1Skamil
36241.83Skamil		lid = state.pe_lwp;
36251.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
36261.1Skamil
36271.83Skamil		traced_lwps[lid - 1] = true;
36281.1Skamil
36291.83Skamil		DPRINTF("Before resuming the child process where it left off "
36301.83Skamil		    "and without signal to be sent\n");
36311.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36321.83Skamil	}
36331.1Skamil
36341.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
36351.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
36361.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
36371.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
36381.83Skamil		    child);
36391.1Skamil
36401.83Skamil		validate_status_stopped(status, SIGTRAP);
36411.1Skamil
36421.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
36431.83Skamil		    "child\n");
36441.83Skamil		SYSCALL_REQUIRE(
36451.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36461.1Skamil
36471.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36481.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
36491.83Skamil		    "si_errno=%#x\n",
36501.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36511.83Skamil		    info.psi_siginfo.si_errno);
36521.1Skamil
36531.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
36541.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
36551.1Skamil
36561.83Skamil		SYSCALL_REQUIRE(
36571.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
36581.1Skamil
36591.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
36601.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
36611.1Skamil
36621.83Skamil		lid = state.pe_lwp;
36631.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
36641.1Skamil
36651.83Skamil		if (trace_create) {
36661.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
36671.83Skamil			traced_lwps[lid - 1] = false;
36681.83Skamil		}
36691.1Skamil
36701.83Skamil		DPRINTF("Before resuming the child process where it left off "
36711.83Skamil		    "and without signal to be sent\n");
36721.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36731.83Skamil	}
36741.1Skamil
36751.83Skamil	kill(child, SIGKILL);
36761.1Skamil
36771.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
36781.1Skamil	    TWAIT_FNAME);
36791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36801.1Skamil
36811.83Skamil	validate_status_signaled(status, SIGKILL, 0);
36821.1Skamil
36831.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
36841.1Skamil	    TWAIT_FNAME);
36851.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36861.1Skamil}
36871.1Skamil
36881.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
36891.83SkamilATF_TC(test);								\
36901.83SkamilATF_TC_HEAD(test, tc)							\
36911.83Skamil{									\
36921.83Skamil        atf_tc_set_md_var(tc, "descr",					\
36931.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
36941.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
36951.83Skamil	    trace_exit ? "" : "out");					\
36961.83Skamil}									\
36971.83Skamil									\
36981.83SkamilATF_TC_BODY(test, tc)							\
36991.83Skamil{									\
37001.83Skamil									\
37011.83Skamil        trace_threads(trace_create, trace_exit);			\
37021.83Skamil}
37031.83Skamil
37041.83SkamilTRACE_THREADS(trace_thread1, false, false)
37051.83SkamilTRACE_THREADS(trace_thread2, false, true)
37061.83SkamilTRACE_THREADS(trace_thread3, true, false)
37071.83SkamilTRACE_THREADS(trace_thread4, true, true)
37081.83Skamil
37091.83Skamil/// ----------------------------------------------------------------------------
37101.83Skamil
37111.84SkamilATF_TC(signal_mask_unrelated);
37121.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
37131.1Skamil{
37141.1Skamil	atf_tc_set_md_var(tc, "descr",
37151.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
37161.1Skamil	    "from catching other signals");
37171.1Skamil}
37181.1Skamil
37191.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
37201.1Skamil{
37211.1Skamil	const int exitval = 5;
37221.1Skamil	const int sigval = SIGSTOP;
37231.1Skamil	const int sigmasked = SIGTRAP;
37241.1Skamil	const int signotmasked = SIGINT;
37251.1Skamil	pid_t child, wpid;
37261.1Skamil#if defined(TWAIT_HAVE_STATUS)
37271.1Skamil	int status;
37281.1Skamil#endif
37291.1Skamil	sigset_t intmask;
37301.1Skamil
37311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37331.1Skamil	if (child == 0) {
37341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37361.1Skamil
37371.1Skamil		sigemptyset(&intmask);
37381.1Skamil		sigaddset(&intmask, sigmasked);
37391.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
37401.1Skamil
37411.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37421.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37431.1Skamil
37441.13Schristos		DPRINTF("Before raising %s from child\n",
37451.1Skamil		    strsignal(signotmasked));
37461.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
37471.1Skamil
37481.13Schristos		DPRINTF("Before exiting of the child process\n");
37491.1Skamil		_exit(exitval);
37501.1Skamil	}
37511.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37521.1Skamil
37531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37551.1Skamil
37561.1Skamil	validate_status_stopped(status, sigval);
37571.1Skamil
37581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37591.1Skamil	    "without signal to be sent\n");
37601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37611.1Skamil
37621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37641.1Skamil
37651.1Skamil	validate_status_stopped(status, signotmasked);
37661.1Skamil
37671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37681.1Skamil	    "without signal to be sent\n");
37691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37701.1Skamil
37711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37731.1Skamil
37741.1Skamil	validate_status_exited(status, exitval);
37751.1Skamil
37761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37781.1Skamil}
37791.1Skamil
37801.84Skamil/// ----------------------------------------------------------------------------
37811.84Skamil
37821.1SkamilATF_TC(signal2);
37831.1SkamilATF_TC_HEAD(signal2, tc)
37841.1Skamil{
37851.1Skamil	atf_tc_set_md_var(tc, "descr",
37861.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
37871.1Skamil	    "catching this raised signal");
37881.1Skamil}
37891.1Skamil
37901.1SkamilATF_TC_BODY(signal2, tc)
37911.1Skamil{
37921.1Skamil	const int exitval = 5;
37931.1Skamil	const int sigval = SIGSTOP;
37941.1Skamil	const int sigmasked = SIGTRAP;
37951.1Skamil	pid_t child, wpid;
37961.1Skamil#if defined(TWAIT_HAVE_STATUS)
37971.1Skamil	int status;
37981.1Skamil#endif
37991.1Skamil	sigset_t intmask;
38001.1Skamil
38011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38031.1Skamil	if (child == 0) {
38041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38061.1Skamil
38071.1Skamil		sigemptyset(&intmask);
38081.1Skamil		sigaddset(&intmask, sigmasked);
38091.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
38101.1Skamil
38111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38131.1Skamil
38141.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
38151.1Skamil		    strsignal(sigmasked));
38161.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
38171.1Skamil
38181.13Schristos		DPRINTF("Before exiting of the child process\n");
38191.1Skamil		_exit(exitval);
38201.1Skamil	}
38211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38221.1Skamil
38231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38251.1Skamil
38261.1Skamil	validate_status_stopped(status, sigval);
38271.1Skamil
38281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38291.1Skamil	    "without signal to be sent\n");
38301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38311.1Skamil
38321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38341.1Skamil
38351.1Skamil	validate_status_exited(status, exitval);
38361.1Skamil
38371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38391.1Skamil}
38401.1Skamil
38411.1SkamilATF_TC(signal3);
38421.1SkamilATF_TC_HEAD(signal3, tc)
38431.1Skamil{
38441.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
38451.1Skamil	atf_tc_set_md_var(tc, "descr",
38461.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
38471.1Skamil	    "catching software breakpoints");
38481.1Skamil}
38491.1Skamil
38501.1SkamilATF_TC_BODY(signal3, tc)
38511.1Skamil{
38521.1Skamil	const int exitval = 5;
38531.1Skamil	const int sigval = SIGSTOP;
38541.1Skamil	const int sigmasked = SIGTRAP;
38551.1Skamil	pid_t child, wpid;
38561.1Skamil#if defined(TWAIT_HAVE_STATUS)
38571.1Skamil	int status;
38581.1Skamil#endif
38591.1Skamil	sigset_t intmask;
38601.1Skamil
38611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38631.1Skamil	if (child == 0) {
38641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38661.1Skamil
38671.1Skamil		sigemptyset(&intmask);
38681.1Skamil		sigaddset(&intmask, sigmasked);
38691.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
38701.1Skamil
38711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38731.1Skamil
38741.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
38751.52Skamil		trigger_trap();
38761.1Skamil
38771.13Schristos		DPRINTF("Before exiting of the child process\n");
38781.1Skamil		_exit(exitval);
38791.1Skamil	}
38801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38811.1Skamil
38821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38841.1Skamil
38851.1Skamil	validate_status_stopped(status, sigval);
38861.1Skamil
38871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38881.1Skamil	    "without signal to be sent\n");
38891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38901.1Skamil
38911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38931.1Skamil
38941.1Skamil	validate_status_stopped(status, sigmasked);
38951.1Skamil
38961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38971.1Skamil	    "without signal to be sent\n");
38981.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
38991.1Skamil
39001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39021.1Skamil
39031.49Skamil	validate_status_signaled(status, SIGKILL, 0);
39041.1Skamil
39051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39071.1Skamil}
39081.1Skamil
39091.1Skamil#if defined(PT_STEP)
39101.1SkamilATF_TC(signal4);
39111.1SkamilATF_TC_HEAD(signal4, tc)
39121.1Skamil{
39131.1Skamil	atf_tc_set_md_var(tc, "descr",
39141.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
39151.1Skamil	    "catching single step trap");
39161.1Skamil}
39171.1Skamil
39181.1SkamilATF_TC_BODY(signal4, tc)
39191.1Skamil{
39201.1Skamil	const int exitval = 5;
39211.1Skamil	const int sigval = SIGSTOP;
39221.1Skamil	const int sigmasked = SIGTRAP;
39231.1Skamil	pid_t child, wpid;
39241.1Skamil#if defined(TWAIT_HAVE_STATUS)
39251.1Skamil	int status;
39261.1Skamil#endif
39271.1Skamil	sigset_t intmask;
39281.1Skamil	int happy;
39291.1Skamil
39301.1Skamil#if defined(__arm__)
39311.5Skamil	/* PT_STEP not supported on arm 32-bit */
39321.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
39331.1Skamil#endif
39341.1Skamil
39351.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39361.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39371.1Skamil	if (child == 0) {
39381.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39391.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39401.1Skamil
39411.1Skamil		happy = check_happy(100);
39421.1Skamil
39431.1Skamil		sigemptyset(&intmask);
39441.1Skamil		sigaddset(&intmask, sigmasked);
39451.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
39461.1Skamil
39471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39491.1Skamil
39501.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
39511.1Skamil
39521.13Schristos		DPRINTF("Before exiting of the child process\n");
39531.1Skamil		_exit(exitval);
39541.1Skamil	}
39551.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39561.1Skamil
39571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39591.1Skamil
39601.1Skamil	validate_status_stopped(status, sigval);
39611.1Skamil
39621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39631.1Skamil	    "without signal to be sent\n");
39641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
39651.1Skamil
39661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39681.1Skamil
39691.1Skamil	validate_status_stopped(status, sigmasked);
39701.1Skamil
39711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39721.1Skamil	    "without signal to be sent\n");
39731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39741.1Skamil
39751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39771.1Skamil
39781.1Skamil	validate_status_exited(status, exitval);
39791.1Skamil
39801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39821.1Skamil}
39831.1Skamil#endif
39841.1Skamil
39851.1SkamilATF_TC(signal5);
39861.1SkamilATF_TC_HEAD(signal5, tc)
39871.1Skamil{
39881.1Skamil	atf_tc_set_md_var(tc, "descr",
39891.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
39901.1Skamil	    "catching exec() breakpoint");
39911.1Skamil}
39921.1Skamil
39931.1SkamilATF_TC_BODY(signal5, tc)
39941.1Skamil{
39951.1Skamil	const int sigval = SIGSTOP;
39961.1Skamil	const int sigmasked = SIGTRAP;
39971.1Skamil	pid_t child, wpid;
39981.1Skamil#if defined(TWAIT_HAVE_STATUS)
39991.1Skamil	int status;
40001.1Skamil#endif
40011.58Skamil	struct ptrace_siginfo info;
40021.1Skamil	sigset_t intmask;
40031.1Skamil
40041.58Skamil	memset(&info, 0, sizeof(info));
40051.14Schristos
40061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40081.1Skamil	if (child == 0) {
40091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40111.1Skamil
40121.1Skamil		sigemptyset(&intmask);
40131.1Skamil		sigaddset(&intmask, sigmasked);
40141.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
40151.1Skamil
40161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40181.1Skamil
40191.13Schristos		DPRINTF("Before calling execve(2) from child\n");
40201.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
40211.1Skamil
40221.58Skamil		/* NOTREACHED */
40231.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
40241.1Skamil	}
40251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40261.1Skamil
40271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40291.1Skamil
40301.1Skamil	validate_status_stopped(status, sigval);
40311.1Skamil
40321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40331.1Skamil	    "without signal to be sent\n");
40341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40351.1Skamil
40361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40381.1Skamil
40391.1Skamil	validate_status_stopped(status, sigmasked);
40401.1Skamil
40411.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40421.61Skre	SYSCALL_REQUIRE(
40431.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
40441.58Skamil
40451.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
40461.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
40471.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
40481.58Skamil	    info.psi_siginfo.si_errno);
40491.58Skamil
40501.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
40511.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
40521.58Skamil
40531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40541.1Skamil	    "without signal to be sent\n");
40551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40561.1Skamil
40571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40591.1Skamil
40601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40611.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40621.1Skamil}
40631.1Skamil
40641.1Skamil#if defined(TWAIT_HAVE_PID)
40651.1SkamilATF_TC(signal6);
40661.1SkamilATF_TC_HEAD(signal6, tc)
40671.1Skamil{
40681.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
40691.1Skamil	atf_tc_set_md_var(tc, "descr",
40701.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
40711.1Skamil	    "catching PTRACE_FORK breakpoint");
40721.1Skamil}
40731.1Skamil
40741.1SkamilATF_TC_BODY(signal6, tc)
40751.1Skamil{
40761.1Skamil	const int exitval = 5;
40771.1Skamil	const int exitval2 = 15;
40781.1Skamil	const int sigval = SIGSTOP;
40791.1Skamil	const int sigmasked = SIGTRAP;
40801.1Skamil	pid_t child, child2, wpid;
40811.1Skamil#if defined(TWAIT_HAVE_STATUS)
40821.1Skamil	int status;
40831.1Skamil#endif
40841.1Skamil	sigset_t intmask;
40851.1Skamil	ptrace_state_t state;
40861.1Skamil	const int slen = sizeof(state);
40871.1Skamil	ptrace_event_t event;
40881.1Skamil	const int elen = sizeof(event);
40891.1Skamil
40901.38Skamil	atf_tc_expect_fail("PR kern/51918");
40911.14Schristos
40921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40941.1Skamil	if (child == 0) {
40951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40971.1Skamil
40981.1Skamil		sigemptyset(&intmask);
40991.1Skamil		sigaddset(&intmask, sigmasked);
41001.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
41011.1Skamil
41021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41041.1Skamil
41051.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
41061.1Skamil
41071.1Skamil		if (child2 == 0)
41081.1Skamil			_exit(exitval2);
41091.1Skamil
41101.1Skamil		FORKEE_REQUIRE_SUCCESS
41111.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
41121.1Skamil
41131.1Skamil		forkee_status_exited(status, exitval2);
41141.1Skamil
41151.13Schristos		DPRINTF("Before exiting of the child process\n");
41161.1Skamil		_exit(exitval);
41171.1Skamil	}
41181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41191.1Skamil
41201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41221.1Skamil
41231.1Skamil	validate_status_stopped(status, sigval);
41241.1Skamil
41251.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
41261.1Skamil	event.pe_set_event = PTRACE_FORK;
41271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
41281.1Skamil
41291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41301.1Skamil	    "without signal to be sent\n");
41311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41321.1Skamil
41331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41351.1Skamil
41361.1Skamil	validate_status_stopped(status, sigmasked);
41371.1Skamil
41381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
41391.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
41401.1Skamil
41411.1Skamil	child2 = state.pe_other_pid;
41421.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
41431.1Skamil
41441.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
41451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
41461.1Skamil	    child2);
41471.1Skamil
41481.1Skamil	validate_status_stopped(status, SIGTRAP);
41491.1Skamil
41501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
41511.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
41521.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
41531.1Skamil
41541.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
41551.1Skamil	    "without signal to be sent\n");
41561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
41571.1Skamil
41581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41591.1Skamil	    "without signal to be sent\n");
41601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41611.1Skamil
41621.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
41631.1Skamil	    TWAIT_FNAME);
41641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
41651.57Skamil	    child2);
41661.1Skamil
41671.1Skamil	validate_status_exited(status, exitval2);
41681.1Skamil
41691.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
41701.1Skamil	    TWAIT_FNAME);
41711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
41721.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
41731.1Skamil
41741.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
41751.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
41761.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41771.1Skamil
41781.1Skamil	validate_status_stopped(status, SIGCHLD);
41791.1Skamil
41801.57Skamil	DPRINTF("Before resuming the child process where it left off and "
41811.1Skamil	    "without signal to be sent\n");
41821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41831.1Skamil
41841.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
41851.1Skamil	    TWAIT_FNAME);
41861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41871.1Skamil
41881.1Skamil	validate_status_exited(status, exitval);
41891.1Skamil
41901.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
41911.57Skamil	    TWAIT_FNAME);
41921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41931.1Skamil}
41941.1Skamil#endif
41951.1Skamil
41961.1Skamil#if defined(TWAIT_HAVE_PID)
41971.1SkamilATF_TC(signal7);
41981.1SkamilATF_TC_HEAD(signal7, tc)
41991.1Skamil{
42001.1Skamil	atf_tc_set_md_var(tc, "descr",
42011.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
42021.1Skamil	    "catching PTRACE_VFORK breakpoint");
42031.1Skamil}
42041.1Skamil
42051.1SkamilATF_TC_BODY(signal7, tc)
42061.1Skamil{
42071.1Skamil	const int exitval = 5;
42081.1Skamil	const int exitval2 = 15;
42091.1Skamil	const int sigval = SIGSTOP;
42101.1Skamil	const int sigmasked = SIGTRAP;
42111.1Skamil	pid_t child, child2, wpid;
42121.1Skamil#if defined(TWAIT_HAVE_STATUS)
42131.1Skamil	int status;
42141.1Skamil#endif
42151.1Skamil	sigset_t intmask;
42161.1Skamil	ptrace_state_t state;
42171.1Skamil	const int slen = sizeof(state);
42181.1Skamil	ptrace_event_t event;
42191.1Skamil	const int elen = sizeof(event);
42201.1Skamil
42211.38Skamil	atf_tc_expect_fail("PR kern/51918");
42221.14Schristos
42231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42251.1Skamil	if (child == 0) {
42261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42281.1Skamil
42291.1Skamil		sigemptyset(&intmask);
42301.1Skamil		sigaddset(&intmask, sigmasked);
42311.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
42321.1Skamil
42331.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42341.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42351.1Skamil
42361.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
42371.1Skamil
42381.1Skamil		if (child2 == 0)
42391.1Skamil			_exit(exitval2);
42401.1Skamil
42411.1Skamil		FORKEE_REQUIRE_SUCCESS
42421.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
42431.1Skamil
42441.1Skamil		forkee_status_exited(status, exitval2);
42451.1Skamil
42461.13Schristos		DPRINTF("Before exiting of the child process\n");
42471.1Skamil		_exit(exitval);
42481.1Skamil	}
42491.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42501.1Skamil
42511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42531.1Skamil
42541.1Skamil	validate_status_stopped(status, sigval);
42551.1Skamil
42561.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
42571.1Skamil	event.pe_set_event = PTRACE_VFORK;
42581.61Skre	SYSCALL_REQUIRE(
42591.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
42601.61Skre	    errno == ENOTSUP);
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 child\n", TWAIT_FNAME);
42671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42681.1Skamil
42691.1Skamil	validate_status_stopped(status, sigmasked);
42701.1Skamil
42711.61Skre	SYSCALL_REQUIRE(
42721.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
42731.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
42741.1Skamil
42751.1Skamil	child2 = state.pe_other_pid;
42761.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
42771.1Skamil
42781.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
42791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
42801.1Skamil	    child2);
42811.1Skamil
42821.1Skamil	validate_status_stopped(status, SIGTRAP);
42831.1Skamil
42841.61Skre	SYSCALL_REQUIRE(
42851.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
42861.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
42871.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
42881.1Skamil
42891.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
42901.1Skamil	    "without signal to be sent\n");
42911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
42921.1Skamil
42931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42941.1Skamil	    "without signal to be sent\n");
42951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42961.1Skamil
42971.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
42981.1Skamil	    TWAIT_FNAME);
42991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
43001.57Skamil	    child2);
43011.1Skamil
43021.1Skamil	validate_status_exited(status, exitval2);
43031.1Skamil
43041.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
43051.1Skamil	    TWAIT_FNAME);
43061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
43071.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
43081.1Skamil
43091.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
43101.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
43111.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43121.1Skamil
43131.1Skamil	validate_status_stopped(status, SIGCHLD);
43141.1Skamil
43151.57Skamil	DPRINTF("Before resuming the child process where it left off and "
43161.1Skamil	    "without signal to be sent\n");
43171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43181.1Skamil
43191.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
43201.1Skamil	    TWAIT_FNAME);
43211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43221.1Skamil
43231.1Skamil	validate_status_exited(status, exitval);
43241.1Skamil
43251.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
43261.57Skamil	    TWAIT_FNAME);
43271.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43281.1Skamil}
43291.1Skamil#endif
43301.1Skamil
43311.1SkamilATF_TC(signal8);
43321.1SkamilATF_TC_HEAD(signal8, tc)
43331.1Skamil{
43341.1Skamil	atf_tc_set_md_var(tc, "descr",
43351.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43361.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
43371.1Skamil}
43381.1Skamil
43391.1SkamilATF_TC_BODY(signal8, tc)
43401.1Skamil{
43411.1Skamil	const int exitval = 5;
43421.1Skamil	const int exitval2 = 15;
43431.1Skamil	const int sigval = SIGSTOP;
43441.1Skamil	const int sigmasked = SIGTRAP;
43451.1Skamil	pid_t child, child2, wpid;
43461.1Skamil#if defined(TWAIT_HAVE_STATUS)
43471.1Skamil	int status;
43481.1Skamil#endif
43491.1Skamil	sigset_t intmask;
43501.1Skamil	ptrace_state_t state;
43511.1Skamil	const int slen = sizeof(state);
43521.1Skamil	ptrace_event_t event;
43531.1Skamil	const int elen = sizeof(event);
43541.1Skamil
43551.14Schristos	atf_tc_expect_fail("PR kern/51918");
43561.14Schristos
43571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43591.1Skamil	if (child == 0) {
43601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43621.1Skamil
43631.1Skamil		sigemptyset(&intmask);
43641.1Skamil		sigaddset(&intmask, sigmasked);
43651.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43661.1Skamil
43671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43691.1Skamil
43701.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
43711.1Skamil
43721.1Skamil		if (child2 == 0)
43731.1Skamil			_exit(exitval2);
43741.1Skamil
43751.1Skamil		FORKEE_REQUIRE_SUCCESS
43761.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
43771.1Skamil
43781.1Skamil		forkee_status_exited(status, exitval2);
43791.1Skamil
43801.13Schristos		DPRINTF("Before exiting of the child process\n");
43811.1Skamil		_exit(exitval);
43821.1Skamil	}
43831.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43841.1Skamil
43851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43871.1Skamil
43881.1Skamil	validate_status_stopped(status, sigval);
43891.1Skamil
43901.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
43911.1Skamil	    child);
43921.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
43931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
43941.1Skamil
43951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43961.1Skamil	    "without signal to be sent\n");
43971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43981.1Skamil
43991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44011.1Skamil
44021.1Skamil	validate_status_stopped(status, sigmasked);
44031.1Skamil
44041.61Skre	SYSCALL_REQUIRE(
44051.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
44061.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
44071.1Skamil
44081.1Skamil	child2 = state.pe_other_pid;
44091.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
44101.1Skamil
44111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44121.1Skamil	    "without signal to be sent\n");
44131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44141.1Skamil
44151.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
44161.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
44171.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44181.1Skamil
44191.1Skamil	validate_status_stopped(status, SIGCHLD);
44201.1Skamil
44211.57Skamil	DPRINTF("Before resuming the child process where it left off and "
44221.1Skamil	    "without signal to be sent\n");
44231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44241.1Skamil
44251.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
44261.1Skamil	    TWAIT_FNAME);
44271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44281.1Skamil
44291.1Skamil	validate_status_exited(status, exitval);
44301.1Skamil
44311.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
44321.57Skamil	    TWAIT_FNAME);
44331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44341.1Skamil}
44351.1Skamil
44361.83Skamilvolatile lwpid_t the_lwp_id = 0;
44371.83Skamil
44381.83Skamilstatic void
44391.83Skamillwp_main_func(void *arg)
44401.83Skamil{
44411.83Skamil	the_lwp_id = _lwp_self();
44421.83Skamil	_lwp_exit();
44431.83Skamil}
44441.83Skamil
44451.1SkamilATF_TC(signal9);
44461.1SkamilATF_TC_HEAD(signal9, tc)
44471.1Skamil{
44481.1Skamil	atf_tc_set_md_var(tc, "descr",
44491.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44501.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
44511.1Skamil}
44521.1Skamil
44531.1SkamilATF_TC_BODY(signal9, tc)
44541.1Skamil{
44551.1Skamil	const int exitval = 5;
44561.1Skamil	const int sigval = SIGSTOP;
44571.1Skamil	const int sigmasked = SIGTRAP;
44581.1Skamil	pid_t child, wpid;
44591.1Skamil#if defined(TWAIT_HAVE_STATUS)
44601.1Skamil	int status;
44611.1Skamil#endif
44621.1Skamil	sigset_t intmask;
44631.1Skamil	ptrace_state_t state;
44641.1Skamil	const int slen = sizeof(state);
44651.1Skamil	ptrace_event_t event;
44661.1Skamil	const int elen = sizeof(event);
44671.1Skamil	ucontext_t uc;
44681.1Skamil	lwpid_t lid;
44691.1Skamil	static const size_t ssize = 16*1024;
44701.1Skamil	void *stack;
44711.1Skamil
44721.14Schristos	atf_tc_expect_fail("PR kern/51918");
44731.14Schristos
44741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44761.1Skamil	if (child == 0) {
44771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44791.1Skamil
44801.1Skamil		sigemptyset(&intmask);
44811.1Skamil		sigaddset(&intmask, sigmasked);
44821.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44831.1Skamil
44841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44861.1Skamil
44871.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
44881.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
44891.1Skamil
44901.13Schristos		DPRINTF("Before making context for new lwp in child\n");
44911.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
44921.1Skamil
44931.13Schristos		DPRINTF("Before creating new in child\n");
44941.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
44951.1Skamil
44961.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
44971.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
44981.1Skamil
44991.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
45001.1Skamil		    "are the same\n", lid, the_lwp_id);
45011.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
45021.1Skamil
45031.13Schristos		DPRINTF("Before exiting of the child process\n");
45041.1Skamil		_exit(exitval);
45051.1Skamil	}
45061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45071.1Skamil
45081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45101.1Skamil
45111.1Skamil	validate_status_stopped(status, sigval);
45121.1Skamil
45131.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
45141.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
45151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
45161.1Skamil
45171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45181.1Skamil	    "without signal to be sent\n");
45191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45201.1Skamil
45211.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
45221.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
45231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45241.1Skamil
45251.1Skamil	validate_status_stopped(status, sigmasked);
45261.1Skamil
45271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
45281.1Skamil
45291.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
45301.1Skamil
45311.1Skamil	lid = state.pe_lwp;
45321.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
45331.1Skamil
45341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45351.1Skamil	    "without signal to be sent\n");
45361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45371.1Skamil
45381.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
45391.1Skamil	    TWAIT_FNAME);
45401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45411.1Skamil
45421.1Skamil	validate_status_exited(status, exitval);
45431.1Skamil
45441.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
45451.1Skamil	    TWAIT_FNAME);
45461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45471.1Skamil}
45481.1Skamil
45491.1SkamilATF_TC(signal10);
45501.1SkamilATF_TC_HEAD(signal10, 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_EXIT breakpoint");
45551.1Skamil}
45561.1Skamil
45571.1SkamilATF_TC_BODY(signal10, 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_EXIT;
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_EXIT);
46341.1Skamil
46351.1Skamil	lid = state.pe_lwp;
46361.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT 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.1Skamilstatic void
46541.1Skamillwp_main_stop(void *arg)
46551.1Skamil{
46561.1Skamil	the_lwp_id = _lwp_self();
46571.1Skamil
46581.1Skamil	raise(SIGTRAP);
46591.1Skamil
46601.1Skamil	_lwp_exit();
46611.1Skamil}
46621.1Skamil
46631.1SkamilATF_TC(suspend1);
46641.1SkamilATF_TC_HEAD(suspend1, tc)
46651.1Skamil{
46661.1Skamil	atf_tc_set_md_var(tc, "descr",
46671.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
46681.1Skamil	    "resumed by a tracee");
46691.1Skamil}
46701.1Skamil
46711.1SkamilATF_TC_BODY(suspend1, tc)
46721.1Skamil{
46731.1Skamil	const int exitval = 5;
46741.1Skamil	const int sigval = SIGSTOP;
46751.1Skamil	pid_t child, wpid;
46761.1Skamil#if defined(TWAIT_HAVE_STATUS)
46771.1Skamil	int status;
46781.1Skamil#endif
46791.1Skamil	ucontext_t uc;
46801.1Skamil	lwpid_t lid;
46811.1Skamil	static const size_t ssize = 16*1024;
46821.1Skamil	void *stack;
46831.1Skamil	struct ptrace_lwpinfo pl;
46841.1Skamil	struct ptrace_siginfo psi;
46851.1Skamil	volatile int go = 0;
46861.1Skamil
46871.17Skamil	// Feature pending for refactoring
46881.17Skamil	atf_tc_expect_fail("PR kern/51995");
46891.17Skamil
46901.16Skamil	// Hangs with qemu
46911.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
46921.16Skamil
46931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46951.1Skamil	if (child == 0) {
46961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46981.1Skamil
46991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47011.1Skamil
47021.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
47031.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
47041.1Skamil
47051.13Schristos		DPRINTF("Before making context for new lwp in child\n");
47061.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
47071.1Skamil
47081.13Schristos		DPRINTF("Before creating new in child\n");
47091.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
47101.1Skamil
47111.1Skamil		while (go == 0)
47121.1Skamil			continue;
47131.1Skamil
47141.1Skamil		raise(SIGINT);
47151.1Skamil
47161.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
47171.1Skamil
47181.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
47191.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
47201.1Skamil
47211.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
47221.1Skamil		    "are the same\n", lid, the_lwp_id);
47231.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
47241.1Skamil
47251.13Schristos		DPRINTF("Before exiting of the child process\n");
47261.1Skamil		_exit(exitval);
47271.1Skamil	}
47281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47291.1Skamil
47301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47321.1Skamil
47331.1Skamil	validate_status_stopped(status, sigval);
47341.1Skamil
47351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47361.1Skamil	    "without signal to be sent\n");
47371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47381.1Skamil
47391.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
47401.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
47411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47421.1Skamil
47431.1Skamil	validate_status_stopped(status, SIGTRAP);
47441.1Skamil
47451.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
47461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
47471.1Skamil
47481.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
47491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
47501.1Skamil
47511.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
47521.1Skamil	    child, getpid());
47531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
47541.1Skamil
47551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47561.1Skamil	    "without signal to be sent\n");
47571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47581.1Skamil
47591.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
47601.1Skamil	    "SIGINT\n", TWAIT_FNAME);
47611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47621.1Skamil
47631.1Skamil	validate_status_stopped(status, SIGINT);
47641.1Skamil
47651.1Skamil	pl.pl_lwpid = 0;
47661.1Skamil
47671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
47681.1Skamil	while (pl.pl_lwpid != 0) {
47691.1Skamil
47701.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
47711.1Skamil		switch (pl.pl_lwpid) {
47721.1Skamil		case 1:
47731.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
47741.1Skamil			break;
47751.1Skamil		case 2:
47761.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
47771.1Skamil			break;
47781.1Skamil		}
47791.1Skamil	}
47801.1Skamil
47811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47821.1Skamil	    "without signal to be sent\n");
47831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47841.1Skamil
47851.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
47861.1Skamil	    TWAIT_FNAME);
47871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47881.1Skamil
47891.1Skamil	validate_status_exited(status, exitval);
47901.1Skamil
47911.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
47921.1Skamil	    TWAIT_FNAME);
47931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47941.1Skamil}
47951.1Skamil
47961.1SkamilATF_TC(suspend2);
47971.1SkamilATF_TC_HEAD(suspend2, tc)
47981.1Skamil{
47991.1Skamil	atf_tc_set_md_var(tc, "descr",
48001.1Skamil	    "Verify that the while the only thread within a process is "
48011.1Skamil	    "suspended, the whole process cannot be unstopped");
48021.1Skamil}
48031.1Skamil
48041.1SkamilATF_TC_BODY(suspend2, tc)
48051.1Skamil{
48061.1Skamil	const int exitval = 5;
48071.1Skamil	const int sigval = SIGSTOP;
48081.1Skamil	pid_t child, wpid;
48091.1Skamil#if defined(TWAIT_HAVE_STATUS)
48101.1Skamil	int status;
48111.1Skamil#endif
48121.1Skamil	struct ptrace_siginfo psi;
48131.1Skamil
48141.17Skamil	// Feature pending for refactoring
48151.17Skamil	atf_tc_expect_fail("PR kern/51995");
48161.17Skamil
48171.16Skamil	// Hangs with qemu
48181.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
48191.16Skamil
48201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48221.1Skamil	if (child == 0) {
48231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48251.1Skamil
48261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
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 reading siginfo and lwpid_t\n");
48401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
48411.1Skamil
48421.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
48431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
48441.1Skamil
48451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48461.1Skamil	    "without signal to be sent\n");
48471.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
48481.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
48491.1Skamil
48501.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
48511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
48521.1Skamil
48531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48541.1Skamil	    "without signal to be sent\n");
48551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48561.1Skamil
48571.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48581.1Skamil	    TWAIT_FNAME);
48591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48601.1Skamil
48611.1Skamil	validate_status_exited(status, exitval);
48621.1Skamil
48631.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48641.1Skamil	    TWAIT_FNAME);
48651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48661.1Skamil}
48671.1Skamil
48681.1SkamilATF_TC(resume1);
48691.1SkamilATF_TC_HEAD(resume1, tc)
48701.1Skamil{
48711.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
48721.1Skamil	atf_tc_set_md_var(tc, "descr",
48731.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
48741.1Skamil	    "resumed by the debugger");
48751.1Skamil}
48761.1Skamil
48771.1SkamilATF_TC_BODY(resume1, tc)
48781.1Skamil{
48791.1Skamil	struct msg_fds fds;
48801.1Skamil	const int exitval = 5;
48811.1Skamil	const int sigval = SIGSTOP;
48821.1Skamil	pid_t child, wpid;
48831.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
48841.1Skamil#if defined(TWAIT_HAVE_STATUS)
48851.1Skamil	int status;
48861.1Skamil#endif
48871.1Skamil	ucontext_t uc;
48881.1Skamil	lwpid_t lid;
48891.1Skamil	static const size_t ssize = 16*1024;
48901.1Skamil	void *stack;
48911.1Skamil	struct ptrace_lwpinfo pl;
48921.1Skamil	struct ptrace_siginfo psi;
48931.1Skamil
48941.17Skamil	// Feature pending for refactoring
48951.17Skamil	atf_tc_expect_fail("PR kern/51995");
48961.17Skamil
48971.15Schristos	// Hangs with qemu
48981.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
48991.1Skamil
49001.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
49011.1Skamil
49021.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49031.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49041.1Skamil	if (child == 0) {
49051.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49061.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49071.1Skamil
49081.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49091.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49101.1Skamil
49111.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
49121.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
49131.1Skamil
49141.13Schristos		DPRINTF("Before making context for new lwp in child\n");
49151.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
49161.1Skamil
49171.13Schristos		DPRINTF("Before creating new in child\n");
49181.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
49191.1Skamil
49201.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
49211.1Skamil
49221.1Skamil		raise(SIGINT);
49231.1Skamil
49241.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
49251.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
49261.1Skamil
49271.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
49281.1Skamil		    "are the same\n", lid, the_lwp_id);
49291.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
49301.1Skamil
49311.13Schristos		DPRINTF("Before exiting of the child process\n");
49321.1Skamil		_exit(exitval);
49331.1Skamil	}
49341.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49351.1Skamil
49361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49381.1Skamil
49391.1Skamil	validate_status_stopped(status, sigval);
49401.1Skamil
49411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49421.1Skamil	    "without signal to be sent\n");
49431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49441.1Skamil
49451.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49461.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
49471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49481.1Skamil
49491.1Skamil	validate_status_stopped(status, SIGTRAP);
49501.1Skamil
49511.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
49521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
49531.1Skamil
49541.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
49551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
49561.1Skamil
49571.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
49581.1Skamil
49591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49601.1Skamil	    "without signal to be sent\n");
49611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49621.1Skamil
49631.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49641.1Skamil	    "SIGINT\n", TWAIT_FNAME);
49651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49661.1Skamil
49671.1Skamil	validate_status_stopped(status, SIGINT);
49681.1Skamil
49691.1Skamil	pl.pl_lwpid = 0;
49701.1Skamil
49711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
49721.1Skamil	while (pl.pl_lwpid != 0) {
49731.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
49741.1Skamil		switch (pl.pl_lwpid) {
49751.1Skamil		case 1:
49761.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
49771.1Skamil			break;
49781.1Skamil		case 2:
49791.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
49801.1Skamil			break;
49811.1Skamil		}
49821.1Skamil	}
49831.1Skamil
49841.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
49851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
49861.1Skamil
49871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49881.1Skamil	    "without signal to be sent\n");
49891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49901.1Skamil
49911.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49921.1Skamil	    TWAIT_FNAME);
49931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49941.1Skamil
49951.1Skamil	validate_status_exited(status, exitval);
49961.1Skamil
49971.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49981.1Skamil	    TWAIT_FNAME);
49991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50001.1Skamil
50011.1Skamil	msg_close(&fds);
50021.1Skamil
50031.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
50041.1Skamil	sleep(10);
50051.1Skamil}
50061.1Skamil
50071.1SkamilATF_TC(syscall1);
50081.1SkamilATF_TC_HEAD(syscall1, tc)
50091.1Skamil{
50101.1Skamil	atf_tc_set_md_var(tc, "descr",
50111.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
50121.1Skamil}
50131.1Skamil
50141.1SkamilATF_TC_BODY(syscall1, tc)
50151.1Skamil{
50161.1Skamil	const int exitval = 5;
50171.1Skamil	const int sigval = SIGSTOP;
50181.1Skamil	pid_t child, wpid;
50191.1Skamil#if defined(TWAIT_HAVE_STATUS)
50201.1Skamil	int status;
50211.1Skamil#endif
50221.1Skamil	struct ptrace_siginfo info;
50231.1Skamil	memset(&info, 0, sizeof(info));
50241.1Skamil
50251.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50261.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50271.1Skamil	if (child == 0) {
50281.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50291.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50301.1Skamil
50311.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50321.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50331.1Skamil
50341.1Skamil		syscall(SYS_getpid);
50351.1Skamil
50361.13Schristos		DPRINTF("Before exiting of the child process\n");
50371.1Skamil		_exit(exitval);
50381.1Skamil	}
50391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50401.1Skamil
50411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50431.1Skamil
50441.1Skamil	validate_status_stopped(status, sigval);
50451.1Skamil
50461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50471.1Skamil	    "without signal to be sent\n");
50481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
50491.1Skamil
50501.13Schristos	DPRINTF("Before calling %s() for the child\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 calling ptrace(2) with PT_GET_SIGINFO for child\n");
50561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50571.1Skamil
50581.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
50591.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
50601.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
50611.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
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_SYSCALL, child, (void *)1, 0) != -1);
50661.1Skamil
50671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50691.1Skamil
50701.1Skamil	validate_status_stopped(status, SIGTRAP);
50711.1Skamil
50721.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50741.1Skamil
50751.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
50761.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
50771.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
50781.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
50791.1Skamil
50801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50811.1Skamil	    "without signal to be sent\n");
50821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50831.1Skamil
50841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50861.1Skamil
50871.1Skamil	validate_status_exited(status, exitval);
50881.1Skamil
50891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50911.1Skamil}
50921.1Skamil
50931.1SkamilATF_TC(syscallemu1);
50941.1SkamilATF_TC_HEAD(syscallemu1, tc)
50951.1Skamil{
50961.1Skamil	atf_tc_set_md_var(tc, "descr",
50971.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
50981.1Skamil}
50991.1Skamil
51001.1SkamilATF_TC_BODY(syscallemu1, tc)
51011.1Skamil{
51021.1Skamil	const int exitval = 5;
51031.1Skamil	const int sigval = SIGSTOP;
51041.1Skamil	pid_t child, wpid;
51051.1Skamil#if defined(TWAIT_HAVE_STATUS)
51061.1Skamil	int status;
51071.1Skamil#endif
51081.1Skamil
51091.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
51101.6Skamil	/* syscallemu does not work on sparc (32-bit) */
51111.6Skamil	atf_tc_expect_fail("PR kern/52166");
51121.6Skamil#endif
51131.6Skamil
51141.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51151.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51161.1Skamil	if (child == 0) {
51171.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51181.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51191.1Skamil
51201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51221.1Skamil
51231.1Skamil		syscall(SYS_exit, 100);
51241.1Skamil
51251.13Schristos		DPRINTF("Before exiting of the child process\n");
51261.1Skamil		_exit(exitval);
51271.1Skamil	}
51281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51291.1Skamil
51301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51321.1Skamil
51331.1Skamil	validate_status_stopped(status, sigval);
51341.1Skamil
51351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51361.1Skamil	    "without signal to be sent\n");
51371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51381.1Skamil
51391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51411.1Skamil
51421.1Skamil	validate_status_stopped(status, SIGTRAP);
51431.1Skamil
51441.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
51451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
51461.1Skamil
51471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51481.1Skamil	    "without signal to be sent\n");
51491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51501.1Skamil
51511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51531.1Skamil
51541.1Skamil	validate_status_stopped(status, SIGTRAP);
51551.1Skamil
51561.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51571.1Skamil	    "without signal to be sent\n");
51581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51591.1Skamil
51601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51621.1Skamil
51631.1Skamil	validate_status_exited(status, exitval);
51641.1Skamil
51651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51671.1Skamil}
51681.1Skamil
51691.1Skamil#include "t_ptrace_amd64_wait.h"
51701.1Skamil#include "t_ptrace_i386_wait.h"
51711.1Skamil#include "t_ptrace_x86_wait.h"
51721.1Skamil
51731.1SkamilATF_TP_ADD_TCS(tp)
51741.1Skamil{
51751.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
51761.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
51771.33Skamil
51781.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
51791.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
51801.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
51811.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
51821.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
51831.33Skamil
51841.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
51851.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
51861.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
51871.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
51881.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
51891.59Skamil
51901.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
51911.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
51921.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
51931.50Skamil
51941.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
51951.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
51961.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
51971.50Skamil
51981.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
51991.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
52001.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
52011.50Skamil
52021.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
52031.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
52041.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
52051.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
52061.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
52071.1Skamil
52081.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
52091.37Skamil
52101.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
52111.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
52121.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
52131.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
52141.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
52151.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
52161.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
52171.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
52181.40Skamil
52191.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
52201.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
52211.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
52221.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
52231.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
52241.41Skamil
52251.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
52261.43Skamil
52271.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
52281.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
52291.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
52301.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
52311.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
52321.59Skamil
52331.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
52341.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
52351.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
52361.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
52371.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
52381.51Skamil
52391.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
52401.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
52411.51Skamil
52421.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
52431.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
52441.51Skamil
52451.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
52461.51Skamil		tracee_sees_its_original_parent_getppid);
52471.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
52481.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
52491.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
52501.51Skamil		tracee_sees_its_original_parent_procfs_status);
52511.1Skamil
52521.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
52531.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
52541.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
52551.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
52561.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
52571.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
52581.1Skamil
52591.31Skamil	ATF_TP_ADD_TC(tp, fork1);
52601.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
52611.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
52621.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
52631.31Skamil	ATF_TP_ADD_TC(tp, fork5);
52641.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
52651.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
52661.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
52671.31Skamil
52681.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
52691.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
52701.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
52711.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
52721.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
52731.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
52741.64Smartin// thes tests hang on SMP machines, disable them for now
52751.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
52761.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
52771.1Skamil
52781.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
52791.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
52801.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
52811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
52821.54Skamil
52831.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
52841.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
52851.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
52861.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
52871.54Skamil
52881.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
52891.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
52901.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
52911.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
52921.54Skamil
52931.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
52941.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
52951.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
52961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
52971.54Skamil
52981.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
52991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
53001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
53011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
53021.54Skamil
53031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
53041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
53051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
53061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
53071.54Skamil
53081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
53091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
53101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
53111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
53121.54Skamil
53131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
53141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
53151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
53161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
53171.54Skamil
53181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
53191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
53201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
53211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
53221.54Skamil
53231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
53241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
53251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
53261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
53271.1Skamil
53281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
53291.1Skamil
53301.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
53311.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
53321.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
53331.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
53341.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
53351.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
53361.1Skamil
53371.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
53381.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
53391.1Skamil
53401.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
53411.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
53421.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
53431.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
53441.1Skamil
53451.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
53461.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
53471.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
53481.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
53491.2Skamil
53501.1Skamil	ATF_TP_ADD_TC(tp, kill1);
53511.1Skamil	ATF_TP_ADD_TC(tp, kill2);
53521.75Skamil	ATF_TP_ADD_TC(tp, kill3);
53531.1Skamil
53541.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
53551.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
53561.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
53571.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
53581.77Skamil
53591.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
53601.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
53611.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
53621.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
53631.1Skamil
53641.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
53651.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
53661.79Skamil
53671.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
53681.1Skamil
53691.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
53701.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
53711.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
53721.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
53731.1Skamil
53741.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
53751.84Skamil
53761.1Skamil	ATF_TP_ADD_TC(tp, signal2);
53771.1Skamil	ATF_TP_ADD_TC(tp, signal3);
53781.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
53791.1Skamil	ATF_TP_ADD_TC(tp, signal5);
53801.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
53811.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
53821.1Skamil	ATF_TP_ADD_TC(tp, signal8);
53831.1Skamil	ATF_TP_ADD_TC(tp, signal9);
53841.1Skamil	ATF_TP_ADD_TC(tp, signal10);
53851.1Skamil
53861.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
53871.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
53881.1Skamil
53891.1Skamil	ATF_TP_ADD_TC(tp, resume1);
53901.1Skamil
53911.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
53921.1Skamil
53931.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
53941.1Skamil
53951.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
53961.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
53971.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
53981.1Skamil
53991.1Skamil	return atf_no_error();
54001.1Skamil}
5401