t_ptrace_wait.c revision 1.85
11.85Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.85 2019/02/14 05:38:45 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.85Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.85 2019/02/14 05:38:45 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.77Skamil#include <pthread.h>
471.1Skamil#include <sched.h>
481.1Skamil#include <signal.h>
491.1Skamil#include <stdint.h>
501.1Skamil#include <stdio.h>
511.1Skamil#include <stdlib.h>
521.1Skamil#include <strings.h>
531.26Skamil#include <time.h>
541.1Skamil#include <unistd.h>
551.1Skamil
561.1Skamil#include <atf-c.h>
571.1Skamil
581.1Skamil#include "h_macros.h"
591.1Skamil
601.1Skamil#include "t_ptrace_wait.h"
611.1Skamil#include "msg.h"
621.1Skamil
631.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
641.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
651.61Skre	sizeof(msg)) == 0)
661.1Skamil
671.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
681.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
691.61Skre	sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
721.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
731.61Skre	sizeof(msg)) == 0)
741.1Skamil
751.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
761.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
771.61Skre	sizeof(msg)) == 0)
781.13Schristos
791.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
801.13Schristos    strerror(errno))
811.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
821.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
831.13Schristos
841.13Schristosstatic int debug = 0;
851.13Schristos
861.13Schristos#define DPRINTF(a, ...)	do  \
871.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
881.13Schristos    while (/*CONSTCOND*/0)
891.1Skamil
901.34Skamil/// ----------------------------------------------------------------------------
911.34Skamil
921.33Skamilstatic void
931.33Skamiltraceme_raise(int sigval)
941.1Skamil{
951.1Skamil	const int exitval = 5;
961.1Skamil	pid_t child, wpid;
971.1Skamil#if defined(TWAIT_HAVE_STATUS)
981.1Skamil	int status;
991.1Skamil#endif
1001.1Skamil
1011.45Skamil	struct ptrace_siginfo info;
1021.45Skamil	memset(&info, 0, sizeof(info));
1031.45Skamil
1041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1061.1Skamil	if (child == 0) {
1071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1091.1Skamil
1101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1121.1Skamil
1131.36Skamil		switch (sigval) {
1141.36Skamil		case SIGKILL:
1151.36Skamil			/* NOTREACHED */
1161.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1171.70Smrg			__unreachable();
1181.36Skamil		default:
1191.36Skamil			DPRINTF("Before exiting of the child process\n");
1201.36Skamil			_exit(exitval);
1211.36Skamil		}
1221.1Skamil	}
1231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1241.1Skamil
1251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1271.1Skamil
1281.36Skamil	switch (sigval) {
1291.36Skamil	case SIGKILL:
1301.36Skamil		validate_status_signaled(status, sigval, 0);
1311.36Skamil		break;
1321.36Skamil	default:
1331.36Skamil		validate_status_stopped(status, sigval);
1341.1Skamil
1351.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1361.61Skre			"child\n");
1371.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1381.61Skre			sizeof(info)) != -1);
1391.45Skamil
1401.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1411.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1421.61Skre			"si_errno=%#x\n",
1431.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1441.61Skre			info.psi_siginfo.si_errno);
1451.45Skamil
1461.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1471.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1481.45Skamil
1491.36Skamil		DPRINTF("Before resuming the child process where it left off "
1501.36Skamil		    "and without signal to be sent\n");
1511.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1521.1Skamil
1531.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1541.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1551.61Skre		    child);
1561.36Skamil		break;
1571.36Skamil	}
1581.1Skamil
1591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1611.1Skamil}
1621.1Skamil
1631.61Skre#define TRACEME_RAISE(test, sig)					\
1641.61SkreATF_TC(test);								\
1651.61SkreATF_TC_HEAD(test, tc)							\
1661.61Skre{									\
1671.61Skre	atf_tc_set_md_var(tc, "descr",					\
1681.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1691.61Skre}									\
1701.61Skre									\
1711.61SkreATF_TC_BODY(test, tc)							\
1721.61Skre{									\
1731.61Skre									\
1741.61Skre	traceme_raise(sig);						\
1751.33Skamil}
1761.33Skamil
1771.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1781.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1791.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1801.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1811.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1821.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1831.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1841.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1851.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
1861.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
1871.33Skamil
1881.34Skamil/// ----------------------------------------------------------------------------
1891.1Skamil
1901.1Skamilstatic void
1911.59Skamiltraceme_crash(int sig)
1921.59Skamil{
1931.59Skamil	pid_t child, wpid;
1941.59Skamil#if defined(TWAIT_HAVE_STATUS)
1951.59Skamil	int status;
1961.59Skamil#endif
1971.59Skamil	struct ptrace_siginfo info;
1981.61Skre
1991.71Skamil#ifndef PTRACE_ILLEGAL_ASM
2001.71Skamil	if (sig == SIGILL)
2011.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
2021.71Skamil#endif
2031.71Skamil
2041.59Skamil	memset(&info, 0, sizeof(info));
2051.59Skamil
2061.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2071.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2081.59Skamil	if (child == 0) {
2091.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2101.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2111.59Skamil
2121.59Skamil		DPRINTF("Before executing a trap\n");
2131.59Skamil		switch (sig) {
2141.59Skamil		case SIGTRAP:
2151.59Skamil			trigger_trap();
2161.59Skamil			break;
2171.59Skamil		case SIGSEGV:
2181.59Skamil			trigger_segv();
2191.59Skamil			break;
2201.59Skamil		case SIGILL:
2211.59Skamil			trigger_ill();
2221.59Skamil			break;
2231.59Skamil		case SIGFPE:
2241.59Skamil			trigger_fpe();
2251.59Skamil			break;
2261.59Skamil		case SIGBUS:
2271.59Skamil			trigger_bus();
2281.59Skamil			break;
2291.59Skamil		default:
2301.59Skamil			/* NOTREACHED */
2311.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2321.59Skamil		}
2331.59Skamil
2341.59Skamil		/* NOTREACHED */
2351.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
2361.59Skamil	}
2371.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2381.59Skamil
2391.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2401.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2411.59Skamil
2421.59Skamil	validate_status_stopped(status, sig);
2431.59Skamil
2441.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
2451.61Skre	SYSCALL_REQUIRE(
2461.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2471.59Skamil
2481.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2491.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2501.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2511.61Skre	    info.psi_siginfo.si_errno);
2521.59Skamil
2531.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
2541.59Skamil	switch (sig) {
2551.59Skamil	case SIGTRAP:
2561.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
2571.59Skamil		break;
2581.59Skamil	case SIGSEGV:
2591.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
2601.59Skamil		break;
2611.71Skamil	case SIGILL:
2621.71Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
2631.71Skamil		break;
2641.59Skamil	case SIGFPE:
2651.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
2661.59Skamil		break;
2671.59Skamil	case SIGBUS:
2681.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
2691.59Skamil		break;
2701.59Skamil	}
2711.59Skamil
2721.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
2731.59Skamil
2741.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2751.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2761.59Skamil
2771.59Skamil	validate_status_signaled(status, SIGKILL, 0);
2781.59Skamil
2791.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2801.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2811.59Skamil}
2821.59Skamil
2831.61Skre#define TRACEME_CRASH(test, sig)					\
2841.61SkreATF_TC(test);								\
2851.61SkreATF_TC_HEAD(test, tc)							\
2861.61Skre{									\
2871.61Skre	atf_tc_set_md_var(tc, "descr",					\
2881.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
2891.61Skre}									\
2901.61Skre									\
2911.61SkreATF_TC_BODY(test, tc)							\
2921.61Skre{									\
2931.61Skre									\
2941.61Skre	traceme_crash(sig);						\
2951.59Skamil}
2961.59Skamil
2971.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
2981.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
2991.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
3001.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
3011.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
3021.59Skamil
3031.59Skamil/// ----------------------------------------------------------------------------
3041.59Skamil
3051.59Skamilstatic void
3061.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
3071.1Skamil{
3081.1Skamil	const int exitval = 5;
3091.34Skamil	const int sigval = SIGSTOP;
3101.1Skamil	pid_t child, wpid;
3111.1Skamil	struct sigaction sa;
3121.1Skamil#if defined(TWAIT_HAVE_STATUS)
3131.1Skamil	int status;
3141.1Skamil#endif
3151.61Skre	struct ptrace_siginfo info;
3161.1Skamil
3171.45Skamil	memset(&info, 0, sizeof(info));
3181.45Skamil
3191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
3201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
3211.1Skamil	if (child == 0) {
3221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3241.1Skamil
3251.34Skamil		sa.sa_handler = sah;
3261.1Skamil		sa.sa_flags = SA_SIGINFO;
3271.1Skamil		sigemptyset(&sa.sa_mask);
3281.1Skamil
3291.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
3301.1Skamil
3311.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3321.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3331.1Skamil
3341.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
3351.1Skamil
3361.13Schristos		DPRINTF("Before exiting of the child process\n");
3371.1Skamil		_exit(exitval);
3381.1Skamil	}
3391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3401.1Skamil
3411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3431.1Skamil
3441.1Skamil	validate_status_stopped(status, sigval);
3451.1Skamil
3461.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3471.61Skre	SYSCALL_REQUIRE(
3481.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3491.45Skamil
3501.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3511.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3521.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3531.45Skamil	    info.psi_siginfo.si_errno);
3541.45Skamil
3551.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3561.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3571.45Skamil
3581.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
3591.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
3601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
3611.1Skamil
3621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3641.1Skamil
3651.1Skamil	validate_status_exited(status, exitval);
3661.1Skamil
3671.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3691.1Skamil}
3701.1Skamil
3711.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
3721.61SkreATF_TC(test);								\
3731.61SkreATF_TC_HEAD(test, tc)							\
3741.61Skre{									\
3751.61Skre	atf_tc_set_md_var(tc, "descr",					\
3761.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
3771.61Skre	    "handled correctly and caught by a signal handler");	\
3781.61Skre}									\
3791.61Skre									\
3801.61Skrestatic int test##_caught = 0;						\
3811.61Skre									\
3821.61Skrestatic void								\
3831.61Skretest##_sighandler(int arg)						\
3841.61Skre{									\
3851.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
3861.61Skre									\
3871.61Skre	++ test##_caught;						\
3881.61Skre}									\
3891.61Skre									\
3901.61SkreATF_TC_BODY(test, tc)							\
3911.61Skre{									\
3921.61Skre									\
3931.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
3941.34Skamil}
3951.34Skamil
3961.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
3971.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
3981.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
3991.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
4001.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
4011.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
4021.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
4031.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
4041.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
4051.34Skamil
4061.34Skamil/// ----------------------------------------------------------------------------
4071.34Skamil
4081.35Skamilstatic void
4091.50Skamiltraceme_sendsignal_masked(int sigsent)
4101.50Skamil{
4111.50Skamil	const int exitval = 5;
4121.50Skamil	const int sigval = SIGSTOP;
4131.50Skamil	pid_t child, wpid;
4141.50Skamil	sigset_t set;
4151.50Skamil#if defined(TWAIT_HAVE_STATUS)
4161.50Skamil	int status;
4171.50Skamil#endif
4181.61Skre	struct ptrace_siginfo info;
4191.50Skamil
4201.50Skamil	memset(&info, 0, sizeof(info));
4211.50Skamil
4221.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4231.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4241.50Skamil	if (child == 0) {
4251.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4261.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4271.50Skamil
4281.50Skamil		sigemptyset(&set);
4291.50Skamil		sigaddset(&set, sigsent);
4301.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
4311.50Skamil
4321.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4331.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4341.50Skamil
4351.50Skamil		_exit(exitval);
4361.50Skamil	}
4371.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4381.50Skamil
4391.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4401.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4411.50Skamil
4421.50Skamil	validate_status_stopped(status, sigval);
4431.50Skamil
4441.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4451.61Skre	SYSCALL_REQUIRE(
4461.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4471.50Skamil
4481.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4491.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4501.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4511.50Skamil	    info.psi_siginfo.si_errno);
4521.50Skamil
4531.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4541.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4551.50Skamil
4561.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
4571.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4581.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4591.50Skamil
4601.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4611.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4621.50Skamil
4631.50Skamil	validate_status_exited(status, exitval);
4641.50Skamil
4651.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
4661.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4671.50Skamil}
4681.50Skamil
4691.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
4701.61SkreATF_TC(test);								\
4711.61SkreATF_TC_HEAD(test, tc)							\
4721.61Skre{									\
4731.61Skre	atf_tc_set_md_var(tc, "descr",					\
4741.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
4751.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
4761.61Skre}									\
4771.61Skre									\
4781.61SkreATF_TC_BODY(test, tc)							\
4791.61Skre{									\
4801.61Skre									\
4811.61Skre	traceme_sendsignal_masked(sig);					\
4821.50Skamil}
4831.50Skamil
4841.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4851.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
4861.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
4871.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
4881.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
4891.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
4901.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
4911.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
4921.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
4931.50Skamil
4941.50Skamil/// ----------------------------------------------------------------------------
4951.50Skamil
4961.50Skamilstatic void
4971.50Skamiltraceme_sendsignal_ignored(int sigsent)
4981.50Skamil{
4991.50Skamil	const int exitval = 5;
5001.50Skamil	const int sigval = SIGSTOP;
5011.50Skamil	pid_t child, wpid;
5021.50Skamil	struct sigaction sa;
5031.50Skamil#if defined(TWAIT_HAVE_STATUS)
5041.50Skamil	int status;
5051.50Skamil#endif
5061.61Skre	struct ptrace_siginfo info;
5071.50Skamil
5081.50Skamil	memset(&info, 0, sizeof(info));
5091.50Skamil
5101.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5111.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
5121.50Skamil	if (child == 0) {
5131.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5141.61Skre
5151.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5161.50Skamil
5171.50Skamil		memset(&sa, 0, sizeof(sa));
5181.50Skamil		sa.sa_handler = SIG_IGN;
5191.50Skamil		sigemptyset(&sa.sa_mask);
5201.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
5211.50Skamil
5221.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5231.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5241.50Skamil
5251.50Skamil		_exit(exitval);
5261.50Skamil	}
5271.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5281.50Skamil
5291.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5301.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5311.50Skamil
5321.50Skamil	validate_status_stopped(status, sigval);
5331.50Skamil
5341.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5351.61Skre	SYSCALL_REQUIRE(
5361.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5371.50Skamil
5381.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5391.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5401.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5411.50Skamil	    info.psi_siginfo.si_errno);
5421.50Skamil
5431.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5441.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5451.50Skamil
5461.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
5471.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
5481.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
5491.50Skamil
5501.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5511.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5521.50Skamil
5531.50Skamil	validate_status_exited(status, exitval);
5541.50Skamil
5551.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5561.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5571.50Skamil}
5581.50Skamil
5591.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
5601.61SkreATF_TC(test);								\
5611.61SkreATF_TC_HEAD(test, tc)							\
5621.61Skre{									\
5631.61Skre	atf_tc_set_md_var(tc, "descr",					\
5641.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
5651.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
5661.61Skre}									\
5671.61Skre									\
5681.61SkreATF_TC_BODY(test, tc)							\
5691.61Skre{									\
5701.61Skre									\
5711.61Skre	traceme_sendsignal_ignored(sig);				\
5721.50Skamil}
5731.50Skamil
5741.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
5751.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
5761.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
5771.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
5781.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
5791.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
5801.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
5811.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
5821.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
5831.50Skamil
5841.50Skamil/// ----------------------------------------------------------------------------
5851.50Skamil
5861.50Skamilstatic void
5871.50Skamiltraceme_sendsignal_simple(int sigsent)
5881.1Skamil{
5891.35Skamil	const int sigval = SIGSTOP;
5901.35Skamil	int exitval = 0;
5911.1Skamil	pid_t child, wpid;
5921.1Skamil#if defined(TWAIT_HAVE_STATUS)
5931.1Skamil	int status;
5941.85Skamil	int expect_core;
5951.85Skamil
5961.85Skamil	switch (sigsent) {
5971.85Skamil	case SIGABRT:
5981.85Skamil	case SIGTRAP:
5991.85Skamil	case SIGBUS:
6001.85Skamil	case SIGILL:
6011.85Skamil	case SIGFPE:
6021.85Skamil	case SIGSEGV:
6031.85Skamil		expect_core = 1;
6041.85Skamil		break;
6051.85Skamil	default:
6061.85Skamil		expect_core = 0;
6071.85Skamil		break;
6081.85Skamil	}
6091.1Skamil#endif
6101.61Skre	struct ptrace_siginfo info;
6111.1Skamil
6121.45Skamil	memset(&info, 0, sizeof(info));
6131.45Skamil
6141.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
6151.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
6161.1Skamil	if (child == 0) {
6171.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
6181.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
6191.1Skamil
6201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
6211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
6221.1Skamil
6231.35Skamil		switch (sigsent) {
6241.35Skamil		case SIGCONT:
6251.48Skamil		case SIGSTOP:
6261.35Skamil			_exit(exitval);
6271.35Skamil		default:
6281.35Skamil			/* NOTREACHED */
6291.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
6301.35Skamil		}
6311.1Skamil	}
6321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
6331.1Skamil
6341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6361.1Skamil
6371.1Skamil	validate_status_stopped(status, sigval);
6381.1Skamil
6391.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6401.61Skre	SYSCALL_REQUIRE(
6411.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6421.45Skamil
6431.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6441.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6451.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6461.45Skamil	    info.psi_siginfo.si_errno);
6471.45Skamil
6481.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6491.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6501.45Skamil
6511.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
6521.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
6531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
6541.1Skamil
6551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6571.1Skamil
6581.35Skamil	switch (sigsent) {
6591.48Skamil	case SIGSTOP:
6601.48Skamil		validate_status_stopped(status, sigsent);
6611.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
6621.61Skre		    "child\n");
6631.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
6641.61Skre		    sizeof(info)) != -1);
6651.48Skamil
6661.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6671.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
6681.61Skre		    "si_errno=%#x\n",
6691.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6701.61Skre		    info.psi_siginfo.si_errno);
6711.48Skamil
6721.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6731.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6741.48Skamil
6751.48Skamil		DPRINTF("Before resuming the child process where it left off "
6761.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
6771.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6781.48Skamil
6791.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6801.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
6811.61Skre		    child);
6821.48Skamil		/* FALLTHROUGH */
6831.35Skamil	case SIGCONT:
6841.35Skamil		validate_status_exited(status, exitval);
6851.35Skamil		break;
6861.35Skamil	default:
6871.35Skamil		validate_status_signaled(status, sigsent, expect_core);
6881.35Skamil		break;
6891.35Skamil	}
6901.1Skamil
6911.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
6921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6931.1Skamil}
6941.1Skamil
6951.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
6961.61SkreATF_TC(test);								\
6971.61SkreATF_TC_HEAD(test, tc)							\
6981.61Skre{									\
6991.61Skre	atf_tc_set_md_var(tc, "descr",					\
7001.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
7011.61Skre	    "handled correctly in a child without a signal handler");	\
7021.61Skre}									\
7031.61Skre									\
7041.61SkreATF_TC_BODY(test, tc)							\
7051.61Skre{									\
7061.61Skre									\
7071.61Skre	traceme_sendsignal_simple(sig);					\
7081.35Skamil}
7091.35Skamil
7101.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
7111.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
7121.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
7131.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
7141.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
7151.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
7161.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
7171.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
7181.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
7191.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
7201.35Skamil
7211.35Skamil/// ----------------------------------------------------------------------------
7221.35Skamil
7231.37SkamilATF_TC(traceme_pid1_parent);
7241.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
7251.37Skamil{
7261.37Skamil	atf_tc_set_md_var(tc, "descr",
7271.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
7281.37Skamil}
7291.37Skamil
7301.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
7311.37Skamil{
7321.37Skamil	struct msg_fds parent_child;
7331.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
7341.37Skamil	pid_t child1, child2, wpid;
7351.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7361.37Skamil#if defined(TWAIT_HAVE_STATUS)
7371.37Skamil	int status;
7381.37Skamil#endif
7391.37Skamil
7401.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
7411.37Skamil
7421.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7431.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
7441.37Skamil	if (child1 == 0) {
7451.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
7461.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
7471.37Skamil		if (child2 != 0) {
7481.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
7491.61Skre			    getpid(), child2);
7501.37Skamil			_exit(exitval_child1);
7511.37Skamil		}
7521.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
7531.37Skamil
7541.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
7551.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
7561.37Skamil
7571.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7581.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
7591.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
7601.37Skamil
7611.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
7621.37Skamil
7631.37Skamil		_exit(exitval_child2);
7641.37Skamil	}
7651.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
7661.37Skamil
7671.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7681.61Skre	TWAIT_REQUIRE_SUCCESS(
7691.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
7701.37Skamil
7711.37Skamil	validate_status_exited(status, exitval_child1);
7721.37Skamil
7731.37Skamil	DPRINTF("Notify that child1 is dead\n");
7741.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
7751.37Skamil
7761.37Skamil	DPRINTF("Wait for exiting of child2\n");
7771.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
7781.37Skamil}
7791.37Skamil
7801.37Skamil/// ----------------------------------------------------------------------------
7811.37Skamil
7821.40Skamilstatic void
7831.40Skamiltraceme_vfork_raise(int sigval)
7841.40Skamil{
7851.46Skamil	const int exitval = 5, exitval_watcher = 10;
7861.46Skamil	pid_t child, parent, watcher, wpid;
7871.46Skamil	int rv;
7881.40Skamil#if defined(TWAIT_HAVE_STATUS)
7891.40Skamil	int status;
7901.85Skamil
7911.85Skamil	/* volatile workarounds GCC -Werror=clobbered */
7921.85Skamil	volatile int expect_core;
7931.85Skamil
7941.85Skamil	switch (sigval) {
7951.85Skamil	case SIGABRT:
7961.85Skamil	case SIGTRAP:
7971.85Skamil	case SIGBUS:
7981.85Skamil	case SIGILL:
7991.85Skamil	case SIGFPE:
8001.85Skamil	case SIGSEGV:
8011.85Skamil		expect_core = 1;
8021.85Skamil		break;
8031.85Skamil	default:
8041.85Skamil		expect_core = 0;
8051.85Skamil		break;
8061.85Skamil	}
8071.40Skamil#endif
8081.40Skamil
8091.46Skamil	/*
8101.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
8111.46Skamil	 * the SIGKILL signal to it.
8121.46Skamil	 *
8131.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
8141.46Skamil	 * simpler to reparent this process to initproc and forget about it.
8151.46Skamil	 */
8161.46Skamil	if (sigval == SIGSTOP) {
8171.46Skamil		parent = getpid();
8181.46Skamil
8191.46Skamil		watcher = fork();
8201.46Skamil		ATF_REQUIRE(watcher != 1);
8211.46Skamil		if (watcher == 0) {
8221.46Skamil			/* Double fork(2) trick to reparent to initproc */
8231.46Skamil			watcher = fork();
8241.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
8251.46Skamil			if (watcher != 0)
8261.46Skamil				_exit(exitval_watcher);
8271.46Skamil
8281.46Skamil			child = await_stopped_child(parent);
8291.46Skamil
8301.46Skamil			errno = 0;
8311.46Skamil			rv = kill(child, SIGKILL);
8321.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
8331.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
8341.46Skamil
8351.46Skamil			/* This exit value will be collected by initproc */
8361.46Skamil			_exit(0);
8371.46Skamil		}
8381.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8391.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
8401.61Skre		    watcher);
8411.46Skamil
8421.46Skamil		validate_status_exited(status, exitval_watcher);
8431.46Skamil
8441.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8451.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
8461.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
8471.46Skamil	}
8481.46Skamil
8491.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8501.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
8511.40Skamil	if (child == 0) {
8521.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8531.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8541.40Skamil
8551.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
8561.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
8571.40Skamil
8581.40Skamil		switch (sigval) {
8591.46Skamil		case SIGSTOP:
8601.40Skamil		case SIGKILL:
8611.40Skamil		case SIGABRT:
8621.40Skamil		case SIGHUP:
8631.85Skamil		case SIGTRAP:
8641.85Skamil		case SIGBUS:
8651.85Skamil		case SIGILL:
8661.85Skamil		case SIGFPE:
8671.85Skamil		case SIGSEGV:
8681.40Skamil			/* NOTREACHED */
8691.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
8701.70Smrg			__unreachable();
8711.40Skamil		default:
8721.40Skamil			DPRINTF("Before exiting of the child process\n");
8731.40Skamil			_exit(exitval);
8741.40Skamil		}
8751.40Skamil	}
8761.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8771.40Skamil
8781.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8791.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8801.40Skamil
8811.40Skamil	switch (sigval) {
8821.40Skamil	case SIGKILL:
8831.40Skamil	case SIGABRT:
8841.40Skamil	case SIGHUP:
8851.85Skamil	case SIGTRAP:
8861.85Skamil	case SIGBUS:
8871.85Skamil	case SIGILL:
8881.85Skamil	case SIGFPE:
8891.85Skamil	case SIGSEGV:
8901.40Skamil		validate_status_signaled(status, sigval, expect_core);
8911.40Skamil		break;
8921.40Skamil	case SIGSTOP:
8931.46Skamil		validate_status_signaled(status, SIGKILL, 0);
8941.46Skamil		break;
8951.40Skamil	case SIGCONT:
8961.47Skamil	case SIGTSTP:
8971.47Skamil	case SIGTTIN:
8981.47Skamil	case SIGTTOU:
8991.40Skamil		validate_status_exited(status, exitval);
9001.40Skamil		break;
9011.40Skamil	default:
9021.40Skamil		/* NOTREACHED */
9031.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
9041.40Skamil		break;
9051.40Skamil	}
9061.40Skamil
9071.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9081.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9091.40Skamil}
9101.40Skamil
9111.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
9121.61SkreATF_TC(test);								\
9131.61SkreATF_TC_HEAD(test, tc)							\
9141.61Skre{									\
9151.61Skre	atf_tc_set_md_var(tc, "descr",					\
9161.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
9171.61Skre	    "vfork(2)ed child");					\
9181.61Skre}									\
9191.61Skre									\
9201.61SkreATF_TC_BODY(test, tc)							\
9211.61Skre{									\
9221.61Skre									\
9231.61Skre	traceme_vfork_raise(sig);					\
9241.40Skamil}
9251.40Skamil
9261.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
9271.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
9281.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
9291.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
9301.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
9311.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
9321.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
9331.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
9341.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
9351.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
9361.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
9371.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
9381.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
9391.40Skamil
9401.40Skamil/// ----------------------------------------------------------------------------
9411.40Skamil
9421.52Skamilstatic void
9431.52Skamiltraceme_vfork_crash(int sig)
9441.41Skamil{
9451.41Skamil	pid_t child, wpid;
9461.41Skamil#if defined(TWAIT_HAVE_STATUS)
9471.41Skamil	int status;
9481.41Skamil#endif
9491.41Skamil
9501.71Skamil#ifndef PTRACE_ILLEGAL_ASM
9511.71Skamil	if (sig == SIGILL)
9521.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
9531.71Skamil#endif
9541.71Skamil
9551.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9561.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
9571.41Skamil	if (child == 0) {
9581.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9591.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9601.41Skamil
9611.52Skamil		DPRINTF("Before executing a trap\n");
9621.52Skamil		switch (sig) {
9631.52Skamil		case SIGTRAP:
9641.52Skamil			trigger_trap();
9651.52Skamil			break;
9661.52Skamil		case SIGSEGV:
9671.52Skamil			trigger_segv();
9681.52Skamil			break;
9691.52Skamil		case SIGILL:
9701.52Skamil			trigger_ill();
9711.52Skamil			break;
9721.52Skamil		case SIGFPE:
9731.52Skamil			trigger_fpe();
9741.52Skamil			break;
9751.52Skamil		case SIGBUS:
9761.52Skamil			trigger_bus();
9771.52Skamil			break;
9781.52Skamil		default:
9791.52Skamil			/* NOTREACHED */
9801.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
9811.52Skamil		}
9821.41Skamil
9831.41Skamil		/* NOTREACHED */
9841.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
9851.41Skamil	}
9861.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9871.41Skamil
9881.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9891.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9901.41Skamil
9911.52Skamil	validate_status_signaled(status, sig, 1);
9921.41Skamil
9931.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9941.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9951.41Skamil}
9961.41Skamil
9971.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
9981.61SkreATF_TC(test);								\
9991.61SkreATF_TC_HEAD(test, tc)							\
10001.61Skre{									\
10011.61Skre	atf_tc_set_md_var(tc, "descr",					\
10021.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
10031.61Skre	    "vfork(2)ed child");					\
10041.61Skre}									\
10051.61Skre									\
10061.61SkreATF_TC_BODY(test, tc)							\
10071.61Skre{									\
10081.61Skre									\
10091.61Skre	traceme_vfork_crash(sig);					\
10101.52Skamil}
10111.52Skamil
10121.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
10131.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
10141.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
10151.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
10161.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
10171.52Skamil
10181.41Skamil/// ----------------------------------------------------------------------------
10191.41Skamil
10201.43SkamilATF_TC(traceme_vfork_exec);
10211.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
10221.43Skamil{
10231.43Skamil	atf_tc_set_md_var(tc, "descr",
10241.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
10251.43Skamil}
10261.43Skamil
10271.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
10281.43Skamil{
10291.43Skamil	const int sigval = SIGTRAP;
10301.43Skamil	pid_t child, wpid;
10311.43Skamil#if defined(TWAIT_HAVE_STATUS)
10321.43Skamil	int status;
10331.43Skamil#endif
10341.61Skre	struct ptrace_siginfo info;
10351.43Skamil
10361.43Skamil	memset(&info, 0, sizeof(info));
10371.43Skamil
10381.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
10391.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
10401.43Skamil	if (child == 0) {
10411.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10421.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10431.43Skamil
10441.43Skamil		DPRINTF("Before calling execve(2) from child\n");
10451.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
10461.43Skamil
10471.43Skamil		/* NOTREACHED */
10481.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
10491.43Skamil	}
10501.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10511.43Skamil
10521.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10531.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10541.43Skamil
10551.43Skamil	validate_status_stopped(status, sigval);
10561.43Skamil
10571.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
10581.61Skre	SYSCALL_REQUIRE(
10591.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
10601.43Skamil
10611.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10621.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
10631.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
10641.43Skamil	    info.psi_siginfo.si_errno);
10651.43Skamil
10661.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
10671.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
10681.43Skamil
10691.43Skamil	DPRINTF("Before resuming the child process where it left off and "
10701.43Skamil	    "without signal to be sent\n");
10711.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
10721.43Skamil
10731.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10741.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10751.43Skamil
10761.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10771.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10781.43Skamil}
10791.43Skamil
10801.43Skamil/// ----------------------------------------------------------------------------
10811.43Skamil
10821.1Skamil#if defined(TWAIT_HAVE_PID)
10831.51Skamilstatic void
10841.59Skamilunrelated_tracer_sees_crash(int sig)
10851.59Skamil{
10861.59Skamil	struct msg_fds parent_tracee, parent_tracer;
10871.59Skamil	const int exitval = 10;
10881.59Skamil	pid_t tracee, tracer, wpid;
10891.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10901.59Skamil#if defined(TWAIT_HAVE_STATUS)
10911.59Skamil	int status;
10921.59Skamil#endif
10931.59Skamil	struct ptrace_siginfo info;
10941.61Skre
10951.71Skamil#ifndef PTRACE_ILLEGAL_ASM
10961.71Skamil	if (sig == SIGILL)
10971.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
10981.71Skamil#endif
10991.71Skamil
11001.59Skamil	memset(&info, 0, sizeof(info));
11011.59Skamil
11021.59Skamil	DPRINTF("Spawn tracee\n");
11031.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
11041.59Skamil	tracee = atf_utils_fork();
11051.59Skamil	if (tracee == 0) {
11061.59Skamil		// Wait for parent to let us crash
11071.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
11081.61Skre
11091.59Skamil		DPRINTF("Before executing a trap\n");
11101.59Skamil		switch (sig) {
11111.59Skamil		case SIGTRAP:
11121.59Skamil			trigger_trap();
11131.59Skamil			break;
11141.59Skamil		case SIGSEGV:
11151.59Skamil			trigger_segv();
11161.59Skamil			break;
11171.59Skamil		case SIGILL:
11181.59Skamil			trigger_ill();
11191.59Skamil			break;
11201.59Skamil		case SIGFPE:
11211.59Skamil			trigger_fpe();
11221.59Skamil			break;
11231.59Skamil		case SIGBUS:
11241.59Skamil			trigger_bus();
11251.59Skamil			break;
11261.59Skamil		default:
11271.59Skamil			/* NOTREACHED */
11281.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
11291.59Skamil		}
11301.59Skamil
11311.59Skamil		/* NOTREACHED */
11321.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
11331.59Skamil	}
11341.59Skamil
11351.59Skamil	DPRINTF("Spawn debugger\n");
11361.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
11371.59Skamil	tracer = atf_utils_fork();
11381.59Skamil	if (tracer == 0) {
11391.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
11401.59Skamil		tracer = atf_utils_fork();
11411.59Skamil		if (tracer != 0)
11421.61Skre			_exit(exitval);
11431.59Skamil
11441.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
11451.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
11461.59Skamil
11471.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
11481.59Skamil		FORKEE_REQUIRE_SUCCESS(
11491.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11501.59Skamil
11511.59Skamil		forkee_status_stopped(status, SIGSTOP);
11521.59Skamil
11531.59Skamil		/* Resume tracee with PT_CONTINUE */
11541.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
11551.59Skamil
11561.59Skamil		/* Inform parent that tracer has attached to tracee */
11571.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
11581.59Skamil
11591.59Skamil		/* Wait for parent to tell use that tracee should have exited */
11601.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
11611.59Skamil
11621.59Skamil		/* Wait for tracee and assert that it exited */
11631.59Skamil		FORKEE_REQUIRE_SUCCESS(
11641.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11651.59Skamil
11661.59Skamil		validate_status_stopped(status, sig);
11671.59Skamil
11681.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
11691.61Skre		    "traced process\n");
11701.61Skre		SYSCALL_REQUIRE(
11711.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
11721.59Skamil
11731.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11741.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
11751.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
11761.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
11771.59Skamil
11781.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
11791.59Skamil		switch (sig) {
11801.59Skamil		case SIGTRAP:
11811.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
11821.59Skamil			break;
11831.59Skamil		case SIGSEGV:
11841.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
11851.59Skamil			break;
11861.71Skamil		case SIGILL:
11871.71Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
11881.71Skamil			break;
11891.59Skamil		case SIGFPE:
11901.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
11911.59Skamil			break;
11921.59Skamil		case SIGBUS:
11931.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
11941.59Skamil			break;
11951.59Skamil		}
11961.59Skamil
11971.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
11981.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
11991.61Skre		TWAIT_REQUIRE_SUCCESS(
12001.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12011.59Skamil
12021.59Skamil		validate_status_signaled(status, SIGKILL, 0);
12031.59Skamil
12041.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
12051.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
12061.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
12071.59Skamil
12081.71Skamil		/* Inform parent that tracer is exiting normally */
12091.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
12101.71Skamil
12111.59Skamil		DPRINTF("Before exiting of the tracer process\n");
12121.59Skamil		_exit(0 /* collect by initproc */);
12131.59Skamil	}
12141.59Skamil
12151.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
12161.59Skamil	    "calling %s()\n", TWAIT_FNAME);
12171.59Skamil	TWAIT_REQUIRE_SUCCESS(
12181.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
12191.59Skamil
12201.59Skamil	validate_status_exited(status, exitval);
12211.59Skamil
12221.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
12231.59Skamil	    TWAIT_FNAME);
12241.59Skamil	TWAIT_REQUIRE_SUCCESS(
12251.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
12261.59Skamil
12271.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
12281.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
12291.59Skamil
12301.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
12311.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
12321.59Skamil
12331.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
12341.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
12351.59Skamil
12361.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
12371.59Skamil	    TWAIT_FNAME);
12381.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12391.59Skamil
12401.59Skamil	validate_status_signaled(status, SIGKILL, 0);
12411.59Skamil
12421.71Skamil	DPRINTF("Await normal exit of tracer\n");
12431.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
12441.71Skamil
12451.59Skamil	msg_close(&parent_tracer);
12461.59Skamil	msg_close(&parent_tracee);
12471.59Skamil}
12481.59Skamil
12491.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
12501.61SkreATF_TC(test);								\
12511.61SkreATF_TC_HEAD(test, tc)							\
12521.61Skre{									\
12531.61Skre	atf_tc_set_md_var(tc, "descr",					\
12541.61Skre	    "Assert that an unrelated tracer sees crash signal from the " \
12551.61Skre	    "debuggee");						\
12561.61Skre}									\
12571.61Skre									\
12581.61SkreATF_TC_BODY(test, tc)							\
12591.61Skre{									\
12601.61Skre									\
12611.61Skre	unrelated_tracer_sees_crash(sig);				\
12621.59Skamil}
12631.59Skamil
12641.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
12651.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
12661.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
12671.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
12681.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
12691.59Skamil#endif
12701.59Skamil
12711.59Skamil/// ----------------------------------------------------------------------------
12721.59Skamil
12731.59Skamil#if defined(TWAIT_HAVE_PID)
12741.59Skamilstatic void
12751.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
12761.67Skamil                                             bool stopped)
12771.1Skamil{
12781.51Skamil	/*
12791.51Skamil	 * notimeout - disable timeout in await zombie function
12801.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
12811.67Skamil	 * stopped - attach to a stopped process
12821.51Skamil	 */
12831.1Skamil
12841.1Skamil	struct msg_fds parent_tracee, parent_tracer;
12851.1Skamil	const int exitval_tracee = 5;
12861.1Skamil	const int exitval_tracer = 10;
12871.1Skamil	pid_t tracee, tracer, wpid;
12881.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
12891.1Skamil#if defined(TWAIT_HAVE_STATUS)
12901.1Skamil	int status;
12911.1Skamil#endif
12921.1Skamil
12931.67Skamil	/*
12941.67Skamil	 * Only a subset of options are supported.
12951.67Skamil	 */
12961.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
12971.67Skamil	            (!notimeout && unrelated && !stopped) ||
12981.67Skamil	            (notimeout && !unrelated && !stopped) ||
12991.67Skamil	            (!notimeout && unrelated && stopped));
13001.67Skamil
13011.13Schristos	DPRINTF("Spawn tracee\n");
13021.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
13031.1Skamil	tracee = atf_utils_fork();
13041.1Skamil	if (tracee == 0) {
13051.67Skamil		if (stopped) {
13061.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
13071.67Skamil			raise(SIGSTOP);
13081.67Skamil		}
13091.67Skamil
13101.1Skamil		// Wait for parent to let us exit
13111.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
13121.1Skamil		_exit(exitval_tracee);
13131.1Skamil	}
13141.1Skamil
13151.13Schristos	DPRINTF("Spawn debugger\n");
13161.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
13171.1Skamil	tracer = atf_utils_fork();
13181.1Skamil	if (tracer == 0) {
13191.51Skamil		if(unrelated) {
13201.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
13211.51Skamil			tracer = atf_utils_fork();
13221.51Skamil			if (tracer != 0)
13231.51Skamil				_exit(exitval_tracer);
13241.51Skamil		}
13251.51Skamil
13261.67Skamil		if (stopped) {
13271.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
13281.67Skamil			await_stopped(tracee);
13291.67Skamil		}
13301.67Skamil
13311.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
13321.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
13331.1Skamil
13341.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
13351.1Skamil		FORKEE_REQUIRE_SUCCESS(
13361.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13371.1Skamil
13381.1Skamil		forkee_status_stopped(status, SIGSTOP);
13391.1Skamil
13401.1Skamil		/* Resume tracee with PT_CONTINUE */
13411.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
13421.1Skamil
13431.1Skamil		/* Inform parent that tracer has attached to tracee */
13441.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
13451.1Skamil
13461.1Skamil		/* Wait for parent to tell use that tracee should have exited */
13471.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
13481.1Skamil
13491.1Skamil		/* Wait for tracee and assert that it exited */
13501.1Skamil		FORKEE_REQUIRE_SUCCESS(
13511.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13521.1Skamil
13531.1Skamil		forkee_status_exited(status, exitval_tracee);
13541.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
13551.1Skamil
13561.13Schristos		DPRINTF("Before exiting of the tracer process\n");
13571.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
13581.51Skamil	}
13591.51Skamil
13601.51Skamil	if (unrelated) {
13611.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
13621.51Skamil		    "calling %s()\n", TWAIT_FNAME);
13631.51Skamil		TWAIT_REQUIRE_SUCCESS(
13641.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
13651.51Skamil
13661.51Skamil		validate_status_exited(status, exitval_tracer);
13671.51Skamil
13681.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
13691.51Skamil		    TWAIT_FNAME);
13701.51Skamil		TWAIT_REQUIRE_SUCCESS(
13711.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
13721.1Skamil	}
13731.1Skamil
13741.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
13751.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
13761.1Skamil
13771.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
13781.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
13791.1Skamil
13801.13Schristos	DPRINTF("Detect that tracee is zombie\n");
13811.51Skamil	if (notimeout)
13821.26Skamil		await_zombie_raw(tracee, 0);
13831.26Skamil	else
13841.26Skamil		await_zombie(tracee);
13851.1Skamil
13861.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
13871.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
13881.1Skamil	    TWAIT_FNAME);
13891.1Skamil	TWAIT_REQUIRE_SUCCESS(
13901.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
13911.1Skamil
13921.51Skamil	if (unrelated) {
13931.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
13941.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
13951.51Skamil	} else {
13961.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
13971.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
13981.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
13991.59Skamil			"%s()\n", TWAIT_FNAME);
14001.51Skamil
14011.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
14021.59Skamil			"tracee\n");
14031.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
14041.51Skamil		    tracer);
14051.1Skamil
14061.51Skamil		validate_status_exited(status, exitval_tracer);
14071.51Skamil	}
14081.1Skamil
14091.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
14101.1Skamil	    TWAIT_FNAME);
14111.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14121.1Skamil
14131.1Skamil	validate_status_exited(status, exitval_tracee);
14141.1Skamil
14151.1Skamil	msg_close(&parent_tracer);
14161.1Skamil	msg_close(&parent_tracee);
14171.1Skamil}
14181.26Skamil
14191.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
14201.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
14211.51Skamil{
14221.51Skamil	atf_tc_set_md_var(tc, "descr",
14231.51Skamil	    "Assert that tracer sees process termination before the parent");
14241.51Skamil}
14251.51Skamil
14261.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
14271.26Skamil{
14281.26Skamil
14291.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
14301.26Skamil}
14311.26Skamil
14321.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
14331.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
14341.1Skamil{
14351.1Skamil	atf_tc_set_md_var(tc, "descr",
14361.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
14371.51Skamil	    "process and no other error is reported");
14381.1Skamil}
14391.1Skamil
14401.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
14411.1Skamil{
14421.51Skamil	time_t start, end;
14431.51Skamil	double diff;
14441.51Skamil	unsigned long N = 0;
14451.1Skamil
14461.51Skamil	/*
14471.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
14481.51Skamil	 * This test body isn't specific to this race, however it's just good
14491.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
14501.51Skamil	 */
14511.1Skamil
14521.51Skamil	start = time(NULL);
14531.51Skamil	while (true) {
14541.51Skamil		DPRINTF("Step: %lu\n", N);
14551.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
14561.67Skamil		                                             false);
14571.51Skamil		end = time(NULL);
14581.51Skamil		diff = difftime(end, start);
14591.51Skamil		if (diff >= 5.0)
14601.51Skamil			break;
14611.51Skamil		++N;
14621.1Skamil	}
14631.51Skamil	DPRINTF("Iterations: %lu\n", N);
14641.51Skamil}
14651.1Skamil
14661.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
14671.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
14681.51Skamil{
14691.51Skamil	atf_tc_set_md_var(tc, "descr",
14701.51Skamil	    "Assert that tracer sees process termination before the parent");
14711.51Skamil}
14721.1Skamil
14731.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
14741.51Skamil{
14751.1Skamil
14761.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
14771.67Skamil}
14781.67Skamil
14791.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
14801.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
14811.67Skamil{
14821.67Skamil	atf_tc_set_md_var(tc, "descr",
14831.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
14841.67Skamil}
14851.67Skamil
14861.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
14871.67Skamil{
14881.67Skamil
14891.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
14901.1Skamil}
14911.1Skamil#endif
14921.1Skamil
14931.51Skamil/// ----------------------------------------------------------------------------
14941.51Skamil
14951.66Skamilstatic void
14961.66Skamilparent_attach_to_its_child(bool stopped)
14971.1Skamil{
14981.1Skamil	struct msg_fds parent_tracee;
14991.1Skamil	const int exitval_tracee = 5;
15001.1Skamil	pid_t tracee, wpid;
15011.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15021.1Skamil#if defined(TWAIT_HAVE_STATUS)
15031.1Skamil	int status;
15041.1Skamil#endif
15051.1Skamil
15061.13Schristos	DPRINTF("Spawn tracee\n");
15071.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15081.1Skamil	tracee = atf_utils_fork();
15091.1Skamil	if (tracee == 0) {
15101.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
15111.13Schristos		DPRINTF("Parent should now attach to tracee\n");
15121.1Skamil
15131.66Skamil		if (stopped) {
15141.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
15151.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
15161.66Skamil		}
15171.66Skamil
15181.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
15191.1Skamil		/* Wait for message from the parent */
15201.1Skamil		_exit(exitval_tracee);
15211.1Skamil	}
15221.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
15231.57Skamil
15241.66Skamil	if (stopped) {
15251.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
15261.66Skamil		await_stopped(tracee);
15271.66Skamil	}
15281.66Skamil
15291.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
15301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
15311.1Skamil
15321.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
15331.1Skamil	    TWAIT_FNAME);
15341.1Skamil	TWAIT_REQUIRE_SUCCESS(
15351.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
15361.1Skamil
15371.1Skamil	validate_status_stopped(status, SIGSTOP);
15381.1Skamil
15391.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
15401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
15411.1Skamil
15421.13Schristos	DPRINTF("Let the tracee exit now\n");
15431.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
15441.1Skamil
15451.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
15461.1Skamil	TWAIT_REQUIRE_SUCCESS(
15471.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
15481.1Skamil
15491.1Skamil	validate_status_exited(status, exitval_tracee);
15501.1Skamil
15511.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
15521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
15531.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
15541.1Skamil
15551.1Skamil	msg_close(&parent_tracee);
15561.1Skamil}
15571.1Skamil
15581.66SkamilATF_TC(parent_attach_to_its_child);
15591.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
15601.66Skamil{
15611.66Skamil	atf_tc_set_md_var(tc, "descr",
15621.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
15631.66Skamil}
15641.66Skamil
15651.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
15661.66Skamil{
15671.66Skamil
15681.66Skamil	parent_attach_to_its_child(false);
15691.66Skamil}
15701.66Skamil
15711.66SkamilATF_TC(parent_attach_to_its_stopped_child);
15721.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
15731.66Skamil{
15741.66Skamil	atf_tc_set_md_var(tc, "descr",
15751.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
15761.66Skamil}
15771.66Skamil
15781.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
15791.66Skamil{
15801.66Skamil
15811.66Skamil	parent_attach_to_its_child(true);
15821.66Skamil}
15831.66Skamil
15841.51Skamil/// ----------------------------------------------------------------------------
15851.51Skamil
15861.65Skamilstatic void
15871.65Skamilchild_attach_to_its_parent(bool stopped)
15881.1Skamil{
15891.1Skamil	struct msg_fds parent_tracee;
15901.1Skamil	const int exitval_tracer = 5;
15911.1Skamil	pid_t tracer, wpid;
15921.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15931.1Skamil#if defined(TWAIT_HAVE_STATUS)
15941.1Skamil	int status;
15951.1Skamil#endif
15961.1Skamil
15971.13Schristos	DPRINTF("Spawn tracer\n");
15981.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15991.1Skamil	tracer = atf_utils_fork();
16001.1Skamil	if (tracer == 0) {
16011.1Skamil		/* Wait for message from the parent */
16021.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
16031.1Skamil
16041.65Skamil		if (stopped) {
16051.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
16061.65Skamil			        getppid());
16071.65Skamil			await_stopped(getppid());
16081.65Skamil		}
16091.65Skamil
16101.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
16111.1Skamil		    getppid());
16121.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
16131.1Skamil
16141.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
16151.1Skamil		    TWAIT_FNAME);
16161.1Skamil		FORKEE_REQUIRE_SUCCESS(
16171.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
16181.1Skamil
16191.1Skamil		forkee_status_stopped(status, SIGSTOP);
16201.1Skamil
16211.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
16221.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
16231.1Skamil		    != -1);
16241.1Skamil
16251.1Skamil		/* Tell parent we are ready */
16261.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
16271.1Skamil
16281.1Skamil		_exit(exitval_tracer);
16291.1Skamil	}
16301.1Skamil
16311.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
16321.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
16331.65Skamil
16341.65Skamil	if (stopped) {
16351.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
16361.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
16371.65Skamil	}
16381.65Skamil
16391.13Schristos	DPRINTF("Allow the tracer to exit now\n");
16401.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
16411.1Skamil
16421.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
16431.1Skamil	TWAIT_REQUIRE_SUCCESS(
16441.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
16451.1Skamil
16461.1Skamil	validate_status_exited(status, exitval_tracer);
16471.1Skamil
16481.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
16491.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
16501.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
16511.1Skamil
16521.1Skamil	msg_close(&parent_tracee);
16531.1Skamil}
16541.1Skamil
16551.65SkamilATF_TC(child_attach_to_its_parent);
16561.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
16571.65Skamil{
16581.65Skamil	atf_tc_set_md_var(tc, "descr",
16591.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
16601.65Skamil}
16611.65Skamil
16621.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
16631.65Skamil{
16641.65Skamil
16651.65Skamil	child_attach_to_its_parent(false);
16661.65Skamil}
16671.65Skamil
16681.65SkamilATF_TC(child_attach_to_its_stopped_parent);
16691.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
16701.65Skamil{
16711.65Skamil	atf_tc_set_md_var(tc, "descr",
16721.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
16731.65Skamil}
16741.65Skamil
16751.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
16761.65Skamil{
16771.65Skamil	/*
16781.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
16791.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
16801.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
16811.65Skamil	 *
16821.65Skamil	 * As a workaround spawn this test as a subprocess.
16831.65Skamil	 */
16841.65Skamil
16851.65Skamil	const int exitval = 15;
16861.65Skamil	pid_t child, wpid;
16871.65Skamil#if defined(TWAIT_HAVE_STATUS)
16881.65Skamil	int status;
16891.65Skamil#endif
16901.65Skamil
16911.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
16921.65Skamil	if (child == 0) {
16931.65Skamil		child_attach_to_its_parent(true);
16941.65Skamil		_exit(exitval);
16951.65Skamil	} else {
16961.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16971.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16981.65Skamil
16991.65Skamil		validate_status_exited(status, exitval);
17001.65Skamil
17011.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
17021.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17031.65Skamil	}
17041.65Skamil}
17051.65Skamil
17061.51Skamil/// ----------------------------------------------------------------------------
17071.51Skamil
17081.1Skamil#if defined(TWAIT_HAVE_PID)
17091.1Skamil
17101.51Skamilenum tracee_sees_its_original_parent_type {
17111.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
17121.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
17131.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
17141.51Skamil};
17151.51Skamil
17161.51Skamilstatic void
17171.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
17181.1Skamil{
17191.1Skamil	struct msg_fds parent_tracer, parent_tracee;
17201.1Skamil	const int exitval_tracee = 5;
17211.1Skamil	const int exitval_tracer = 10;
17221.1Skamil	pid_t parent, tracee, tracer, wpid;
17231.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
17241.1Skamil#if defined(TWAIT_HAVE_STATUS)
17251.1Skamil	int status;
17261.1Skamil#endif
17271.51Skamil	/* sysctl(3) - kinfo_proc2 */
17281.51Skamil	int name[CTL_MAXNAME];
17291.51Skamil	struct kinfo_proc2 kp;
17301.51Skamil	size_t len = sizeof(kp);
17311.51Skamil	unsigned int namelen;
17321.51Skamil
17331.51Skamil	/* procfs - status  */
17341.51Skamil	FILE *fp;
17351.51Skamil	struct stat st;
17361.51Skamil	const char *fname = "/proc/curproc/status";
17371.51Skamil	char s_executable[MAXPATHLEN];
17381.51Skamil	int s_pid, s_ppid;
17391.51Skamil	int rv;
17401.51Skamil
17411.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
17421.61Skre		SYSCALL_REQUIRE(
17431.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
17441.61Skre		if (rv != 0)
17451.51Skamil			atf_tc_skip("/proc/curproc/status not found");
17461.51Skamil	}
17471.1Skamil
17481.13Schristos	DPRINTF("Spawn tracee\n");
17491.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
17501.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
17511.1Skamil	tracee = atf_utils_fork();
17521.1Skamil	if (tracee == 0) {
17531.1Skamil		parent = getppid();
17541.1Skamil
17551.1Skamil		/* Emit message to the parent */
17561.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
17571.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
17581.1Skamil
17591.51Skamil		switch (type) {
17601.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
17611.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
17621.51Skamil			break;
17631.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
17641.51Skamil			namelen = 0;
17651.51Skamil			name[namelen++] = CTL_KERN;
17661.51Skamil			name[namelen++] = KERN_PROC2;
17671.51Skamil			name[namelen++] = KERN_PROC_PID;
17681.51Skamil			name[namelen++] = getpid();
17691.51Skamil			name[namelen++] = len;
17701.51Skamil			name[namelen++] = 1;
17711.51Skamil
17721.61Skre			FORKEE_ASSERT_EQ(
17731.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
17741.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
17751.51Skamil			break;
17761.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
17771.51Skamil			/*
17781.51Skamil			 * Format:
17791.51Skamil			 *  EXECUTABLE PID PPID ...
17801.51Skamil			 */
17811.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
17821.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
17831.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
17841.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
17851.51Skamil			break;
17861.51Skamil		}
17871.1Skamil
17881.1Skamil		_exit(exitval_tracee);
17891.1Skamil	}
17901.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
17911.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
17921.1Skamil
17931.13Schristos	DPRINTF("Spawn debugger\n");
17941.1Skamil	tracer = atf_utils_fork();
17951.1Skamil	if (tracer == 0) {
17961.1Skamil		/* No IPC to communicate with the child */
17971.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
17981.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
17991.1Skamil
18001.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
18011.1Skamil		FORKEE_REQUIRE_SUCCESS(
18021.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
18031.1Skamil
18041.1Skamil		forkee_status_stopped(status, SIGSTOP);
18051.1Skamil
18061.1Skamil		/* Resume tracee with PT_CONTINUE */
18071.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
18081.1Skamil
18091.1Skamil		/* Inform parent that tracer has attached to tracee */
18101.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
18111.1Skamil
18121.1Skamil		/* Wait for parent to tell use that tracee should have exited */
18131.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
18141.1Skamil
18151.1Skamil		/* Wait for tracee and assert that it exited */
18161.1Skamil		FORKEE_REQUIRE_SUCCESS(
18171.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
18181.1Skamil
18191.1Skamil		forkee_status_exited(status, exitval_tracee);
18201.1Skamil
18211.13Schristos		DPRINTF("Before exiting of the tracer process\n");
18221.1Skamil		_exit(exitval_tracer);
18231.1Skamil	}
18241.1Skamil
18251.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
18261.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
18271.1Skamil
18281.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
18291.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
18301.1Skamil
18311.13Schristos	DPRINTF("Detect that tracee is zombie\n");
18321.1Skamil	await_zombie(tracee);
18331.1Skamil
18341.13Schristos	DPRINTF("Assert that there is no status about tracee - "
18351.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
18361.1Skamil	TWAIT_REQUIRE_SUCCESS(
18371.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
18381.1Skamil
18391.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
18401.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
18411.1Skamil
18421.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
18431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
18441.1Skamil	    tracer);
18451.1Skamil
18461.1Skamil	validate_status_exited(status, exitval_tracer);
18471.1Skamil
18481.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
18491.1Skamil	    TWAIT_FNAME);
18501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
18511.1Skamil	    tracee);
18521.1Skamil
18531.1Skamil	validate_status_exited(status, exitval_tracee);
18541.1Skamil
18551.1Skamil	msg_close(&parent_tracer);
18561.1Skamil	msg_close(&parent_tracee);
18571.1Skamil}
18581.1Skamil
18591.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
18601.61SkreATF_TC(test);								\
18611.61SkreATF_TC_HEAD(test, tc)							\
18621.61Skre{									\
18631.61Skre	atf_tc_set_md_var(tc, "descr",					\
18641.61Skre	    "Assert that tracee sees its original parent when being traced " \
18651.61Skre	    "(check " descr ")");					\
18661.61Skre}									\
18671.61Skre									\
18681.61SkreATF_TC_BODY(test, tc)							\
18691.61Skre{									\
18701.61Skre									\
18711.61Skre	tracee_sees_its_original_parent(type);				\
18721.1Skamil}
18731.1Skamil
18741.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18751.51Skamil	tracee_sees_its_original_parent_getppid,
18761.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
18771.51Skamil	"getppid(2)");
18781.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18791.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
18801.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
18811.51Skamil	"sysctl(3) and kinfo_proc2");
18821.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18831.51Skamil	tracee_sees_its_original_parent_procfs_status,
18841.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
18851.51Skamil	"the status file in procfs");
18861.1Skamil#endif
18871.1Skamil
18881.51Skamil/// ----------------------------------------------------------------------------
18891.1Skamil
18901.53Skamilstatic void
18911.53Skamileventmask_preserved(int event)
18921.1Skamil{
18931.1Skamil	const int exitval = 5;
18941.1Skamil	const int sigval = SIGSTOP;
18951.1Skamil	pid_t child, wpid;
18961.1Skamil#if defined(TWAIT_HAVE_STATUS)
18971.1Skamil	int status;
18981.1Skamil#endif
18991.1Skamil	ptrace_event_t set_event, get_event;
19001.1Skamil	const int len = sizeof(ptrace_event_t);
19011.1Skamil
19021.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19031.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19041.1Skamil	if (child == 0) {
19051.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19061.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19071.1Skamil
19081.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19091.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19101.1Skamil
19111.13Schristos		DPRINTF("Before exiting of the child process\n");
19121.1Skamil		_exit(exitval);
19131.1Skamil	}
19141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19151.1Skamil
19161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19181.1Skamil
19191.1Skamil	validate_status_stopped(status, sigval);
19201.1Skamil
19211.53Skamil	set_event.pe_set_event = event;
19221.61Skre	SYSCALL_REQUIRE(
19231.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
19241.61Skre	SYSCALL_REQUIRE(
19251.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
19261.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
19271.1Skamil
19281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19291.1Skamil	    "without signal to be sent\n");
19301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19311.1Skamil
19321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19341.1Skamil
19351.1Skamil	validate_status_exited(status, exitval);
19361.1Skamil
19371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19391.1Skamil}
19401.1Skamil
19411.61Skre#define EVENTMASK_PRESERVED(test, event)				\
19421.61SkreATF_TC(test);								\
19431.61SkreATF_TC_HEAD(test, tc)							\
19441.61Skre{									\
19451.61Skre	atf_tc_set_md_var(tc, "descr",					\
19461.61Skre	    "Verify that eventmask " #event " is preserved");		\
19471.61Skre}									\
19481.61Skre									\
19491.61SkreATF_TC_BODY(test, tc)							\
19501.61Skre{									\
19511.61Skre									\
19521.61Skre	eventmask_preserved(event);					\
19531.1Skamil}
19541.1Skamil
19551.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
19561.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
19571.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
19581.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
19591.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
19601.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
19611.1Skamil
19621.53Skamil/// ----------------------------------------------------------------------------
19631.1Skamil
19641.28Skamilstatic void
19651.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
19661.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
19671.1Skamil{
19681.1Skamil	const int exitval = 5;
19691.1Skamil	const int exitval2 = 15;
19701.1Skamil	const int sigval = SIGSTOP;
19711.31Skamil	pid_t child, child2 = 0, wpid;
19721.1Skamil#if defined(TWAIT_HAVE_STATUS)
19731.1Skamil	int status;
19741.1Skamil#endif
19751.1Skamil	ptrace_state_t state;
19761.1Skamil	const int slen = sizeof(state);
19771.1Skamil	ptrace_event_t event;
19781.1Skamil	const int elen = sizeof(event);
19791.1Skamil
19801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19821.1Skamil	if (child == 0) {
19831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19851.1Skamil
19861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19881.1Skamil
19891.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
19901.1Skamil
19911.1Skamil		if (child2 == 0)
19921.1Skamil			_exit(exitval2);
19931.1Skamil
19941.1Skamil		FORKEE_REQUIRE_SUCCESS
19951.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
19961.1Skamil
19971.1Skamil		forkee_status_exited(status, exitval2);
19981.1Skamil
19991.13Schristos		DPRINTF("Before exiting of the child process\n");
20001.1Skamil		_exit(exitval);
20011.1Skamil	}
20021.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20031.1Skamil
20041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20061.1Skamil
20071.1Skamil	validate_status_stopped(status, sigval);
20081.1Skamil
20091.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
20101.61Skre	    trackfork ? "|PTRACE_FORK" : "",
20111.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
20121.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
20131.30Skamil	event.pe_set_event = 0;
20141.30Skamil	if (trackfork)
20151.30Skamil		event.pe_set_event |= PTRACE_FORK;
20161.30Skamil	if (trackvfork)
20171.30Skamil		event.pe_set_event |= PTRACE_VFORK;
20181.30Skamil	if (trackvforkdone)
20191.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
20201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
20211.1Skamil
20221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20231.1Skamil	    "without signal to be sent\n");
20241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20251.1Skamil
20261.29Skamil#if defined(TWAIT_HAVE_PID)
20271.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
20281.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
20291.61Skre		    child);
20301.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
20311.61Skre		    child);
20321.1Skamil
20331.29Skamil		validate_status_stopped(status, SIGTRAP);
20341.1Skamil
20351.61Skre		SYSCALL_REQUIRE(
20361.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
20371.31Skamil		if (trackfork && fn == fork) {
20381.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
20391.30Skamil			       PTRACE_FORK);
20401.30Skamil		}
20411.31Skamil		if (trackvfork && fn == vfork) {
20421.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
20431.30Skamil			       PTRACE_VFORK);
20441.30Skamil		}
20451.29Skamil
20461.29Skamil		child2 = state.pe_other_pid;
20471.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
20481.29Skamil
20491.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
20501.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
20511.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
20521.29Skamil		    child2);
20531.1Skamil
20541.29Skamil		validate_status_stopped(status, SIGTRAP);
20551.1Skamil
20561.61Skre		SYSCALL_REQUIRE(
20571.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
20581.31Skamil		if (trackfork && fn == fork) {
20591.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
20601.30Skamil			       PTRACE_FORK);
20611.30Skamil		}
20621.31Skamil		if (trackvfork && fn == vfork) {
20631.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
20641.30Skamil			       PTRACE_VFORK);
20651.30Skamil		}
20661.30Skamil
20671.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
20681.29Skamil
20691.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
20701.29Skamil		    "and without signal to be sent\n");
20711.61Skre		SYSCALL_REQUIRE(
20721.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
20731.29Skamil
20741.29Skamil		DPRINTF("Before resuming the child process where it left off "
20751.61Skre		    "and without signal to be sent\n");
20761.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20771.30Skamil	}
20781.30Skamil#endif
20791.30Skamil
20801.31Skamil	if (trackvforkdone && fn == vfork) {
20811.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
20821.61Skre		    child);
20831.61Skre		TWAIT_REQUIRE_SUCCESS(
20841.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
20851.30Skamil
20861.30Skamil		validate_status_stopped(status, SIGTRAP);
20871.30Skamil
20881.61Skre		SYSCALL_REQUIRE(
20891.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
20901.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
20911.30Skamil
20921.30Skamil		child2 = state.pe_other_pid;
20931.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
20941.61Skre		    child2);
20951.30Skamil
20961.30Skamil		DPRINTF("Before resuming the child process where it left off "
20971.61Skre		    "and without signal to be sent\n");
20981.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20991.30Skamil	}
21001.29Skamil
21011.30Skamil#if defined(TWAIT_HAVE_PID)
21021.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
21031.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
21041.61Skre		    "\n", TWAIT_FNAME);
21051.61Skre		TWAIT_REQUIRE_SUCCESS(
21061.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
21071.29Skamil
21081.29Skamil		validate_status_exited(status, exitval2);
21091.29Skamil
21101.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
21111.61Skre		    "process\n", TWAIT_FNAME);
21121.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
21131.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
21141.29Skamil	}
21151.29Skamil#endif
21161.1Skamil
21171.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
21181.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
21191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21201.1Skamil
21211.1Skamil	validate_status_stopped(status, SIGCHLD);
21221.1Skamil
21231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21241.1Skamil	    "without signal to be sent\n");
21251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21261.1Skamil
21271.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
21281.1Skamil	    TWAIT_FNAME);
21291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21301.1Skamil
21311.1Skamil	validate_status_exited(status, exitval);
21321.1Skamil
21331.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
21341.1Skamil	    TWAIT_FNAME);
21351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21361.1Skamil}
21371.28Skamil
21381.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
21391.61SkreATF_TC(name);								\
21401.61SkreATF_TC_HEAD(name, tc)							\
21411.61Skre{									\
21421.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
21431.61Skre}									\
21441.61Skre									\
21451.61SkreATF_TC_BODY(name, tc)							\
21461.61Skre{									\
21471.61Skre									\
21481.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
21491.32Skamil}
21501.32Skamil
21511.32Skamil#define F false
21521.32Skamil#define T true
21531.32Skamil
21541.32Skamil#define F_IF__0(x)
21551.32Skamil#define F_IF__1(x) x
21561.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
21571.32Skamil#define F_IF_(x,y) F_IF__(x,y)
21581.32Skamil#define F_IF(x,y) F_IF_(x,y)
21591.32Skamil
21601.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
21611.61Skre	"Verify " #function "(2) called with 0"				\
21621.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
21631.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
21641.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
21651.61Skre	" in EVENT_MASK."						\
21661.61Skre	F_IF(dchildbit," Detach child in this test.")			\
21671.61Skre	F_IF(dparentbit," Detach parent in this test.")
21681.1Skamil
21691.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
21701.31Skamil#if defined(TWAIT_HAVE_PID)
21711.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
21721.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
21731.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
21741.31Skamil#endif
21751.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
21761.31Skamil#if defined(TWAIT_HAVE_PID)
21771.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
21781.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
21791.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
21801.31Skamil#endif
21811.1Skamil
21821.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
21831.31Skamil#if defined(TWAIT_HAVE_PID)
21841.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
21851.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
21861.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
21871.31Skamil#endif
21881.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
21891.31Skamil#if defined(TWAIT_HAVE_PID)
21901.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
21911.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
21921.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
21931.31Skamil#endif
21941.31Skamil
21951.54Skamil/// ----------------------------------------------------------------------------
21961.31Skamil
21971.54Skamilenum bytes_transfer_type {
21981.54Skamil	BYTES_TRANSFER_DATA,
21991.54Skamil	BYTES_TRANSFER_DATAIO,
22001.54Skamil	BYTES_TRANSFER_TEXT,
22011.54Skamil	BYTES_TRANSFER_TEXTIO,
22021.54Skamil	BYTES_TRANSFER_AUXV
22031.54Skamil};
22041.31Skamil
22051.54Skamilstatic int __used
22061.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
22071.54Skamil{
22081.54Skamil	int e, f, g, h;
22091.1Skamil
22101.54Skamil	a *= 4;
22111.54Skamil	b += 3;
22121.54Skamil	c -= 2;
22131.54Skamil	d /= 1;
22141.1Skamil
22151.54Skamil	e = strtol("10", NULL, 10);
22161.54Skamil	f = strtol("20", NULL, 10);
22171.54Skamil	g = strtol("30", NULL, 10);
22181.54Skamil	h = strtol("40", NULL, 10);
22191.1Skamil
22201.54Skamil	return (a + b * c - d) + (e * f - g / h);
22211.1Skamil}
22221.1Skamil
22231.54Skamilstatic void
22241.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
22251.1Skamil{
22261.1Skamil	const int exitval = 5;
22271.1Skamil	const int sigval = SIGSTOP;
22281.1Skamil	pid_t child, wpid;
22291.54Skamil	bool skip = false;
22301.1Skamil
22311.54Skamil	int lookup_me = 0;
22321.54Skamil	uint8_t lookup_me8 = 0;
22331.54Skamil	uint16_t lookup_me16 = 0;
22341.54Skamil	uint32_t lookup_me32 = 0;
22351.54Skamil	uint64_t lookup_me64 = 0;
22361.1Skamil
22371.54Skamil	int magic = 0x13579246;
22381.54Skamil	uint8_t magic8 = 0xab;
22391.54Skamil	uint16_t magic16 = 0x1234;
22401.54Skamil	uint32_t magic32 = 0x98765432;
22411.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
22421.1Skamil
22431.54Skamil	struct ptrace_io_desc io;
22441.1Skamil#if defined(TWAIT_HAVE_STATUS)
22451.1Skamil	int status;
22461.1Skamil#endif
22471.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
22481.60Skre	AuxInfo ai[513], *aip;
22491.55Schristos
22501.55Schristos	ATF_REQUIRE(size < sizeof(ai));
22511.1Skamil
22521.54Skamil	/* Prepare variables for .TEXT transfers */
22531.54Skamil	switch (type) {
22541.54Skamil	case BYTES_TRANSFER_TEXT:
22551.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
22561.54Skamil		break;
22571.54Skamil	case BYTES_TRANSFER_TEXTIO:
22581.54Skamil		switch (size) {
22591.54Skamil		case 8:
22601.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
22611.54Skamil			break;
22621.54Skamil		case 16:
22631.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
22641.54Skamil			break;
22651.54Skamil		case 32:
22661.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
22671.54Skamil			break;
22681.54Skamil		case 64:
22691.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
22701.54Skamil			break;
22711.54Skamil		}
22721.54Skamil		break;
22731.54Skamil	default:
22741.54Skamil		break;
22751.54Skamil	}
22761.1Skamil
22771.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
22781.54Skamil	switch (type) {
22791.54Skamil	case BYTES_TRANSFER_TEXTIO:
22801.54Skamil	case BYTES_TRANSFER_DATAIO:
22811.54Skamil		io.piod_op = operation;
22821.54Skamil		switch (size) {
22831.54Skamil		case 8:
22841.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22851.54Skamil			               (void *)bytes_transfer_dummy :
22861.54Skamil			               &lookup_me8;
22871.54Skamil			io.piod_addr = &lookup_me8;
22881.54Skamil			io.piod_len = sizeof(lookup_me8);
22891.54Skamil			break;
22901.54Skamil		case 16:
22911.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22921.54Skamil			               (void *)bytes_transfer_dummy :
22931.54Skamil			               &lookup_me16;
22941.54Skamil			io.piod_addr = &lookup_me16;
22951.54Skamil			io.piod_len = sizeof(lookup_me16);
22961.54Skamil			break;
22971.54Skamil		case 32:
22981.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22991.54Skamil			               (void *)bytes_transfer_dummy :
23001.54Skamil			               &lookup_me32;
23011.54Skamil			io.piod_addr = &lookup_me32;
23021.54Skamil			io.piod_len = sizeof(lookup_me32);
23031.54Skamil			break;
23041.54Skamil		case 64:
23051.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
23061.54Skamil			               (void *)bytes_transfer_dummy :
23071.54Skamil			               &lookup_me64;
23081.54Skamil			io.piod_addr = &lookup_me64;
23091.54Skamil			io.piod_len = sizeof(lookup_me64);
23101.54Skamil			break;
23111.54Skamil		default:
23121.54Skamil			break;
23131.54Skamil		}
23141.54Skamil		break;
23151.54Skamil	case BYTES_TRANSFER_AUXV:
23161.54Skamil		io.piod_op = operation;
23171.54Skamil		io.piod_offs = 0;
23181.54Skamil		io.piod_addr = ai;
23191.54Skamil		io.piod_len = size;
23201.54Skamil		break;
23211.54Skamil	default:
23221.54Skamil		break;
23231.1Skamil	}
23241.1Skamil
23251.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23261.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23271.1Skamil	if (child == 0) {
23281.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23291.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23301.1Skamil
23311.54Skamil		switch (type) {
23321.54Skamil		case BYTES_TRANSFER_DATA:
23331.54Skamil			switch (operation) {
23341.54Skamil			case PT_READ_D:
23351.54Skamil			case PT_READ_I:
23361.54Skamil				lookup_me = magic;
23371.54Skamil				break;
23381.54Skamil			default:
23391.54Skamil				break;
23401.54Skamil			}
23411.54Skamil			break;
23421.54Skamil		case BYTES_TRANSFER_DATAIO:
23431.54Skamil			switch (operation) {
23441.54Skamil			case PIOD_READ_D:
23451.54Skamil			case PIOD_READ_I:
23461.54Skamil				switch (size) {
23471.54Skamil				case 8:
23481.54Skamil					lookup_me8 = magic8;
23491.54Skamil					break;
23501.54Skamil				case 16:
23511.54Skamil					lookup_me16 = magic16;
23521.54Skamil					break;
23531.54Skamil				case 32:
23541.54Skamil					lookup_me32 = magic32;
23551.54Skamil					break;
23561.54Skamil				case 64:
23571.54Skamil					lookup_me64 = magic64;
23581.54Skamil					break;
23591.54Skamil				default:
23601.54Skamil					break;
23611.54Skamil				}
23621.54Skamil				break;
23631.54Skamil			default:
23641.54Skamil				break;
23651.54Skamil			}
23661.54Skamil		default:
23671.54Skamil			break;
23681.54Skamil		}
23691.54Skamil
23701.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23711.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23721.1Skamil
23731.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
23741.54Skamil		switch (type) {
23751.54Skamil		case BYTES_TRANSFER_DATA:
23761.54Skamil			switch (operation) {
23771.54Skamil			case PT_WRITE_D:
23781.54Skamil			case PT_WRITE_I:
23791.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
23801.54Skamil				break;
23811.54Skamil			default:
23821.54Skamil				break;
23831.54Skamil			}
23841.54Skamil			break;
23851.54Skamil		case BYTES_TRANSFER_DATAIO:
23861.54Skamil			switch (operation) {
23871.54Skamil			case PIOD_WRITE_D:
23881.54Skamil			case PIOD_WRITE_I:
23891.54Skamil				switch (size) {
23901.54Skamil				case 8:
23911.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
23921.54Skamil					break;
23931.54Skamil				case 16:
23941.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
23951.54Skamil					break;
23961.54Skamil				case 32:
23971.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
23981.54Skamil					break;
23991.54Skamil				case 64:
24001.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
24011.54Skamil					break;
24021.54Skamil				default:
24031.54Skamil					break;
24041.54Skamil				}
24051.54Skamil				break;
24061.54Skamil			default:
24071.54Skamil				break;
24081.54Skamil			}
24091.54Skamil			break;
24101.54Skamil		case BYTES_TRANSFER_TEXT:
24111.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
24121.54Skamil			                     sizeof(magic)) == 0);
24131.54Skamil			break;
24141.54Skamil		case BYTES_TRANSFER_TEXTIO:
24151.54Skamil			switch (size) {
24161.54Skamil			case 8:
24171.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
24181.54Skamil				                     bytes_transfer_dummy,
24191.54Skamil				                     sizeof(magic8)) == 0);
24201.54Skamil				break;
24211.54Skamil			case 16:
24221.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
24231.54Skamil				                     bytes_transfer_dummy,
24241.54Skamil				                     sizeof(magic16)) == 0);
24251.54Skamil				break;
24261.54Skamil			case 32:
24271.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
24281.54Skamil				                     bytes_transfer_dummy,
24291.54Skamil				                     sizeof(magic32)) == 0);
24301.54Skamil				break;
24311.54Skamil			case 64:
24321.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
24331.54Skamil				                     bytes_transfer_dummy,
24341.54Skamil				                     sizeof(magic64)) == 0);
24351.54Skamil				break;
24361.54Skamil			}
24371.54Skamil			break;
24381.54Skamil		default:
24391.54Skamil			break;
24401.54Skamil		}
24411.54Skamil
24421.13Schristos		DPRINTF("Before exiting of the child process\n");
24431.1Skamil		_exit(exitval);
24441.1Skamil	}
24451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24461.1Skamil
24471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24491.1Skamil
24501.1Skamil	validate_status_stopped(status, sigval);
24511.1Skamil
24521.54Skamil	/* Check PaX MPROTECT */
24531.54Skamil	if (!can_we_write_to_text(child)) {
24541.54Skamil		switch (type) {
24551.54Skamil		case BYTES_TRANSFER_TEXTIO:
24561.54Skamil			switch (operation) {
24571.54Skamil			case PIOD_WRITE_D:
24581.54Skamil			case PIOD_WRITE_I:
24591.54Skamil				skip = true;
24601.54Skamil				break;
24611.54Skamil			default:
24621.54Skamil				break;
24631.54Skamil			}
24641.54Skamil			break;
24651.54Skamil		case BYTES_TRANSFER_TEXT:
24661.54Skamil			switch (operation) {
24671.54Skamil			case PT_WRITE_D:
24681.54Skamil			case PT_WRITE_I:
24691.54Skamil				skip = true;
24701.54Skamil				break;
24711.54Skamil			default:
24721.54Skamil				break;
24731.54Skamil			}
24741.54Skamil			break;
24751.54Skamil		default:
24761.54Skamil			break;
24771.54Skamil		}
24781.54Skamil	}
24791.1Skamil
24801.54Skamil	/* Bailout cleanly killing the child process */
24811.54Skamil	if (skip) {
24821.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
24831.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24841.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
24851.54Skamil		                      child);
24861.1Skamil
24871.54Skamil		validate_status_signaled(status, SIGKILL, 0);
24881.1Skamil
24891.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
24901.54Skamil	}
24911.1Skamil
24921.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
24931.54Skamil	       "parent=%d\n", child, getpid());
24941.1Skamil
24951.54Skamil	switch (type) {
24961.54Skamil	case BYTES_TRANSFER_TEXTIO:
24971.54Skamil	case BYTES_TRANSFER_DATAIO:
24981.54Skamil	case BYTES_TRANSFER_AUXV:
24991.54Skamil		switch (operation) {
25001.54Skamil		case PIOD_WRITE_D:
25011.54Skamil		case PIOD_WRITE_I:
25021.54Skamil			switch (size) {
25031.54Skamil			case 8:
25041.54Skamil				lookup_me8 = magic8;
25051.54Skamil				break;
25061.54Skamil			case 16:
25071.54Skamil				lookup_me16 = magic16;
25081.54Skamil				break;
25091.54Skamil			case 32:
25101.54Skamil				lookup_me32 = magic32;
25111.54Skamil				break;
25121.54Skamil			case 64:
25131.54Skamil				lookup_me64 = magic64;
25141.54Skamil				break;
25151.54Skamil			default:
25161.54Skamil				break;
25171.54Skamil			}
25181.54Skamil			break;
25191.54Skamil		default:
25201.54Skamil			break;
25211.54Skamil		}
25221.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
25231.54Skamil		switch (operation) {
25241.54Skamil		case PIOD_READ_D:
25251.54Skamil		case PIOD_READ_I:
25261.54Skamil			switch (size) {
25271.54Skamil			case 8:
25281.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
25291.54Skamil				break;
25301.54Skamil			case 16:
25311.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
25321.54Skamil				break;
25331.54Skamil			case 32:
25341.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
25351.54Skamil				break;
25361.54Skamil			case 64:
25371.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
25381.54Skamil				break;
25391.54Skamil			default:
25401.54Skamil				break;
25411.54Skamil			}
25421.54Skamil			break;
25431.54Skamil		case PIOD_READ_AUXV:
25441.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
25451.54Skamil			        io.piod_len);
25461.54Skamil			ATF_REQUIRE(io.piod_len > 0);
25471.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
25481.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
25491.54Skamil				    (long long int)aip->a_type,
25501.54Skamil				    (long long int)aip->a_v);
25511.54Skamil			break;
25521.54Skamil		default:
25531.54Skamil			break;
25541.54Skamil		}
25551.54Skamil		break;
25561.54Skamil	case BYTES_TRANSFER_TEXT:
25571.54Skamil		switch (operation) {
25581.54Skamil		case PT_READ_D:
25591.54Skamil		case PT_READ_I:
25601.54Skamil			errno = 0;
25611.54Skamil			lookup_me = ptrace(operation, child,
25621.54Skamil			                   bytes_transfer_dummy, 0);
25631.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
25641.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
25651.54Skamil			break;
25661.54Skamil		case PT_WRITE_D:
25671.54Skamil		case PT_WRITE_I:
25681.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
25691.54Skamil			                       bytes_transfer_dummy, magic)
25701.54Skamil			                != -1);
25711.54Skamil			break;
25721.54Skamil		default:
25731.54Skamil			break;
25741.54Skamil		}
25751.54Skamil		break;
25761.54Skamil	case BYTES_TRANSFER_DATA:
25771.54Skamil		switch (operation) {
25781.54Skamil		case PT_READ_D:
25791.54Skamil		case PT_READ_I:
25801.54Skamil			errno = 0;
25811.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
25821.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
25831.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
25841.54Skamil			break;
25851.54Skamil		case PT_WRITE_D:
25861.54Skamil		case PT_WRITE_I:
25871.54Skamil			lookup_me = magic;
25881.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
25891.54Skamil			                       magic) != -1);
25901.54Skamil			break;
25911.54Skamil		default:
25921.54Skamil			break;
25931.54Skamil		}
25941.54Skamil		break;
25951.54Skamil	default:
25961.54Skamil		break;
25971.54Skamil	}
25981.1Skamil
25991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26001.1Skamil	    "without signal to be sent\n");
26011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26021.1Skamil
26031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26051.1Skamil
26061.1Skamil	validate_status_exited(status, exitval);
26071.1Skamil
26081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26091.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26101.1Skamil}
26111.1Skamil
26121.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
26131.61SkreATF_TC(test);								\
26141.61SkreATF_TC_HEAD(test, tc)							\
26151.61Skre{									\
26161.61Skre	atf_tc_set_md_var(tc, "descr",					\
26171.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
26181.61Skre	    " of type " #type);						\
26191.61Skre}									\
26201.61Skre									\
26211.61SkreATF_TC_BODY(test, tc)							\
26221.61Skre{									\
26231.61Skre									\
26241.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
26251.1Skamil}
26261.1Skamil
26271.54Skamil// DATA
26281.1Skamil
26291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
26301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
26311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
26321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
26331.54Skamil
26341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
26351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
26361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
26371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
26381.54Skamil
26391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
26401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
26411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
26421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
26431.54Skamil
26441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
26451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
26461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
26471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
26481.54Skamil
26491.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
26501.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
26511.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
26521.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
26531.54Skamil
26541.54Skamil// TEXT
26551.54Skamil
26561.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
26571.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
26581.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
26591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
26601.54Skamil
26611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
26621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
26631.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
26641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
26651.54Skamil
26661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
26671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
26681.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
26691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
26701.54Skamil
26711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
26721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
26731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
26741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
26751.54Skamil
26761.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
26771.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
26781.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
26791.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
26801.1Skamil
26811.54Skamil// AUXV
26821.1Skamil
26831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
26841.1Skamil
26851.54Skamil/// ----------------------------------------------------------------------------
26861.1Skamil
26871.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
26881.72Skamilstatic void
26891.72Skamilaccess_regs(const char *regset, const char *aux)
26901.1Skamil{
26911.1Skamil	const int exitval = 5;
26921.1Skamil	const int sigval = SIGSTOP;
26931.1Skamil	pid_t child, wpid;
26941.1Skamil#if defined(TWAIT_HAVE_STATUS)
26951.1Skamil	int status;
26961.1Skamil#endif
26971.72Skamil#if defined(HAVE_GPREGS)
26981.72Skamil	struct reg gpr;
26991.76Sscole	register_t rgstr;
27001.1Skamil#endif
27011.72Skamil#if defined(HAVE_FPREGS)
27021.72Skamil	struct fpreg fpr;
27031.1Skamil#endif
27041.76Sscole
27051.72Skamil#if !defined(HAVE_GPREGS)
27061.72Skamil	if (strcmp(regset, "regs") == 0)
27071.72Skamil		atf_tc_fail("Impossible test scenario!");
27081.1Skamil#endif
27091.1Skamil
27101.72Skamil#if !defined(HAVE_FPREGS)
27111.72Skamil	if (strcmp(regset, "fpregs") == 0)
27121.72Skamil		atf_tc_fail("Impossible test scenario!");
27131.1Skamil#endif
27141.1Skamil
27151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27171.1Skamil	if (child == 0) {
27181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27201.1Skamil
27211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27231.1Skamil
27241.13Schristos		DPRINTF("Before exiting of the child process\n");
27251.1Skamil		_exit(exitval);
27261.1Skamil	}
27271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27281.1Skamil
27291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27311.1Skamil
27321.1Skamil	validate_status_stopped(status, sigval);
27331.1Skamil
27341.1Skamil#if defined(HAVE_GPREGS)
27351.72Skamil	if (strcmp(regset, "regs") == 0) {
27361.72Skamil		DPRINTF("Call GETREGS for the child process\n");
27371.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
27381.72Skamil
27391.72Skamil		if (strcmp(aux, "none") == 0) {
27401.72Skamil			DPRINTF("Retrieved registers\n");
27411.72Skamil		} else if (strcmp(aux, "pc") == 0) {
27421.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
27431.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
27441.72Skamil		} else if (strcmp(aux, "set_pc") == 0) {
27451.72Skamil			rgstr = PTRACE_REG_PC(&gpr);
27461.72Skamil			PTRACE_REG_SET_PC(&gpr, rgstr);
27471.72Skamil		} else if (strcmp(aux, "sp") == 0) {
27481.72Skamil			rgstr = PTRACE_REG_SP(&gpr);
27491.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
27501.72Skamil		} else if (strcmp(aux, "intrv") == 0) {
27511.72Skamil			rgstr = PTRACE_REG_INTRV(&gpr);
27521.72Skamil			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
27531.72Skamil		} else if (strcmp(aux, "setregs") == 0) {
27541.72Skamil			DPRINTF("Call SETREGS for the child process\n");
27551.72Skamil			SYSCALL_REQUIRE(
27561.72Skamil			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
27571.72Skamil		}
27581.72Skamil	}
27591.1Skamil#endif
27601.1Skamil
27611.72Skamil#if defined(HAVE_FPREGS)
27621.72Skamil	if (strcmp(regset, "fpregs") == 0) {
27631.72Skamil		DPRINTF("Call GETFPREGS for the child process\n");
27641.72Skamil		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
27651.72Skamil
27661.72Skamil		if (strcmp(aux, "getfpregs") == 0) {
27671.72Skamil			DPRINTF("Retrieved FP registers\n");
27681.72Skamil		} else if (strcmp(aux, "setfpregs") == 0) {
27691.72Skamil			DPRINTF("Call SETFPREGS for the child\n");
27701.72Skamil			SYSCALL_REQUIRE(
27711.72Skamil			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
27721.72Skamil		}
27731.1Skamil	}
27741.1Skamil#endif
27751.1Skamil
27761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27771.1Skamil	    "without signal to be sent\n");
27781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27791.1Skamil
27801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27821.1Skamil
27831.1Skamil	validate_status_exited(status, exitval);
27841.1Skamil
27851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27871.1Skamil}
27881.1Skamil
27891.72Skamil#define ACCESS_REGS(test, regset, aux)					\
27901.72SkamilATF_TC(test);								\
27911.72SkamilATF_TC_HEAD(test, tc)							\
27921.72Skamil{									\
27931.72Skamil        atf_tc_set_md_var(tc, "descr",					\
27941.72Skamil            "Verify " regset " with auxiliary operation: " aux);	\
27951.72Skamil}									\
27961.72Skamil									\
27971.72SkamilATF_TC_BODY(test, tc)							\
27981.72Skamil{									\
27991.72Skamil									\
28001.72Skamil        access_regs(regset, aux);					\
28011.1Skamil}
28021.1Skamil#endif
28031.1Skamil
28041.72Skamil#if defined(HAVE_GPREGS)
28051.72SkamilACCESS_REGS(access_regs1, "regs", "none")
28061.72SkamilACCESS_REGS(access_regs2, "regs", "pc")
28071.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc")
28081.72SkamilACCESS_REGS(access_regs4, "regs", "sp")
28091.72SkamilACCESS_REGS(access_regs5, "regs", "intrv")
28101.72SkamilACCESS_REGS(access_regs6, "regs", "setregs")
28111.1Skamil#endif
28121.1Skamil#if defined(HAVE_FPREGS)
28131.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
28141.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
28151.1Skamil#endif
28161.1Skamil
28171.72Skamil/// ----------------------------------------------------------------------------
28181.1Skamil
28191.1Skamil#if defined(PT_STEP)
28201.1Skamilstatic void
28211.2Skamilptrace_step(int N, int setstep)
28221.1Skamil{
28231.1Skamil	const int exitval = 5;
28241.1Skamil	const int sigval = SIGSTOP;
28251.1Skamil	pid_t child, wpid;
28261.1Skamil#if defined(TWAIT_HAVE_STATUS)
28271.1Skamil	int status;
28281.1Skamil#endif
28291.1Skamil	int happy;
28301.81Skamil	struct ptrace_siginfo info;
28311.1Skamil
28321.1Skamil#if defined(__arm__)
28331.1Skamil	/* PT_STEP not supported on arm 32-bit */
28341.1Skamil	atf_tc_expect_fail("PR kern/52119");
28351.1Skamil#endif
28361.1Skamil
28371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28391.1Skamil	if (child == 0) {
28401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28421.1Skamil
28431.1Skamil		happy = check_happy(999);
28441.1Skamil
28451.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28461.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28471.1Skamil
28481.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
28491.1Skamil
28501.13Schristos		DPRINTF("Before exiting of the child process\n");
28511.1Skamil		_exit(exitval);
28521.1Skamil	}
28531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28541.1Skamil
28551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28571.1Skamil
28581.1Skamil	validate_status_stopped(status, sigval);
28591.1Skamil
28601.81Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
28611.81Skamil	SYSCALL_REQUIRE(
28621.81Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
28631.81Skamil
28641.81Skamil	DPRINTF("Before checking siginfo_t\n");
28651.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
28661.81Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
28671.81Skamil
28681.1Skamil	while (N --> 0) {
28691.2Skamil		if (setstep) {
28701.13Schristos			DPRINTF("Before resuming the child process where it "
28711.2Skamil			    "left off and without signal to be sent (use "
28721.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
28731.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
28741.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
28751.2Skamil			    != -1);
28761.2Skamil		} else {
28771.13Schristos			DPRINTF("Before resuming the child process where it "
28781.2Skamil			    "left off and without signal to be sent (use "
28791.2Skamil			    "PT_STEP)\n");
28801.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
28811.2Skamil			    != -1);
28821.2Skamil		}
28831.1Skamil
28841.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28851.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
28861.1Skamil		    child);
28871.1Skamil
28881.1Skamil		validate_status_stopped(status, SIGTRAP);
28891.2Skamil
28901.81Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
28911.81Skamil		SYSCALL_REQUIRE(
28921.81Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
28931.81Skamil
28941.81Skamil		DPRINTF("Before checking siginfo_t\n");
28951.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
28961.81Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
28971.81Skamil
28981.2Skamil		if (setstep) {
28991.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
29001.2Skamil		}
29011.1Skamil	}
29021.1Skamil
29031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29041.1Skamil	    "without signal to be sent\n");
29051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29061.1Skamil
29071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29091.1Skamil
29101.1Skamil	validate_status_exited(status, exitval);
29111.1Skamil
29121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29141.1Skamil}
29151.1Skamil
29161.73Skamil#define PTRACE_STEP(test, N, setstep)					\
29171.73SkamilATF_TC(test);								\
29181.73SkamilATF_TC_HEAD(test, tc)							\
29191.73Skamil{									\
29201.73Skamil        atf_tc_set_md_var(tc, "descr",					\
29211.74Skamil            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
29221.73Skamil}									\
29231.73Skamil									\
29241.73SkamilATF_TC_BODY(test, tc)							\
29251.73Skamil{									\
29261.73Skamil									\
29271.73Skamil        ptrace_step(N, setstep);					\
29281.1Skamil}
29291.1Skamil
29301.73SkamilPTRACE_STEP(step1, 1, 0)
29311.73SkamilPTRACE_STEP(step2, 2, 0)
29321.73SkamilPTRACE_STEP(step3, 3, 0)
29331.73SkamilPTRACE_STEP(step4, 4, 0)
29341.73SkamilPTRACE_STEP(setstep1, 1, 1)
29351.73SkamilPTRACE_STEP(setstep2, 2, 1)
29361.73SkamilPTRACE_STEP(setstep3, 3, 1)
29371.73SkamilPTRACE_STEP(setstep4, 4, 1)
29381.1Skamil#endif
29391.1Skamil
29401.73Skamil/// ----------------------------------------------------------------------------
29411.1Skamil
29421.75Skamilstatic void
29431.75Skamilptrace_kill(const char *type)
29441.1Skamil{
29451.75Skamil	const int sigval = SIGSTOP;
29461.1Skamil	pid_t child, wpid;
29471.1Skamil#if defined(TWAIT_HAVE_STATUS)
29481.1Skamil	int status;
29491.1Skamil#endif
29501.1Skamil
29511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29531.1Skamil	if (child == 0) {
29541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29561.1Skamil
29571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29591.1Skamil
29601.1Skamil		/* NOTREACHED */
29611.1Skamil		FORKEE_ASSERTX(0 &&
29621.1Skamil		    "Child should be terminated by a signal from its parent");
29631.1Skamil	}
29641.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29651.1Skamil
29661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29681.1Skamil
29691.1Skamil	validate_status_stopped(status, sigval);
29701.1Skamil
29711.75Skamil	DPRINTF("Before killing the child process with %s\n", type);
29721.75Skamil	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
29731.75Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
29741.75Skamil	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
29751.75Skamil		kill(child, SIGKILL);
29761.75Skamil	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
29771.75Skamil		setpgid(child, 0);
29781.75Skamil		killpg(getpgid(child), SIGKILL);
29791.75Skamil	}
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.75Skamil	validate_status_signaled(status, SIGKILL, 0);
29851.1Skamil
29861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29881.1Skamil}
29891.1Skamil
29901.75Skamil#define PTRACE_KILL(test, type)						\
29911.75SkamilATF_TC(test);								\
29921.75SkamilATF_TC_HEAD(test, tc)							\
29931.75Skamil{									\
29941.75Skamil        atf_tc_set_md_var(tc, "descr",					\
29951.75Skamil            "Verify killing the child with " type);			\
29961.75Skamil}									\
29971.75Skamil									\
29981.75SkamilATF_TC_BODY(test, tc)							\
29991.75Skamil{									\
30001.75Skamil									\
30011.75Skamil        ptrace_kill(type);						\
30021.1Skamil}
30031.1Skamil
30041.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
30051.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)")
30061.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)")
30071.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)")
30081.1Skamil
30091.75Skamil/// ----------------------------------------------------------------------------
30101.1Skamil
30111.77Skamilstatic void
30121.77Skamiltraceme_lwpinfo(const int threads)
30131.1Skamil{
30141.1Skamil	const int sigval = SIGSTOP;
30151.77Skamil	const int sigval2 = SIGINT;
30161.1Skamil	pid_t child, wpid;
30171.1Skamil#if defined(TWAIT_HAVE_STATUS)
30181.1Skamil	int status;
30191.1Skamil#endif
30201.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
30211.77Skamil	struct ptrace_siginfo info;
30221.77Skamil
30231.77Skamil	/* Maximum number of supported threads in this test */
30241.77Skamil	pthread_t t[3];
30251.77Skamil	int n, rv;
30261.77Skamil
30271.77Skamil	ATF_REQUIRE((int)__arraycount(t) >= threads);
30281.1Skamil
30291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30311.1Skamil	if (child == 0) {
30321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30341.1Skamil
30351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30371.1Skamil
30381.77Skamil		for (n = 0; n < threads; n++) {
30391.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
30401.77Skamil			FORKEE_ASSERT(rv == 0);
30411.77Skamil		}
30421.77Skamil
30431.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
30441.77Skamil		FORKEE_ASSERT(raise(sigval2) == 0);
30451.77Skamil
30461.77Skamil		/* NOTREACHED */
30471.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
30481.1Skamil	}
30491.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30501.1Skamil
30511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30531.1Skamil
30541.1Skamil	validate_status_stopped(status, sigval);
30551.1Skamil
30561.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
30571.77Skamil	SYSCALL_REQUIRE(
30581.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
30591.77Skamil
30601.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
30611.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
30621.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
30631.77Skamil	    info.psi_siginfo.si_errno);
30641.77Skamil
30651.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
30661.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
30671.77Skamil
30681.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
30691.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
30701.1Skamil
30711.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
30721.77Skamil	ATF_REQUIRE(lwp.pl_lwpid > 0);
30731.1Skamil
30741.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
30751.77Skamil	    lwp.pl_lwpid);
30761.77Skamil	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
30771.1Skamil
30781.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
30791.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
30801.1Skamil
30811.77Skamil	DPRINTF("Assert that there exists a single thread only\n");
30821.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
30831.1Skamil
30841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30851.1Skamil	    "without signal to be sent\n");
30861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30871.1Skamil
30881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30901.1Skamil
30911.77Skamil	validate_status_stopped(status, sigval2);
30921.77Skamil
30931.77Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
30941.77Skamil	SYSCALL_REQUIRE(
30951.77Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
30961.77Skamil
30971.77Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
30981.77Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
30991.77Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
31001.77Skamil	    info.psi_siginfo.si_errno);
31011.77Skamil
31021.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
31031.77Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
31041.77Skamil
31051.77Skamil	memset(&lwp, 0, sizeof(lwp));
31061.77Skamil
31071.77Skamil	for (n = 0; n <= threads; n++) {
31081.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
31091.77Skamil		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
31101.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
31111.77Skamil
31121.77Skamil		DPRINTF("Assert that the thread exists\n");
31131.77Skamil		ATF_REQUIRE(lwp.pl_lwpid > 0);
31141.77Skamil
31151.77Skamil		DPRINTF("Assert that lwp thread %d received expected event\n",
31161.77Skamil		    lwp.pl_lwpid);
31171.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
31181.77Skamil		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
31191.77Skamil	}
31201.77Skamil	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
31211.77Skamil	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
31221.77Skamil	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
31231.77Skamil
31241.77Skamil	DPRINTF("Assert that there are no more threads\n");
31251.77Skamil	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
31261.77Skamil
31271.77Skamil	DPRINTF("Before resuming the child process where it left off and "
31281.77Skamil	    "without signal to be sent\n");
31291.77Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
31301.77Skamil
31311.77Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31321.77Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31331.77Skamil
31341.77Skamil	validate_status_signaled(status, SIGKILL, 0);
31351.1Skamil
31361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31381.1Skamil}
31391.1Skamil
31401.77Skamil#define TRACEME_LWPINFO(test, threads)					\
31411.77SkamilATF_TC(test);								\
31421.77SkamilATF_TC_HEAD(test, tc)							\
31431.77Skamil{									\
31441.77Skamil	atf_tc_set_md_var(tc, "descr",					\
31451.77Skamil	    "Verify LWPINFO with the child with " #threads		\
31461.77Skamil	    " spawned extra threads");					\
31471.77Skamil}									\
31481.77Skamil									\
31491.77SkamilATF_TC_BODY(test, tc)							\
31501.77Skamil{									\
31511.77Skamil									\
31521.77Skamil	traceme_lwpinfo(threads);					\
31531.1Skamil}
31541.1Skamil
31551.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0)
31561.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1)
31571.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2)
31581.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3)
31591.77Skamil
31601.77Skamil/// ----------------------------------------------------------------------------
31611.77Skamil
31621.77Skamil#if defined(TWAIT_HAVE_PID)
31631.77Skamilstatic void
31641.77Skamilattach_lwpinfo(const int threads)
31651.1Skamil{
31661.77Skamil	const int sigval = SIGINT;
31671.1Skamil	struct msg_fds parent_tracee, parent_tracer;
31681.1Skamil	const int exitval_tracer = 10;
31691.1Skamil	pid_t tracee, tracer, wpid;
31701.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
31711.1Skamil#if defined(TWAIT_HAVE_STATUS)
31721.1Skamil	int status;
31731.1Skamil#endif
31741.77Skamil	struct ptrace_lwpinfo lwp = {0, 0};
31751.77Skamil	struct ptrace_siginfo info;
31761.77Skamil
31771.77Skamil	/* Maximum number of supported threads in this test */
31781.77Skamil	pthread_t t[3];
31791.77Skamil	int n, rv;
31801.1Skamil
31811.13Schristos	DPRINTF("Spawn tracee\n");
31821.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
31831.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
31841.1Skamil	tracee = atf_utils_fork();
31851.1Skamil	if (tracee == 0) {
31861.1Skamil		/* Wait for message from the parent */
31871.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
31881.1Skamil
31891.77Skamil		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
31901.77Skamil
31911.77Skamil		for (n = 0; n < threads; n++) {
31921.77Skamil			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
31931.77Skamil			FORKEE_ASSERT(rv == 0);
31941.77Skamil		}
31951.77Skamil
31961.77Skamil		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
31971.77Skamil
31981.77Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31991.77Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32001.77Skamil
32011.77Skamil		/* NOTREACHED */
32021.77Skamil		FORKEE_ASSERTX(0 && "Not reached");
32031.1Skamil	}
32041.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
32051.1Skamil
32061.13Schristos	DPRINTF("Spawn debugger\n");
32071.1Skamil	tracer = atf_utils_fork();
32081.1Skamil	if (tracer == 0) {
32091.1Skamil		/* No IPC to communicate with the child */
32101.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
32111.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
32121.1Skamil
32131.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
32141.1Skamil		FORKEE_REQUIRE_SUCCESS(
32151.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
32161.1Skamil
32171.1Skamil		forkee_status_stopped(status, SIGSTOP);
32181.1Skamil
32191.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
32201.77Skamil		    "tracee");
32211.77Skamil		FORKEE_ASSERT(
32221.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
32231.77Skamil
32241.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
32251.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
32261.77Skamil		    "si_errno=%#x\n",
32271.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
32281.77Skamil		    info.psi_siginfo.si_errno);
32291.77Skamil
32301.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
32311.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
32321.77Skamil
32331.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
32341.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
32351.1Skamil		    != -1);
32361.1Skamil
32371.13Schristos		DPRINTF("Assert that there exists a thread\n");
32381.77Skamil		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
32391.1Skamil
32401.13Schristos		DPRINTF("Assert that lwp thread %d received event "
32411.77Skamil		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
32421.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
32431.1Skamil
32441.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
32451.77Skamil		    "tracee\n");
32461.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
32471.1Skamil		    != -1);
32481.1Skamil
32491.77Skamil		DPRINTF("Assert that there are no more lwp threads in "
32501.77Skamil		    "tracee\n");
32511.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
32521.1Skamil
32531.1Skamil		/* Resume tracee with PT_CONTINUE */
32541.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
32551.1Skamil
32561.1Skamil		/* Inform parent that tracer has attached to tracee */
32571.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
32581.77Skamil
32591.1Skamil		/* Wait for parent */
32601.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
32611.1Skamil
32621.77Skamil		/* Wait for tracee and assert that it raised a signal */
32631.77Skamil		FORKEE_REQUIRE_SUCCESS(
32641.77Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
32651.77Skamil
32661.77Skamil		forkee_status_stopped(status, SIGINT);
32671.77Skamil
32681.77Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
32691.77Skamil		    "child");
32701.77Skamil		FORKEE_ASSERT(
32711.77Skamil		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
32721.77Skamil
32731.77Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
32741.77Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
32751.77Skamil		    "si_errno=%#x\n",
32761.77Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
32771.77Skamil		    info.psi_siginfo.si_errno);
32781.77Skamil
32791.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
32801.77Skamil		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
32811.77Skamil
32821.77Skamil		memset(&lwp, 0, sizeof(lwp));
32831.77Skamil
32841.77Skamil		for (n = 0; n <= threads; n++) {
32851.77Skamil			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
32861.77Skamil			    "child\n");
32871.77Skamil			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
32881.77Skamil			    sizeof(lwp)) != -1);
32891.77Skamil			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
32901.77Skamil
32911.77Skamil			DPRINTF("Assert that the thread exists\n");
32921.77Skamil			FORKEE_ASSERT(lwp.pl_lwpid > 0);
32931.77Skamil
32941.77Skamil			DPRINTF("Assert that lwp thread %d received expected "
32951.77Skamil			    "event\n", lwp.pl_lwpid);
32961.77Skamil			FORKEE_ASSERT_EQ(lwp.pl_event,
32971.77Skamil			    info.psi_lwpid == lwp.pl_lwpid ?
32981.77Skamil			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
32991.77Skamil		}
33001.77Skamil		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
33011.77Skamil		    "tracee\n");
33021.77Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
33031.77Skamil		    != -1);
33041.77Skamil		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
33051.77Skamil
33061.77Skamil		DPRINTF("Assert that there are no more threads\n");
33071.77Skamil		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
33081.77Skamil
33091.77Skamil		DPRINTF("Before resuming the child process where it left off "
33101.77Skamil		    "and without signal to be sent\n");
33111.77Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
33121.77Skamil		    != -1);
33131.77Skamil
33141.1Skamil		/* Wait for tracee and assert that it exited */
33151.1Skamil		FORKEE_REQUIRE_SUCCESS(
33161.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
33171.1Skamil
33181.77Skamil		forkee_status_signaled(status, SIGKILL, 0);
33191.1Skamil
33201.13Schristos		DPRINTF("Before exiting of the tracer process\n");
33211.1Skamil		_exit(exitval_tracer);
33221.1Skamil	}
33231.1Skamil
33241.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
33251.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
33261.1Skamil
33271.77Skamil	DPRINTF("Resume the tracee and spawn threads\n");
33281.77Skamil	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
33291.77Skamil
33301.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
33311.77Skamil	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
33321.1Skamil
33331.77Skamil	DPRINTF("Resume the tracer and let it detect multiple threads\n");
33341.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
33351.1Skamil
33361.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
33371.1Skamil	    TWAIT_FNAME);
33381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
33391.1Skamil	    tracer);
33401.1Skamil
33411.1Skamil	validate_status_exited(status, exitval_tracer);
33421.1Skamil
33431.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
33441.1Skamil	    TWAIT_FNAME);
33451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
33461.1Skamil	    tracee);
33471.1Skamil
33481.77Skamil	validate_status_signaled(status, SIGKILL, 0);
33491.1Skamil
33501.1Skamil	msg_close(&parent_tracer);
33511.1Skamil	msg_close(&parent_tracee);
33521.1Skamil}
33531.77Skamil
33541.77Skamil#define ATTACH_LWPINFO(test, threads)					\
33551.77SkamilATF_TC(test);								\
33561.77SkamilATF_TC_HEAD(test, tc)							\
33571.77Skamil{									\
33581.77Skamil	atf_tc_set_md_var(tc, "descr",					\
33591.77Skamil	    "Verify LWPINFO with the child with " #threads		\
33601.77Skamil	    " spawned extra threads (tracer is not the original "	\
33611.77Skamil	    "parent)");							\
33621.77Skamil}									\
33631.77Skamil									\
33641.77SkamilATF_TC_BODY(test, tc)							\
33651.77Skamil{									\
33661.77Skamil									\
33671.77Skamil	attach_lwpinfo(threads);					\
33681.77Skamil}
33691.77Skamil
33701.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0)
33711.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1)
33721.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2)
33731.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3)
33741.1Skamil#endif
33751.1Skamil
33761.77Skamil/// ----------------------------------------------------------------------------
33771.77Skamil
33781.1Skamilstatic void
33791.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
33801.1Skamil{
33811.1Skamil	const int exitval = 5;
33821.1Skamil	const int sigval = SIGINT;
33831.1Skamil	const int sigfaked = SIGTRAP;
33841.1Skamil	const int sicodefaked = TRAP_BRKPT;
33851.1Skamil	pid_t child, wpid;
33861.1Skamil	struct sigaction sa;
33871.1Skamil#if defined(TWAIT_HAVE_STATUS)
33881.1Skamil	int status;
33891.1Skamil#endif
33901.1Skamil	struct ptrace_siginfo info;
33911.1Skamil	memset(&info, 0, sizeof(info));
33921.1Skamil
33931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33951.1Skamil	if (child == 0) {
33961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33981.1Skamil
33991.79Skamil		sa.sa_sigaction = sah;
34001.1Skamil		sa.sa_flags = SA_SIGINFO;
34011.1Skamil		sigemptyset(&sa.sa_mask);
34021.1Skamil
34031.79Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
34041.79Skamil		    != -1);
34051.1Skamil
34061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34081.1Skamil
34091.79Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
34101.1Skamil
34111.13Schristos		DPRINTF("Before exiting of the child process\n");
34121.1Skamil		_exit(exitval);
34131.1Skamil	}
34141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34151.1Skamil
34161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34181.1Skamil
34191.1Skamil	validate_status_stopped(status, sigval);
34201.1Skamil
34211.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
34221.61Skre	SYSCALL_REQUIRE(
34231.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
34241.1Skamil
34251.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
34261.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
34271.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
34281.1Skamil	    info.psi_siginfo.si_errno);
34291.1Skamil
34301.79Skamil	if (faked) {
34311.79Skamil		DPRINTF("Before setting new faked signal to signo=%d "
34321.79Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
34331.79Skamil		info.psi_siginfo.si_signo = sigfaked;
34341.79Skamil		info.psi_siginfo.si_code = sicodefaked;
34351.79Skamil	}
34361.1Skamil
34371.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
34381.61Skre	SYSCALL_REQUIRE(
34391.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
34401.1Skamil
34411.79Skamil	if (faked) {
34421.79Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
34431.79Skamil		    "child\n");
34441.79Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
34451.79Skamil		    sizeof(info)) != -1);
34461.1Skamil
34471.79Skamil		DPRINTF("Before checking siginfo_t\n");
34481.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
34491.79Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
34501.79Skamil	}
34511.1Skamil
34521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34531.1Skamil	    "without signal to be sent\n");
34541.79Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
34551.79Skamil	    faked ? sigfaked : sigval) != -1);
34561.1Skamil
34571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34591.1Skamil
34601.1Skamil	validate_status_exited(status, exitval);
34611.1Skamil
34621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34641.1Skamil}
34651.1Skamil
34661.79Skamil#define PTRACE_SIGINFO(test, faked)					\
34671.79SkamilATF_TC(test);								\
34681.79SkamilATF_TC_HEAD(test, tc)							\
34691.79Skamil{									\
34701.79Skamil	atf_tc_set_md_var(tc, "descr",					\
34711.79Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
34721.79Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
34731.79Skamil}									\
34741.79Skamil									\
34751.79Skamilstatic int test##_caught = 0;						\
34761.79Skamil									\
34771.79Skamilstatic void								\
34781.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
34791.79Skamil{									\
34801.79Skamil	if (faked) {							\
34811.79Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
34821.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
34831.79Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
34841.79Skamil	} else {							\
34851.79Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
34861.79Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
34871.79Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
34881.79Skamil	}								\
34891.79Skamil									\
34901.79Skamil	++ test##_caught;						\
34911.79Skamil}									\
34921.79Skamil									\
34931.79SkamilATF_TC_BODY(test, tc)							\
34941.79Skamil{									\
34951.79Skamil									\
34961.79Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
34971.79Skamil}
34981.79Skamil
34991.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
35001.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
35011.79Skamil
35021.79Skamil/// ----------------------------------------------------------------------------
35031.79Skamil
35041.82SkamilATF_TC(traceme_exec);
35051.82SkamilATF_TC_HEAD(traceme_exec, tc)
35061.1Skamil{
35071.1Skamil	atf_tc_set_md_var(tc, "descr",
35081.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
35091.1Skamil}
35101.1Skamil
35111.82SkamilATF_TC_BODY(traceme_exec, tc)
35121.1Skamil{
35131.1Skamil	const int sigval = SIGTRAP;
35141.1Skamil	pid_t child, wpid;
35151.1Skamil#if defined(TWAIT_HAVE_STATUS)
35161.1Skamil	int status;
35171.1Skamil#endif
35181.1Skamil
35191.1Skamil	struct ptrace_siginfo info;
35201.1Skamil	memset(&info, 0, sizeof(info));
35211.1Skamil
35221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35241.1Skamil	if (child == 0) {
35251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35271.1Skamil
35281.13Schristos		DPRINTF("Before calling execve(2) from child\n");
35291.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
35301.1Skamil
35311.1Skamil		FORKEE_ASSERT(0 && "Not reached");
35321.1Skamil	}
35331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35341.1Skamil
35351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35371.1Skamil
35381.1Skamil	validate_status_stopped(status, sigval);
35391.1Skamil
35401.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35411.61Skre	SYSCALL_REQUIRE(
35421.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35431.1Skamil
35441.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35451.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35461.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35471.1Skamil	    info.psi_siginfo.si_errno);
35481.1Skamil
35491.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
35501.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
35511.1Skamil
35521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35531.1Skamil	    "without signal to be sent\n");
35541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35551.1Skamil
35561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35581.1Skamil
35591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35611.1Skamil}
35621.1Skamil
35631.82Skamil/// ----------------------------------------------------------------------------
35641.82Skamil
35651.83Skamilstatic volatile int done;
35661.1Skamil
35671.83Skamilstatic void *
35681.83Skamiltrace_threads_cb(void *arg __unused)
35691.1Skamil{
35701.1Skamil
35711.83Skamil	done++;
35721.83Skamil
35731.83Skamil	while (done < 3)
35741.83Skamil		continue;
35751.83Skamil
35761.83Skamil	return NULL;
35771.1Skamil}
35781.1Skamil
35791.83Skamilstatic void
35801.83Skamiltrace_threads(bool trace_create, bool trace_exit)
35811.1Skamil{
35821.1Skamil	const int sigval = SIGSTOP;
35831.1Skamil	pid_t child, wpid;
35841.1Skamil#if defined(TWAIT_HAVE_STATUS)
35851.1Skamil	int status;
35861.1Skamil#endif
35871.1Skamil	ptrace_state_t state;
35881.1Skamil	const int slen = sizeof(state);
35891.1Skamil	ptrace_event_t event;
35901.1Skamil	const int elen = sizeof(event);
35911.83Skamil	struct ptrace_siginfo info;
35921.83Skamil
35931.83Skamil	pthread_t t[3];
35941.83Skamil	int rv;
35951.83Skamil	size_t n;
35961.1Skamil	lwpid_t lid;
35971.83Skamil
35981.83Skamil	/* Track created and exited threads */
35991.83Skamil	bool traced_lwps[__arraycount(t)];
36001.83Skamil
36011.83Skamil	atf_tc_skip("PR kern/51995");
36021.1Skamil
36031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36051.1Skamil	if (child == 0) {
36061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36081.1Skamil
36091.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36101.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36111.1Skamil
36121.83Skamil		for (n = 0; n < __arraycount(t); n++) {
36131.83Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
36141.83Skamil			    NULL);
36151.83Skamil			FORKEE_ASSERT(rv == 0);
36161.83Skamil		}
36171.1Skamil
36181.83Skamil		for (n = 0; n < __arraycount(t); n++) {
36191.83Skamil			rv = pthread_join(t[n], NULL);
36201.83Skamil			FORKEE_ASSERT(rv == 0);
36211.83Skamil		}
36221.1Skamil
36231.83Skamil		/*
36241.83Skamil		 * There is race between _exit() and pthread_join() detaching
36251.83Skamil		 * a thread. For simplicity kill the process after detecting
36261.83Skamil		 * LWP events.
36271.83Skamil		 */
36281.83Skamil		while (true)
36291.83Skamil			continue;
36301.1Skamil
36311.83Skamil		FORKEE_ASSERT(0 && "Not reached");
36321.1Skamil	}
36331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36341.1Skamil
36351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36371.1Skamil
36381.1Skamil	validate_status_stopped(status, sigval);
36391.1Skamil
36401.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36411.83Skamil	SYSCALL_REQUIRE(
36421.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36431.1Skamil
36441.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36451.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
36461.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36471.83Skamil	    info.psi_siginfo.si_errno);
36481.1Skamil
36491.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
36501.83Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
36511.1Skamil
36521.83Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
36531.83Skamil	memset(&event, 0, sizeof(event));
36541.83Skamil	if (trace_create)
36551.83Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
36561.83Skamil	if (trace_exit)
36571.83Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
36581.83Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
36591.1Skamil
36601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36611.1Skamil	    "without signal to be sent\n");
36621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36631.1Skamil
36641.83Skamil	memset(traced_lwps, 0, sizeof(traced_lwps));
36651.1Skamil
36661.83Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
36671.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
36681.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
36691.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
36701.83Skamil		    child);
36711.1Skamil
36721.83Skamil		validate_status_stopped(status, SIGTRAP);
36731.1Skamil
36741.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
36751.83Skamil		    "child\n");
36761.83Skamil		SYSCALL_REQUIRE(
36771.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36781.1Skamil
36791.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36801.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
36811.83Skamil		    "si_errno=%#x\n",
36821.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36831.83Skamil		    info.psi_siginfo.si_errno);
36841.1Skamil
36851.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
36861.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
36871.1Skamil
36881.83Skamil		SYSCALL_REQUIRE(
36891.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
36901.1Skamil
36911.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
36921.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
36931.1Skamil
36941.83Skamil		lid = state.pe_lwp;
36951.83Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
36961.1Skamil
36971.83Skamil		traced_lwps[lid - 1] = true;
36981.1Skamil
36991.83Skamil		DPRINTF("Before resuming the child process where it left off "
37001.83Skamil		    "and without signal to be sent\n");
37011.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37021.83Skamil	}
37031.1Skamil
37041.83Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
37051.83Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
37061.83Skamil		    "SIGTRAP\n", TWAIT_FNAME);
37071.83Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
37081.83Skamil		    child);
37091.1Skamil
37101.83Skamil		validate_status_stopped(status, SIGTRAP);
37111.1Skamil
37121.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
37131.83Skamil		    "child\n");
37141.83Skamil		SYSCALL_REQUIRE(
37151.83Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37161.1Skamil
37171.83Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37181.83Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
37191.83Skamil		    "si_errno=%#x\n",
37201.83Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37211.83Skamil		    info.psi_siginfo.si_errno);
37221.1Skamil
37231.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
37241.83Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
37251.1Skamil
37261.83Skamil		SYSCALL_REQUIRE(
37271.83Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
37281.1Skamil
37291.83Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
37301.83Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
37311.1Skamil
37321.83Skamil		lid = state.pe_lwp;
37331.83Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
37341.1Skamil
37351.83Skamil		if (trace_create) {
37361.83Skamil			ATF_REQUIRE(traced_lwps[lid - 1] == true);
37371.83Skamil			traced_lwps[lid - 1] = false;
37381.83Skamil		}
37391.1Skamil
37401.83Skamil		DPRINTF("Before resuming the child process where it left off "
37411.83Skamil		    "and without signal to be sent\n");
37421.83Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37431.83Skamil	}
37441.1Skamil
37451.83Skamil	kill(child, SIGKILL);
37461.1Skamil
37471.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
37481.1Skamil	    TWAIT_FNAME);
37491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37501.1Skamil
37511.83Skamil	validate_status_signaled(status, SIGKILL, 0);
37521.1Skamil
37531.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
37541.1Skamil	    TWAIT_FNAME);
37551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37561.1Skamil}
37571.1Skamil
37581.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit)			\
37591.83SkamilATF_TC(test);								\
37601.83SkamilATF_TC_HEAD(test, tc)							\
37611.83Skamil{									\
37621.83Skamil        atf_tc_set_md_var(tc, "descr",					\
37631.83Skamil            "Verify spawning threads with%s tracing LWP create and"	\
37641.83Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
37651.83Skamil	    trace_exit ? "" : "out");					\
37661.83Skamil}									\
37671.83Skamil									\
37681.83SkamilATF_TC_BODY(test, tc)							\
37691.83Skamil{									\
37701.83Skamil									\
37711.83Skamil        trace_threads(trace_create, trace_exit);			\
37721.83Skamil}
37731.83Skamil
37741.83SkamilTRACE_THREADS(trace_thread1, false, false)
37751.83SkamilTRACE_THREADS(trace_thread2, false, true)
37761.83SkamilTRACE_THREADS(trace_thread3, true, false)
37771.83SkamilTRACE_THREADS(trace_thread4, true, true)
37781.83Skamil
37791.83Skamil/// ----------------------------------------------------------------------------
37801.83Skamil
37811.84SkamilATF_TC(signal_mask_unrelated);
37821.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc)
37831.1Skamil{
37841.1Skamil	atf_tc_set_md_var(tc, "descr",
37851.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
37861.1Skamil	    "from catching other signals");
37871.1Skamil}
37881.1Skamil
37891.84SkamilATF_TC_BODY(signal_mask_unrelated, tc)
37901.1Skamil{
37911.1Skamil	const int exitval = 5;
37921.1Skamil	const int sigval = SIGSTOP;
37931.1Skamil	const int sigmasked = SIGTRAP;
37941.1Skamil	const int signotmasked = SIGINT;
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 from child\n",
38151.1Skamil		    strsignal(signotmasked));
38161.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 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_stopped(status, signotmasked);
38361.1Skamil
38371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38381.1Skamil	    "without signal to be sent\n");
38391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38401.1Skamil
38411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38431.1Skamil
38441.1Skamil	validate_status_exited(status, exitval);
38451.1Skamil
38461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38481.1Skamil}
38491.1Skamil
38501.84Skamil/// ----------------------------------------------------------------------------
38511.84Skamil
38521.1SkamilATF_TC(signal2);
38531.1SkamilATF_TC_HEAD(signal2, tc)
38541.1Skamil{
38551.1Skamil	atf_tc_set_md_var(tc, "descr",
38561.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
38571.1Skamil	    "catching this raised signal");
38581.1Skamil}
38591.1Skamil
38601.1SkamilATF_TC_BODY(signal2, tc)
38611.1Skamil{
38621.1Skamil	const int exitval = 5;
38631.1Skamil	const int sigval = SIGSTOP;
38641.1Skamil	const int sigmasked = SIGTRAP;
38651.1Skamil	pid_t child, wpid;
38661.1Skamil#if defined(TWAIT_HAVE_STATUS)
38671.1Skamil	int status;
38681.1Skamil#endif
38691.1Skamil	sigset_t intmask;
38701.1Skamil
38711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38731.1Skamil	if (child == 0) {
38741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38761.1Skamil
38771.1Skamil		sigemptyset(&intmask);
38781.1Skamil		sigaddset(&intmask, sigmasked);
38791.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
38801.1Skamil
38811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38831.1Skamil
38841.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
38851.1Skamil		    strsignal(sigmasked));
38861.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
38871.1Skamil
38881.13Schristos		DPRINTF("Before exiting of the child process\n");
38891.1Skamil		_exit(exitval);
38901.1Skamil	}
38911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38921.1Skamil
38931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38951.1Skamil
38961.1Skamil	validate_status_stopped(status, sigval);
38971.1Skamil
38981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38991.1Skamil	    "without signal to be sent\n");
39001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39011.1Skamil
39021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39041.1Skamil
39051.1Skamil	validate_status_exited(status, exitval);
39061.1Skamil
39071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39081.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39091.1Skamil}
39101.1Skamil
39111.1SkamilATF_TC(signal3);
39121.1SkamilATF_TC_HEAD(signal3, tc)
39131.1Skamil{
39141.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
39151.1Skamil	atf_tc_set_md_var(tc, "descr",
39161.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
39171.1Skamil	    "catching software breakpoints");
39181.1Skamil}
39191.1Skamil
39201.1SkamilATF_TC_BODY(signal3, tc)
39211.1Skamil{
39221.1Skamil	const int exitval = 5;
39231.1Skamil	const int sigval = SIGSTOP;
39241.1Skamil	const int sigmasked = SIGTRAP;
39251.1Skamil	pid_t child, wpid;
39261.1Skamil#if defined(TWAIT_HAVE_STATUS)
39271.1Skamil	int status;
39281.1Skamil#endif
39291.1Skamil	sigset_t intmask;
39301.1Skamil
39311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39331.1Skamil	if (child == 0) {
39341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39361.1Skamil
39371.1Skamil		sigemptyset(&intmask);
39381.1Skamil		sigaddset(&intmask, sigmasked);
39391.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
39401.1Skamil
39411.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39421.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39431.1Skamil
39441.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
39451.52Skamil		trigger_trap();
39461.1Skamil
39471.13Schristos		DPRINTF("Before exiting of the child process\n");
39481.1Skamil		_exit(exitval);
39491.1Skamil	}
39501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39511.1Skamil
39521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39541.1Skamil
39551.1Skamil	validate_status_stopped(status, sigval);
39561.1Skamil
39571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39581.1Skamil	    "without signal to be sent\n");
39591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39601.1Skamil
39611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39631.1Skamil
39641.1Skamil	validate_status_stopped(status, sigmasked);
39651.1Skamil
39661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39671.1Skamil	    "without signal to be sent\n");
39681.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
39691.1Skamil
39701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39721.1Skamil
39731.49Skamil	validate_status_signaled(status, SIGKILL, 0);
39741.1Skamil
39751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39771.1Skamil}
39781.1Skamil
39791.1Skamil#if defined(PT_STEP)
39801.1SkamilATF_TC(signal4);
39811.1SkamilATF_TC_HEAD(signal4, tc)
39821.1Skamil{
39831.1Skamil	atf_tc_set_md_var(tc, "descr",
39841.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
39851.1Skamil	    "catching single step trap");
39861.1Skamil}
39871.1Skamil
39881.1SkamilATF_TC_BODY(signal4, tc)
39891.1Skamil{
39901.1Skamil	const int exitval = 5;
39911.1Skamil	const int sigval = SIGSTOP;
39921.1Skamil	const int sigmasked = SIGTRAP;
39931.1Skamil	pid_t child, wpid;
39941.1Skamil#if defined(TWAIT_HAVE_STATUS)
39951.1Skamil	int status;
39961.1Skamil#endif
39971.1Skamil	sigset_t intmask;
39981.1Skamil	int happy;
39991.1Skamil
40001.1Skamil#if defined(__arm__)
40011.5Skamil	/* PT_STEP not supported on arm 32-bit */
40021.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
40031.1Skamil#endif
40041.1Skamil
40051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40071.1Skamil	if (child == 0) {
40081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40101.1Skamil
40111.1Skamil		happy = check_happy(100);
40121.1Skamil
40131.1Skamil		sigemptyset(&intmask);
40141.1Skamil		sigaddset(&intmask, sigmasked);
40151.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
40161.1Skamil
40171.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40181.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40191.1Skamil
40201.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
40211.1Skamil
40221.13Schristos		DPRINTF("Before exiting of the child process\n");
40231.1Skamil		_exit(exitval);
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_STEP, 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.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40421.1Skamil	    "without signal to be sent\n");
40431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40441.1Skamil
40451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40471.1Skamil
40481.1Skamil	validate_status_exited(status, exitval);
40491.1Skamil
40501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40521.1Skamil}
40531.1Skamil#endif
40541.1Skamil
40551.1SkamilATF_TC(signal5);
40561.1SkamilATF_TC_HEAD(signal5, tc)
40571.1Skamil{
40581.1Skamil	atf_tc_set_md_var(tc, "descr",
40591.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
40601.1Skamil	    "catching exec() breakpoint");
40611.1Skamil}
40621.1Skamil
40631.1SkamilATF_TC_BODY(signal5, tc)
40641.1Skamil{
40651.1Skamil	const int sigval = SIGSTOP;
40661.1Skamil	const int sigmasked = SIGTRAP;
40671.1Skamil	pid_t child, wpid;
40681.1Skamil#if defined(TWAIT_HAVE_STATUS)
40691.1Skamil	int status;
40701.1Skamil#endif
40711.58Skamil	struct ptrace_siginfo info;
40721.1Skamil	sigset_t intmask;
40731.1Skamil
40741.58Skamil	memset(&info, 0, sizeof(info));
40751.14Schristos
40761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40781.1Skamil	if (child == 0) {
40791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40811.1Skamil
40821.1Skamil		sigemptyset(&intmask);
40831.1Skamil		sigaddset(&intmask, sigmasked);
40841.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
40851.1Skamil
40861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40881.1Skamil
40891.13Schristos		DPRINTF("Before calling execve(2) from child\n");
40901.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
40911.1Skamil
40921.58Skamil		/* NOTREACHED */
40931.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
40941.1Skamil	}
40951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40961.1Skamil
40971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40991.1Skamil
41001.1Skamil	validate_status_stopped(status, sigval);
41011.1Skamil
41021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41031.1Skamil	    "without signal to be sent\n");
41041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41051.1Skamil
41061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41081.1Skamil
41091.1Skamil	validate_status_stopped(status, sigmasked);
41101.1Skamil
41111.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
41121.61Skre	SYSCALL_REQUIRE(
41131.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
41141.58Skamil
41151.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
41161.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
41171.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
41181.58Skamil	    info.psi_siginfo.si_errno);
41191.58Skamil
41201.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
41211.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
41221.58Skamil
41231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41241.1Skamil	    "without signal to be sent\n");
41251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41261.1Skamil
41271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41291.1Skamil
41301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41321.1Skamil}
41331.1Skamil
41341.1Skamil#if defined(TWAIT_HAVE_PID)
41351.1SkamilATF_TC(signal6);
41361.1SkamilATF_TC_HEAD(signal6, tc)
41371.1Skamil{
41381.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
41391.1Skamil	atf_tc_set_md_var(tc, "descr",
41401.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
41411.1Skamil	    "catching PTRACE_FORK breakpoint");
41421.1Skamil}
41431.1Skamil
41441.1SkamilATF_TC_BODY(signal6, tc)
41451.1Skamil{
41461.1Skamil	const int exitval = 5;
41471.1Skamil	const int exitval2 = 15;
41481.1Skamil	const int sigval = SIGSTOP;
41491.1Skamil	const int sigmasked = SIGTRAP;
41501.1Skamil	pid_t child, child2, wpid;
41511.1Skamil#if defined(TWAIT_HAVE_STATUS)
41521.1Skamil	int status;
41531.1Skamil#endif
41541.1Skamil	sigset_t intmask;
41551.1Skamil	ptrace_state_t state;
41561.1Skamil	const int slen = sizeof(state);
41571.1Skamil	ptrace_event_t event;
41581.1Skamil	const int elen = sizeof(event);
41591.1Skamil
41601.38Skamil	atf_tc_expect_fail("PR kern/51918");
41611.14Schristos
41621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41641.1Skamil	if (child == 0) {
41651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41671.1Skamil
41681.1Skamil		sigemptyset(&intmask);
41691.1Skamil		sigaddset(&intmask, sigmasked);
41701.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
41711.1Skamil
41721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41741.1Skamil
41751.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
41761.1Skamil
41771.1Skamil		if (child2 == 0)
41781.1Skamil			_exit(exitval2);
41791.1Skamil
41801.1Skamil		FORKEE_REQUIRE_SUCCESS
41811.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
41821.1Skamil
41831.1Skamil		forkee_status_exited(status, exitval2);
41841.1Skamil
41851.13Schristos		DPRINTF("Before exiting of the child process\n");
41861.1Skamil		_exit(exitval);
41871.1Skamil	}
41881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41891.1Skamil
41901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41921.1Skamil
41931.1Skamil	validate_status_stopped(status, sigval);
41941.1Skamil
41951.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
41961.1Skamil	event.pe_set_event = PTRACE_FORK;
41971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
41981.1Skamil
41991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42001.1Skamil	    "without signal to be sent\n");
42011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42021.1Skamil
42031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42051.1Skamil
42061.1Skamil	validate_status_stopped(status, sigmasked);
42071.1Skamil
42081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
42091.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
42101.1Skamil
42111.1Skamil	child2 = state.pe_other_pid;
42121.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
42131.1Skamil
42141.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
42151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
42161.1Skamil	    child2);
42171.1Skamil
42181.1Skamil	validate_status_stopped(status, SIGTRAP);
42191.1Skamil
42201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
42211.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
42221.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
42231.1Skamil
42241.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
42251.1Skamil	    "without signal to be sent\n");
42261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
42271.1Skamil
42281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42291.1Skamil	    "without signal to be sent\n");
42301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42311.1Skamil
42321.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
42331.1Skamil	    TWAIT_FNAME);
42341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
42351.57Skamil	    child2);
42361.1Skamil
42371.1Skamil	validate_status_exited(status, exitval2);
42381.1Skamil
42391.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
42401.1Skamil	    TWAIT_FNAME);
42411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
42421.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
42431.1Skamil
42441.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
42451.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
42461.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42471.1Skamil
42481.1Skamil	validate_status_stopped(status, SIGCHLD);
42491.1Skamil
42501.57Skamil	DPRINTF("Before resuming the child process where it left off and "
42511.1Skamil	    "without signal to be sent\n");
42521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42531.1Skamil
42541.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
42551.1Skamil	    TWAIT_FNAME);
42561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42571.1Skamil
42581.1Skamil	validate_status_exited(status, exitval);
42591.1Skamil
42601.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
42611.57Skamil	    TWAIT_FNAME);
42621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42631.1Skamil}
42641.1Skamil#endif
42651.1Skamil
42661.1Skamil#if defined(TWAIT_HAVE_PID)
42671.1SkamilATF_TC(signal7);
42681.1SkamilATF_TC_HEAD(signal7, tc)
42691.1Skamil{
42701.1Skamil	atf_tc_set_md_var(tc, "descr",
42711.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
42721.1Skamil	    "catching PTRACE_VFORK breakpoint");
42731.1Skamil}
42741.1Skamil
42751.1SkamilATF_TC_BODY(signal7, tc)
42761.1Skamil{
42771.1Skamil	const int exitval = 5;
42781.1Skamil	const int exitval2 = 15;
42791.1Skamil	const int sigval = SIGSTOP;
42801.1Skamil	const int sigmasked = SIGTRAP;
42811.1Skamil	pid_t child, child2, wpid;
42821.1Skamil#if defined(TWAIT_HAVE_STATUS)
42831.1Skamil	int status;
42841.1Skamil#endif
42851.1Skamil	sigset_t intmask;
42861.1Skamil	ptrace_state_t state;
42871.1Skamil	const int slen = sizeof(state);
42881.1Skamil	ptrace_event_t event;
42891.1Skamil	const int elen = sizeof(event);
42901.1Skamil
42911.38Skamil	atf_tc_expect_fail("PR kern/51918");
42921.14Schristos
42931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42951.1Skamil	if (child == 0) {
42961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42981.1Skamil
42991.1Skamil		sigemptyset(&intmask);
43001.1Skamil		sigaddset(&intmask, sigmasked);
43011.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43021.1Skamil
43031.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43041.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43051.1Skamil
43061.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
43071.1Skamil
43081.1Skamil		if (child2 == 0)
43091.1Skamil			_exit(exitval2);
43101.1Skamil
43111.1Skamil		FORKEE_REQUIRE_SUCCESS
43121.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
43131.1Skamil
43141.1Skamil		forkee_status_exited(status, exitval2);
43151.1Skamil
43161.13Schristos		DPRINTF("Before exiting of the child process\n");
43171.1Skamil		_exit(exitval);
43181.1Skamil	}
43191.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43201.1Skamil
43211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43231.1Skamil
43241.1Skamil	validate_status_stopped(status, sigval);
43251.1Skamil
43261.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
43271.1Skamil	event.pe_set_event = PTRACE_VFORK;
43281.61Skre	SYSCALL_REQUIRE(
43291.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
43301.61Skre	    errno == ENOTSUP);
43311.1Skamil
43321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43331.1Skamil	    "without signal to be sent\n");
43341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43351.1Skamil
43361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43381.1Skamil
43391.1Skamil	validate_status_stopped(status, sigmasked);
43401.1Skamil
43411.61Skre	SYSCALL_REQUIRE(
43421.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
43431.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
43441.1Skamil
43451.1Skamil	child2 = state.pe_other_pid;
43461.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
43471.1Skamil
43481.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
43491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
43501.1Skamil	    child2);
43511.1Skamil
43521.1Skamil	validate_status_stopped(status, SIGTRAP);
43531.1Skamil
43541.61Skre	SYSCALL_REQUIRE(
43551.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
43561.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
43571.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
43581.1Skamil
43591.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
43601.1Skamil	    "without signal to be sent\n");
43611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
43621.1Skamil
43631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43641.1Skamil	    "without signal to be sent\n");
43651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43661.1Skamil
43671.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
43681.1Skamil	    TWAIT_FNAME);
43691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
43701.57Skamil	    child2);
43711.1Skamil
43721.1Skamil	validate_status_exited(status, exitval2);
43731.1Skamil
43741.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
43751.1Skamil	    TWAIT_FNAME);
43761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
43771.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
43781.1Skamil
43791.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
43801.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
43811.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43821.1Skamil
43831.1Skamil	validate_status_stopped(status, SIGCHLD);
43841.1Skamil
43851.57Skamil	DPRINTF("Before resuming the child process where it left off and "
43861.1Skamil	    "without signal to be sent\n");
43871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43881.1Skamil
43891.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
43901.1Skamil	    TWAIT_FNAME);
43911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43921.1Skamil
43931.1Skamil	validate_status_exited(status, exitval);
43941.1Skamil
43951.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
43961.57Skamil	    TWAIT_FNAME);
43971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43981.1Skamil}
43991.1Skamil#endif
44001.1Skamil
44011.1SkamilATF_TC(signal8);
44021.1SkamilATF_TC_HEAD(signal8, tc)
44031.1Skamil{
44041.1Skamil	atf_tc_set_md_var(tc, "descr",
44051.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44061.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
44071.1Skamil}
44081.1Skamil
44091.1SkamilATF_TC_BODY(signal8, tc)
44101.1Skamil{
44111.1Skamil	const int exitval = 5;
44121.1Skamil	const int exitval2 = 15;
44131.1Skamil	const int sigval = SIGSTOP;
44141.1Skamil	const int sigmasked = SIGTRAP;
44151.1Skamil	pid_t child, child2, wpid;
44161.1Skamil#if defined(TWAIT_HAVE_STATUS)
44171.1Skamil	int status;
44181.1Skamil#endif
44191.1Skamil	sigset_t intmask;
44201.1Skamil	ptrace_state_t state;
44211.1Skamil	const int slen = sizeof(state);
44221.1Skamil	ptrace_event_t event;
44231.1Skamil	const int elen = sizeof(event);
44241.1Skamil
44251.14Schristos	atf_tc_expect_fail("PR kern/51918");
44261.14Schristos
44271.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44281.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44291.1Skamil	if (child == 0) {
44301.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44311.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44321.1Skamil
44331.1Skamil		sigemptyset(&intmask);
44341.1Skamil		sigaddset(&intmask, sigmasked);
44351.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44361.1Skamil
44371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44391.1Skamil
44401.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
44411.1Skamil
44421.1Skamil		if (child2 == 0)
44431.1Skamil			_exit(exitval2);
44441.1Skamil
44451.1Skamil		FORKEE_REQUIRE_SUCCESS
44461.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
44471.1Skamil
44481.1Skamil		forkee_status_exited(status, exitval2);
44491.1Skamil
44501.13Schristos		DPRINTF("Before exiting of the child process\n");
44511.1Skamil		_exit(exitval);
44521.1Skamil	}
44531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44541.1Skamil
44551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44571.1Skamil
44581.1Skamil	validate_status_stopped(status, sigval);
44591.1Skamil
44601.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
44611.1Skamil	    child);
44621.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
44631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
44641.1Skamil
44651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44661.1Skamil	    "without signal to be sent\n");
44671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44681.1Skamil
44691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44711.1Skamil
44721.1Skamil	validate_status_stopped(status, sigmasked);
44731.1Skamil
44741.61Skre	SYSCALL_REQUIRE(
44751.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
44761.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
44771.1Skamil
44781.1Skamil	child2 = state.pe_other_pid;
44791.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
44801.1Skamil
44811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44821.1Skamil	    "without signal to be sent\n");
44831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44841.1Skamil
44851.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
44861.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
44871.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44881.1Skamil
44891.1Skamil	validate_status_stopped(status, SIGCHLD);
44901.1Skamil
44911.57Skamil	DPRINTF("Before resuming the child process where it left off and "
44921.1Skamil	    "without signal to be sent\n");
44931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44941.1Skamil
44951.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
44961.1Skamil	    TWAIT_FNAME);
44971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44981.1Skamil
44991.1Skamil	validate_status_exited(status, exitval);
45001.1Skamil
45011.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
45021.57Skamil	    TWAIT_FNAME);
45031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45041.1Skamil}
45051.1Skamil
45061.83Skamilvolatile lwpid_t the_lwp_id = 0;
45071.83Skamil
45081.83Skamilstatic void
45091.83Skamillwp_main_func(void *arg)
45101.83Skamil{
45111.83Skamil	the_lwp_id = _lwp_self();
45121.83Skamil	_lwp_exit();
45131.83Skamil}
45141.83Skamil
45151.1SkamilATF_TC(signal9);
45161.1SkamilATF_TC_HEAD(signal9, tc)
45171.1Skamil{
45181.1Skamil	atf_tc_set_md_var(tc, "descr",
45191.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45201.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
45211.1Skamil}
45221.1Skamil
45231.1SkamilATF_TC_BODY(signal9, tc)
45241.1Skamil{
45251.1Skamil	const int exitval = 5;
45261.1Skamil	const int sigval = SIGSTOP;
45271.1Skamil	const int sigmasked = SIGTRAP;
45281.1Skamil	pid_t child, wpid;
45291.1Skamil#if defined(TWAIT_HAVE_STATUS)
45301.1Skamil	int status;
45311.1Skamil#endif
45321.1Skamil	sigset_t intmask;
45331.1Skamil	ptrace_state_t state;
45341.1Skamil	const int slen = sizeof(state);
45351.1Skamil	ptrace_event_t event;
45361.1Skamil	const int elen = sizeof(event);
45371.1Skamil	ucontext_t uc;
45381.1Skamil	lwpid_t lid;
45391.1Skamil	static const size_t ssize = 16*1024;
45401.1Skamil	void *stack;
45411.1Skamil
45421.14Schristos	atf_tc_expect_fail("PR kern/51918");
45431.14Schristos
45441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45461.1Skamil	if (child == 0) {
45471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45491.1Skamil
45501.1Skamil		sigemptyset(&intmask);
45511.1Skamil		sigaddset(&intmask, sigmasked);
45521.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45531.1Skamil
45541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45561.1Skamil
45571.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
45581.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
45591.1Skamil
45601.13Schristos		DPRINTF("Before making context for new lwp in child\n");
45611.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
45621.1Skamil
45631.13Schristos		DPRINTF("Before creating new in child\n");
45641.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
45651.1Skamil
45661.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
45671.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
45681.1Skamil
45691.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
45701.1Skamil		    "are the same\n", lid, the_lwp_id);
45711.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
45721.1Skamil
45731.13Schristos		DPRINTF("Before exiting of the child process\n");
45741.1Skamil		_exit(exitval);
45751.1Skamil	}
45761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45771.1Skamil
45781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45801.1Skamil
45811.1Skamil	validate_status_stopped(status, sigval);
45821.1Skamil
45831.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
45841.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
45851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
45861.1Skamil
45871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45881.1Skamil	    "without signal to be sent\n");
45891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45901.1Skamil
45911.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
45921.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
45931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45941.1Skamil
45951.1Skamil	validate_status_stopped(status, sigmasked);
45961.1Skamil
45971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
45981.1Skamil
45991.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
46001.1Skamil
46011.1Skamil	lid = state.pe_lwp;
46021.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
46031.1Skamil
46041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46051.1Skamil	    "without signal to be sent\n");
46061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46071.1Skamil
46081.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
46091.1Skamil	    TWAIT_FNAME);
46101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46111.1Skamil
46121.1Skamil	validate_status_exited(status, exitval);
46131.1Skamil
46141.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
46151.1Skamil	    TWAIT_FNAME);
46161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46171.1Skamil}
46181.1Skamil
46191.1SkamilATF_TC(signal10);
46201.1SkamilATF_TC_HEAD(signal10, tc)
46211.1Skamil{
46221.1Skamil	atf_tc_set_md_var(tc, "descr",
46231.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
46241.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
46251.1Skamil}
46261.1Skamil
46271.1SkamilATF_TC_BODY(signal10, tc)
46281.1Skamil{
46291.1Skamil	const int exitval = 5;
46301.1Skamil	const int sigval = SIGSTOP;
46311.1Skamil	const int sigmasked = SIGTRAP;
46321.1Skamil	pid_t child, wpid;
46331.1Skamil#if defined(TWAIT_HAVE_STATUS)
46341.1Skamil	int status;
46351.1Skamil#endif
46361.1Skamil	sigset_t intmask;
46371.1Skamil	ptrace_state_t state;
46381.1Skamil	const int slen = sizeof(state);
46391.1Skamil	ptrace_event_t event;
46401.1Skamil	const int elen = sizeof(event);
46411.1Skamil	ucontext_t uc;
46421.1Skamil	lwpid_t lid;
46431.1Skamil	static const size_t ssize = 16*1024;
46441.1Skamil	void *stack;
46451.1Skamil
46461.14Schristos	atf_tc_expect_fail("PR kern/51918");
46471.14Schristos
46481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46501.1Skamil	if (child == 0) {
46511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46531.1Skamil
46541.1Skamil		sigemptyset(&intmask);
46551.1Skamil		sigaddset(&intmask, sigmasked);
46561.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46571.1Skamil
46581.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46591.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46601.1Skamil
46611.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
46621.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
46631.1Skamil
46641.13Schristos		DPRINTF("Before making context for new lwp in child\n");
46651.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
46661.1Skamil
46671.13Schristos		DPRINTF("Before creating new in child\n");
46681.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
46691.1Skamil
46701.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
46711.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
46721.1Skamil
46731.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
46741.1Skamil		    "are the same\n", lid, the_lwp_id);
46751.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
46761.1Skamil
46771.13Schristos		DPRINTF("Before exiting of the child process\n");
46781.1Skamil		_exit(exitval);
46791.1Skamil	}
46801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46811.1Skamil
46821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46841.1Skamil
46851.1Skamil	validate_status_stopped(status, sigval);
46861.1Skamil
46871.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
46881.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
46891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
46901.1Skamil
46911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46921.1Skamil	    "without signal to be sent\n");
46931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46941.1Skamil
46951.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
46961.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
46971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46981.1Skamil
46991.1Skamil	validate_status_stopped(status, sigmasked);
47001.1Skamil
47011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
47021.1Skamil
47031.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
47041.1Skamil
47051.1Skamil	lid = state.pe_lwp;
47061.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
47071.1Skamil
47081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47091.1Skamil	    "without signal to be sent\n");
47101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47111.1Skamil
47121.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
47131.1Skamil	    TWAIT_FNAME);
47141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47151.1Skamil
47161.1Skamil	validate_status_exited(status, exitval);
47171.1Skamil
47181.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
47191.1Skamil	    TWAIT_FNAME);
47201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47211.1Skamil}
47221.1Skamil
47231.1Skamilstatic void
47241.1Skamillwp_main_stop(void *arg)
47251.1Skamil{
47261.1Skamil	the_lwp_id = _lwp_self();
47271.1Skamil
47281.1Skamil	raise(SIGTRAP);
47291.1Skamil
47301.1Skamil	_lwp_exit();
47311.1Skamil}
47321.1Skamil
47331.1SkamilATF_TC(suspend1);
47341.1SkamilATF_TC_HEAD(suspend1, tc)
47351.1Skamil{
47361.1Skamil	atf_tc_set_md_var(tc, "descr",
47371.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
47381.1Skamil	    "resumed by a tracee");
47391.1Skamil}
47401.1Skamil
47411.1SkamilATF_TC_BODY(suspend1, tc)
47421.1Skamil{
47431.1Skamil	const int exitval = 5;
47441.1Skamil	const int sigval = SIGSTOP;
47451.1Skamil	pid_t child, wpid;
47461.1Skamil#if defined(TWAIT_HAVE_STATUS)
47471.1Skamil	int status;
47481.1Skamil#endif
47491.1Skamil	ucontext_t uc;
47501.1Skamil	lwpid_t lid;
47511.1Skamil	static const size_t ssize = 16*1024;
47521.1Skamil	void *stack;
47531.1Skamil	struct ptrace_lwpinfo pl;
47541.1Skamil	struct ptrace_siginfo psi;
47551.1Skamil	volatile int go = 0;
47561.1Skamil
47571.17Skamil	// Feature pending for refactoring
47581.17Skamil	atf_tc_expect_fail("PR kern/51995");
47591.17Skamil
47601.16Skamil	// Hangs with qemu
47611.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
47621.16Skamil
47631.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47641.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47651.1Skamil	if (child == 0) {
47661.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47671.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47681.1Skamil
47691.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47701.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47711.1Skamil
47721.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
47731.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
47741.1Skamil
47751.13Schristos		DPRINTF("Before making context for new lwp in child\n");
47761.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
47771.1Skamil
47781.13Schristos		DPRINTF("Before creating new in child\n");
47791.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
47801.1Skamil
47811.1Skamil		while (go == 0)
47821.1Skamil			continue;
47831.1Skamil
47841.1Skamil		raise(SIGINT);
47851.1Skamil
47861.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
47871.1Skamil
47881.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
47891.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
47901.1Skamil
47911.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
47921.1Skamil		    "are the same\n", lid, the_lwp_id);
47931.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
47941.1Skamil
47951.13Schristos		DPRINTF("Before exiting of the child process\n");
47961.1Skamil		_exit(exitval);
47971.1Skamil	}
47981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47991.1Skamil
48001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48021.1Skamil
48031.1Skamil	validate_status_stopped(status, sigval);
48041.1Skamil
48051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48061.1Skamil	    "without signal to be sent\n");
48071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48081.1Skamil
48091.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48101.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
48111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48121.1Skamil
48131.1Skamil	validate_status_stopped(status, SIGTRAP);
48141.1Skamil
48151.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
48161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
48171.1Skamil
48181.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
48191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
48201.1Skamil
48211.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
48221.1Skamil	    child, getpid());
48231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
48241.1Skamil
48251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48261.1Skamil	    "without signal to be sent\n");
48271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48281.1Skamil
48291.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48301.1Skamil	    "SIGINT\n", TWAIT_FNAME);
48311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48321.1Skamil
48331.1Skamil	validate_status_stopped(status, SIGINT);
48341.1Skamil
48351.1Skamil	pl.pl_lwpid = 0;
48361.1Skamil
48371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
48381.1Skamil	while (pl.pl_lwpid != 0) {
48391.1Skamil
48401.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
48411.1Skamil		switch (pl.pl_lwpid) {
48421.1Skamil		case 1:
48431.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
48441.1Skamil			break;
48451.1Skamil		case 2:
48461.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
48471.1Skamil			break;
48481.1Skamil		}
48491.1Skamil	}
48501.1Skamil
48511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48521.1Skamil	    "without signal to be sent\n");
48531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48541.1Skamil
48551.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48561.1Skamil	    TWAIT_FNAME);
48571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48581.1Skamil
48591.1Skamil	validate_status_exited(status, exitval);
48601.1Skamil
48611.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48621.1Skamil	    TWAIT_FNAME);
48631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48641.1Skamil}
48651.1Skamil
48661.1SkamilATF_TC(suspend2);
48671.1SkamilATF_TC_HEAD(suspend2, tc)
48681.1Skamil{
48691.1Skamil	atf_tc_set_md_var(tc, "descr",
48701.1Skamil	    "Verify that the while the only thread within a process is "
48711.1Skamil	    "suspended, the whole process cannot be unstopped");
48721.1Skamil}
48731.1Skamil
48741.1SkamilATF_TC_BODY(suspend2, tc)
48751.1Skamil{
48761.1Skamil	const int exitval = 5;
48771.1Skamil	const int sigval = SIGSTOP;
48781.1Skamil	pid_t child, wpid;
48791.1Skamil#if defined(TWAIT_HAVE_STATUS)
48801.1Skamil	int status;
48811.1Skamil#endif
48821.1Skamil	struct ptrace_siginfo psi;
48831.1Skamil
48841.17Skamil	// Feature pending for refactoring
48851.17Skamil	atf_tc_expect_fail("PR kern/51995");
48861.17Skamil
48871.16Skamil	// Hangs with qemu
48881.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
48891.16Skamil
48901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48921.1Skamil	if (child == 0) {
48931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48951.1Skamil
48961.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48971.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48981.1Skamil
48991.13Schristos		DPRINTF("Before exiting of the child process\n");
49001.1Skamil		_exit(exitval);
49011.1Skamil	}
49021.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49031.1Skamil
49041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49061.1Skamil
49071.1Skamil	validate_status_stopped(status, sigval);
49081.1Skamil
49091.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
49101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
49111.1Skamil
49121.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
49131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
49141.1Skamil
49151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49161.1Skamil	    "without signal to be sent\n");
49171.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
49181.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
49191.1Skamil
49201.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
49211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
49221.1Skamil
49231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49241.1Skamil	    "without signal to be sent\n");
49251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49261.1Skamil
49271.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49281.1Skamil	    TWAIT_FNAME);
49291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49301.1Skamil
49311.1Skamil	validate_status_exited(status, exitval);
49321.1Skamil
49331.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49341.1Skamil	    TWAIT_FNAME);
49351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49361.1Skamil}
49371.1Skamil
49381.1SkamilATF_TC(resume1);
49391.1SkamilATF_TC_HEAD(resume1, tc)
49401.1Skamil{
49411.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
49421.1Skamil	atf_tc_set_md_var(tc, "descr",
49431.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
49441.1Skamil	    "resumed by the debugger");
49451.1Skamil}
49461.1Skamil
49471.1SkamilATF_TC_BODY(resume1, tc)
49481.1Skamil{
49491.1Skamil	struct msg_fds fds;
49501.1Skamil	const int exitval = 5;
49511.1Skamil	const int sigval = SIGSTOP;
49521.1Skamil	pid_t child, wpid;
49531.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
49541.1Skamil#if defined(TWAIT_HAVE_STATUS)
49551.1Skamil	int status;
49561.1Skamil#endif
49571.1Skamil	ucontext_t uc;
49581.1Skamil	lwpid_t lid;
49591.1Skamil	static const size_t ssize = 16*1024;
49601.1Skamil	void *stack;
49611.1Skamil	struct ptrace_lwpinfo pl;
49621.1Skamil	struct ptrace_siginfo psi;
49631.1Skamil
49641.17Skamil	// Feature pending for refactoring
49651.17Skamil	atf_tc_expect_fail("PR kern/51995");
49661.17Skamil
49671.15Schristos	// Hangs with qemu
49681.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
49691.1Skamil
49701.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
49711.1Skamil
49721.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49731.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49741.1Skamil	if (child == 0) {
49751.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49761.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49771.1Skamil
49781.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49791.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49801.1Skamil
49811.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
49821.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
49831.1Skamil
49841.13Schristos		DPRINTF("Before making context for new lwp in child\n");
49851.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
49861.1Skamil
49871.13Schristos		DPRINTF("Before creating new in child\n");
49881.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
49891.1Skamil
49901.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
49911.1Skamil
49921.1Skamil		raise(SIGINT);
49931.1Skamil
49941.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
49951.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
49961.1Skamil
49971.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
49981.1Skamil		    "are the same\n", lid, the_lwp_id);
49991.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
50001.1Skamil
50011.13Schristos		DPRINTF("Before exiting of the child process\n");
50021.1Skamil		_exit(exitval);
50031.1Skamil	}
50041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50051.1Skamil
50061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50081.1Skamil
50091.1Skamil	validate_status_stopped(status, sigval);
50101.1Skamil
50111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50121.1Skamil	    "without signal to be sent\n");
50131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50141.1Skamil
50151.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50161.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
50171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50181.1Skamil
50191.1Skamil	validate_status_stopped(status, SIGTRAP);
50201.1Skamil
50211.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
50221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
50231.1Skamil
50241.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
50251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
50261.1Skamil
50271.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
50281.1Skamil
50291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50301.1Skamil	    "without signal to be sent\n");
50311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50321.1Skamil
50331.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50341.1Skamil	    "SIGINT\n", TWAIT_FNAME);
50351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50361.1Skamil
50371.1Skamil	validate_status_stopped(status, SIGINT);
50381.1Skamil
50391.1Skamil	pl.pl_lwpid = 0;
50401.1Skamil
50411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
50421.1Skamil	while (pl.pl_lwpid != 0) {
50431.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
50441.1Skamil		switch (pl.pl_lwpid) {
50451.1Skamil		case 1:
50461.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
50471.1Skamil			break;
50481.1Skamil		case 2:
50491.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
50501.1Skamil			break;
50511.1Skamil		}
50521.1Skamil	}
50531.1Skamil
50541.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
50551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
50561.1Skamil
50571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50581.1Skamil	    "without signal to be sent\n");
50591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50601.1Skamil
50611.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
50621.1Skamil	    TWAIT_FNAME);
50631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50641.1Skamil
50651.1Skamil	validate_status_exited(status, exitval);
50661.1Skamil
50671.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
50681.1Skamil	    TWAIT_FNAME);
50691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50701.1Skamil
50711.1Skamil	msg_close(&fds);
50721.1Skamil
50731.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
50741.1Skamil	sleep(10);
50751.1Skamil}
50761.1Skamil
50771.1SkamilATF_TC(syscall1);
50781.1SkamilATF_TC_HEAD(syscall1, tc)
50791.1Skamil{
50801.1Skamil	atf_tc_set_md_var(tc, "descr",
50811.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
50821.1Skamil}
50831.1Skamil
50841.1SkamilATF_TC_BODY(syscall1, tc)
50851.1Skamil{
50861.1Skamil	const int exitval = 5;
50871.1Skamil	const int sigval = SIGSTOP;
50881.1Skamil	pid_t child, wpid;
50891.1Skamil#if defined(TWAIT_HAVE_STATUS)
50901.1Skamil	int status;
50911.1Skamil#endif
50921.1Skamil	struct ptrace_siginfo info;
50931.1Skamil	memset(&info, 0, sizeof(info));
50941.1Skamil
50951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50971.1Skamil	if (child == 0) {
50981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51001.1Skamil
51011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51031.1Skamil
51041.1Skamil		syscall(SYS_getpid);
51051.1Skamil
51061.13Schristos		DPRINTF("Before exiting of the child process\n");
51071.1Skamil		_exit(exitval);
51081.1Skamil	}
51091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51101.1Skamil
51111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51131.1Skamil
51141.1Skamil	validate_status_stopped(status, sigval);
51151.1Skamil
51161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51171.1Skamil	    "without signal to be sent\n");
51181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51191.1Skamil
51201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51221.1Skamil
51231.1Skamil	validate_status_stopped(status, SIGTRAP);
51241.1Skamil
51251.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51271.1Skamil
51281.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
51291.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
51301.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51311.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
51321.1Skamil
51331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51341.1Skamil	    "without signal to be sent\n");
51351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51361.1Skamil
51371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51391.1Skamil
51401.1Skamil	validate_status_stopped(status, SIGTRAP);
51411.1Skamil
51421.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51441.1Skamil
51451.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
51461.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
51471.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51481.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
51491.1Skamil
51501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51511.1Skamil	    "without signal to be sent\n");
51521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51531.1Skamil
51541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51561.1Skamil
51571.1Skamil	validate_status_exited(status, exitval);
51581.1Skamil
51591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51611.1Skamil}
51621.1Skamil
51631.1SkamilATF_TC(syscallemu1);
51641.1SkamilATF_TC_HEAD(syscallemu1, tc)
51651.1Skamil{
51661.1Skamil	atf_tc_set_md_var(tc, "descr",
51671.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
51681.1Skamil}
51691.1Skamil
51701.1SkamilATF_TC_BODY(syscallemu1, tc)
51711.1Skamil{
51721.1Skamil	const int exitval = 5;
51731.1Skamil	const int sigval = SIGSTOP;
51741.1Skamil	pid_t child, wpid;
51751.1Skamil#if defined(TWAIT_HAVE_STATUS)
51761.1Skamil	int status;
51771.1Skamil#endif
51781.1Skamil
51791.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
51801.6Skamil	/* syscallemu does not work on sparc (32-bit) */
51811.6Skamil	atf_tc_expect_fail("PR kern/52166");
51821.6Skamil#endif
51831.6Skamil
51841.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51851.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51861.1Skamil	if (child == 0) {
51871.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51881.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51891.1Skamil
51901.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51911.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51921.1Skamil
51931.1Skamil		syscall(SYS_exit, 100);
51941.1Skamil
51951.13Schristos		DPRINTF("Before exiting of the child process\n");
51961.1Skamil		_exit(exitval);
51971.1Skamil	}
51981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51991.1Skamil
52001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52021.1Skamil
52031.1Skamil	validate_status_stopped(status, sigval);
52041.1Skamil
52051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52061.1Skamil	    "without signal to be sent\n");
52071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
52081.1Skamil
52091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52111.1Skamil
52121.1Skamil	validate_status_stopped(status, SIGTRAP);
52131.1Skamil
52141.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
52151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
52161.1Skamil
52171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52181.1Skamil	    "without signal to be sent\n");
52191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
52201.1Skamil
52211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52231.1Skamil
52241.1Skamil	validate_status_stopped(status, SIGTRAP);
52251.1Skamil
52261.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52271.1Skamil	    "without signal to be sent\n");
52281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52291.1Skamil
52301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52321.1Skamil
52331.1Skamil	validate_status_exited(status, exitval);
52341.1Skamil
52351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52371.1Skamil}
52381.1Skamil
52391.1Skamil#include "t_ptrace_amd64_wait.h"
52401.1Skamil#include "t_ptrace_i386_wait.h"
52411.1Skamil#include "t_ptrace_x86_wait.h"
52421.1Skamil
52431.1SkamilATF_TP_ADD_TCS(tp)
52441.1Skamil{
52451.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
52461.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
52471.33Skamil
52481.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
52491.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
52501.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
52511.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
52521.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
52531.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise6);
52541.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise7);
52551.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise8);
52561.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise9);
52571.85Skamil	ATF_TP_ADD_TC(tp, traceme_raise10);
52581.33Skamil
52591.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
52601.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
52611.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
52621.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
52631.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
52641.59Skamil
52651.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
52661.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
52671.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
52681.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
52691.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
52701.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
52711.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
52721.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
52731.50Skamil
52741.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
52751.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
52761.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
52771.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
52781.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
52791.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
52801.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
52811.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
52821.50Skamil
52831.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
52841.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
52851.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
52861.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
52871.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
52881.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
52891.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
52901.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
52911.50Skamil
52921.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
52931.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
52941.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
52951.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
52961.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
52971.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
52981.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
52991.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
53001.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
53011.85Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
53021.1Skamil
53031.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
53041.37Skamil
53051.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
53061.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
53071.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
53081.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
53091.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
53101.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
53111.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
53121.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
53131.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
53141.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
53151.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
53161.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
53171.85Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
53181.40Skamil
53191.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
53201.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
53211.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
53221.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
53231.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
53241.41Skamil
53251.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
53261.43Skamil
53271.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
53281.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
53291.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
53301.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
53311.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
53321.59Skamil
53331.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
53341.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
53351.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
53361.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
53371.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
53381.51Skamil
53391.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
53401.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
53411.51Skamil
53421.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
53431.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
53441.51Skamil
53451.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
53461.51Skamil		tracee_sees_its_original_parent_getppid);
53471.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
53481.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
53491.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
53501.51Skamil		tracee_sees_its_original_parent_procfs_status);
53511.1Skamil
53521.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
53531.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
53541.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
53551.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
53561.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
53571.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
53581.1Skamil
53591.31Skamil	ATF_TP_ADD_TC(tp, fork1);
53601.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
53611.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
53621.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
53631.31Skamil	ATF_TP_ADD_TC(tp, fork5);
53641.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
53651.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
53661.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
53671.31Skamil
53681.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
53691.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
53701.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
53711.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
53721.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
53731.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
53741.64Smartin// thes tests hang on SMP machines, disable them for now
53751.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
53761.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
53771.1Skamil
53781.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
53791.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
53801.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
53811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
53821.54Skamil
53831.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
53841.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
53851.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
53861.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
53871.54Skamil
53881.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
53891.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
53901.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
53911.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
53921.54Skamil
53931.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
53941.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
53951.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
53961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
53971.54Skamil
53981.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
53991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
54001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
54011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
54021.54Skamil
54031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
54041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
54051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
54061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
54071.54Skamil
54081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
54091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
54101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
54111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
54121.54Skamil
54131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
54141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
54151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
54161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
54171.54Skamil
54181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
54191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
54201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
54211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
54221.54Skamil
54231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
54241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
54251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
54261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
54271.1Skamil
54281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
54291.1Skamil
54301.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
54311.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
54321.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
54331.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
54341.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
54351.72Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
54361.1Skamil
54371.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
54381.72Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
54391.1Skamil
54401.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
54411.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
54421.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
54431.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
54441.1Skamil
54451.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
54461.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
54471.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
54481.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
54491.2Skamil
54501.1Skamil	ATF_TP_ADD_TC(tp, kill1);
54511.1Skamil	ATF_TP_ADD_TC(tp, kill2);
54521.75Skamil	ATF_TP_ADD_TC(tp, kill3);
54531.1Skamil
54541.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
54551.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
54561.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
54571.77Skamil	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
54581.77Skamil
54591.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
54601.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
54611.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
54621.77Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
54631.1Skamil
54641.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
54651.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
54661.79Skamil
54671.82Skamil	ATF_TP_ADD_TC(tp, traceme_exec);
54681.1Skamil
54691.83Skamil	ATF_TP_ADD_TC(tp, trace_thread1);
54701.83Skamil	ATF_TP_ADD_TC(tp, trace_thread2);
54711.83Skamil	ATF_TP_ADD_TC(tp, trace_thread3);
54721.83Skamil	ATF_TP_ADD_TC(tp, trace_thread4);
54731.1Skamil
54741.84Skamil	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
54751.84Skamil
54761.1Skamil	ATF_TP_ADD_TC(tp, signal2);
54771.1Skamil	ATF_TP_ADD_TC(tp, signal3);
54781.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
54791.1Skamil	ATF_TP_ADD_TC(tp, signal5);
54801.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
54811.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
54821.1Skamil	ATF_TP_ADD_TC(tp, signal8);
54831.1Skamil	ATF_TP_ADD_TC(tp, signal9);
54841.1Skamil	ATF_TP_ADD_TC(tp, signal10);
54851.1Skamil
54861.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
54871.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
54881.1Skamil
54891.1Skamil	ATF_TP_ADD_TC(tp, resume1);
54901.1Skamil
54911.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
54921.1Skamil
54931.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
54941.1Skamil
54951.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
54961.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
54971.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
54981.1Skamil
54991.1Skamil	return atf_no_error();
55001.1Skamil}
5501