t_ptrace_wait.c revision 1.28
11.28Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.28 2018/04/10 00:09:31 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.1Skamil * Copyright (c) 2016 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.28Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.28 2018/04/10 00:09:31 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.1Skamil#include <sys/ptrace.h>
351.1Skamil#include <sys/resource.h>
361.1Skamil#include <sys/stat.h>
371.1Skamil#include <sys/syscall.h>
381.1Skamil#include <sys/sysctl.h>
391.1Skamil#include <sys/wait.h>
401.1Skamil#include <machine/reg.h>
411.1Skamil#include <elf.h>
421.1Skamil#include <err.h>
431.1Skamil#include <errno.h>
441.1Skamil#include <lwp.h>
451.1Skamil#include <sched.h>
461.1Skamil#include <signal.h>
471.1Skamil#include <stdint.h>
481.1Skamil#include <stdio.h>
491.1Skamil#include <stdlib.h>
501.1Skamil#include <strings.h>
511.26Skamil#include <time.h>
521.1Skamil#include <unistd.h>
531.1Skamil
541.1Skamil#include <atf-c.h>
551.1Skamil
561.1Skamil#include "h_macros.h"
571.1Skamil
581.1Skamil#include "t_ptrace_wait.h"
591.1Skamil#include "msg.h"
601.1Skamil
611.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
621.13Schristos    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, sizeof(msg)) == 0)
631.1Skamil
641.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
651.1Skamil    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
661.1Skamil
671.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
681.1Skamil    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, sizeof(msg)) == 0)
691.1Skamil
701.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
711.13Schristos    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
721.13Schristos
731.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
741.13Schristos    strerror(errno))
751.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
761.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
771.13Schristos
781.13Schristosstatic int debug = 0;
791.13Schristos
801.13Schristos#define DPRINTF(a, ...)	do  \
811.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
821.13Schristos    while (/*CONSTCOND*/0)
831.1Skamil
841.1Skamil
851.1SkamilATF_TC(traceme1);
861.1SkamilATF_TC_HEAD(traceme1, tc)
871.1Skamil{
881.1Skamil	atf_tc_set_md_var(tc, "descr",
891.1Skamil	    "Verify SIGSTOP followed by _exit(2) in a child");
901.1Skamil}
911.1Skamil
921.1SkamilATF_TC_BODY(traceme1, tc)
931.1Skamil{
941.1Skamil	const int exitval = 5;
951.1Skamil	const int sigval = SIGSTOP;
961.1Skamil	pid_t child, wpid;
971.1Skamil#if defined(TWAIT_HAVE_STATUS)
981.1Skamil	int status;
991.1Skamil#endif
1001.1Skamil
1011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1031.1Skamil	if (child == 0) {
1041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1061.1Skamil
1071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1091.1Skamil
1101.13Schristos		DPRINTF("Before exiting of the child process\n");
1111.1Skamil		_exit(exitval);
1121.1Skamil	}
1131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1141.1Skamil
1151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1171.1Skamil
1181.1Skamil	validate_status_stopped(status, sigval);
1191.1Skamil
1201.13Schristos	DPRINTF("Before resuming the child process where it left off and "
1211.1Skamil	    "without signal to be sent\n");
1221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1231.1Skamil
1241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1261.1Skamil
1271.1Skamil	validate_status_exited(status, exitval);
1281.1Skamil
1291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1301.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1311.1Skamil}
1321.1Skamil
1331.1SkamilATF_TC(traceme2);
1341.1SkamilATF_TC_HEAD(traceme2, tc)
1351.1Skamil{
1361.1Skamil	atf_tc_set_md_var(tc, "descr",
1371.27Skamil	    "Verify that a signal emitted by a tracer to a child is caught by "
1381.27Skamil	    "a signal handler");
1391.1Skamil}
1401.1Skamil
1411.1Skamilstatic int traceme2_caught = 0;
1421.1Skamil
1431.1Skamilstatic void
1441.1Skamiltraceme2_sighandler(int sig)
1451.1Skamil{
1461.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
1471.1Skamil
1481.1Skamil	++traceme2_caught;
1491.1Skamil}
1501.1Skamil
1511.1SkamilATF_TC_BODY(traceme2, tc)
1521.1Skamil{
1531.1Skamil	const int exitval = 5;
1541.1Skamil	const int sigval = SIGSTOP, sigsent = SIGINT;
1551.1Skamil	pid_t child, wpid;
1561.1Skamil	struct sigaction sa;
1571.1Skamil#if defined(TWAIT_HAVE_STATUS)
1581.1Skamil	int status;
1591.1Skamil#endif
1601.1Skamil
1611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1631.1Skamil	if (child == 0) {
1641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1661.1Skamil
1671.1Skamil		sa.sa_handler = traceme2_sighandler;
1681.1Skamil		sa.sa_flags = SA_SIGINFO;
1691.1Skamil		sigemptyset(&sa.sa_mask);
1701.1Skamil
1711.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
1721.1Skamil
1731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1751.1Skamil
1761.1Skamil		FORKEE_ASSERT_EQ(traceme2_caught, 1);
1771.1Skamil
1781.13Schristos		DPRINTF("Before exiting of the child process\n");
1791.1Skamil		_exit(exitval);
1801.1Skamil	}
1811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1821.1Skamil
1831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1851.1Skamil
1861.1Skamil	validate_status_stopped(status, sigval);
1871.1Skamil
1881.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
1891.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
1901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
1911.1Skamil
1921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1941.1Skamil
1951.1Skamil	validate_status_exited(status, exitval);
1961.1Skamil
1971.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
1981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1991.1Skamil}
2001.1Skamil
2011.1SkamilATF_TC(traceme3);
2021.1SkamilATF_TC_HEAD(traceme3, tc)
2031.1Skamil{
2041.1Skamil	atf_tc_set_md_var(tc, "descr",
2051.1Skamil	    "Verify SIGSTOP followed by termination by a signal in a child");
2061.1Skamil}
2071.1Skamil
2081.1SkamilATF_TC_BODY(traceme3, tc)
2091.1Skamil{
2101.1Skamil	const int sigval = SIGSTOP, sigsent = SIGINT /* Without core-dump */;
2111.1Skamil	pid_t child, wpid;
2121.1Skamil#if defined(TWAIT_HAVE_STATUS)
2131.1Skamil	int status;
2141.1Skamil#endif
2151.1Skamil
2161.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
2171.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
2181.1Skamil	if (child == 0) {
2191.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2201.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2211.1Skamil
2221.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2231.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2241.1Skamil
2251.1Skamil		/* NOTREACHED */
2261.1Skamil		FORKEE_ASSERTX(0 &&
2271.1Skamil		    "Child should be terminated by a signal from its parent");
2281.1Skamil	}
2291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2301.1Skamil
2311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2331.1Skamil
2341.1Skamil	validate_status_stopped(status, sigval);
2351.1Skamil
2361.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2371.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2391.1Skamil
2401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2421.1Skamil
2431.1Skamil	validate_status_signaled(status, sigsent, 0);
2441.1Skamil
2451.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2471.1Skamil}
2481.1Skamil
2491.1SkamilATF_TC(traceme4);
2501.1SkamilATF_TC_HEAD(traceme4, tc)
2511.1Skamil{
2521.1Skamil	atf_tc_set_md_var(tc, "descr",
2531.1Skamil	    "Verify SIGSTOP followed by SIGCONT and _exit(2) in a child");
2541.1Skamil}
2551.1Skamil
2561.1SkamilATF_TC_BODY(traceme4, tc)
2571.1Skamil{
2581.1Skamil	const int exitval = 5;
2591.1Skamil	const int sigval = SIGSTOP, sigsent = SIGCONT;
2601.1Skamil	pid_t child, wpid;
2611.1Skamil#if defined(TWAIT_HAVE_STATUS)
2621.1Skamil	int status;
2631.1Skamil#endif
2641.1Skamil
2651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
2661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
2671.1Skamil	if (child == 0) {
2681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2701.1Skamil
2711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2731.1Skamil
2741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigsent));
2751.1Skamil		FORKEE_ASSERT(raise(sigsent) == 0);
2761.1Skamil
2771.13Schristos		DPRINTF("Before exiting of the child process\n");
2781.1Skamil		_exit(exitval);
2791.1Skamil	}
2801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),child);
2811.1Skamil
2821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2841.1Skamil
2851.1Skamil	validate_status_stopped(status, sigval);
2861.1Skamil
2871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
2881.1Skamil	    "without signal to be sent\n");
2891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2901.1Skamil
2911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2931.1Skamil
2941.1Skamil	validate_status_stopped(status, sigsent);
2951.1Skamil
2961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
2971.1Skamil	    "without signal to be sent\n");
2981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2991.1Skamil
3001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3021.1Skamil
3031.1Skamil	validate_status_exited(status, exitval);
3041.1Skamil
3051.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3071.1Skamil}
3081.1Skamil
3091.1Skamil#if defined(TWAIT_HAVE_PID)
3101.1SkamilATF_TC(attach1);
3111.1SkamilATF_TC_HEAD(attach1, tc)
3121.1Skamil{
3131.1Skamil	atf_tc_set_md_var(tc, "descr",
3141.1Skamil	    "Assert that tracer sees process termination before the parent");
3151.1Skamil}
3161.1Skamil
3171.26Skamilstatic void
3181.26Skamilattach1_raw(bool raw)
3191.1Skamil{
3201.1Skamil	struct msg_fds parent_tracee, parent_tracer;
3211.1Skamil	const int exitval_tracee = 5;
3221.1Skamil	const int exitval_tracer = 10;
3231.1Skamil	pid_t tracee, tracer, wpid;
3241.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
3251.1Skamil#if defined(TWAIT_HAVE_STATUS)
3261.1Skamil	int status;
3271.1Skamil#endif
3281.1Skamil
3291.13Schristos	DPRINTF("Spawn tracee\n");
3301.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
3311.1Skamil	tracee = atf_utils_fork();
3321.1Skamil	if (tracee == 0) {
3331.1Skamil		// Wait for parent to let us exit
3341.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
3351.1Skamil		_exit(exitval_tracee);
3361.1Skamil	}
3371.1Skamil
3381.13Schristos	DPRINTF("Spawn debugger\n");
3391.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
3401.1Skamil	tracer = atf_utils_fork();
3411.1Skamil	if (tracer == 0) {
3421.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
3431.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
3441.1Skamil
3451.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
3461.1Skamil		FORKEE_REQUIRE_SUCCESS(
3471.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
3481.1Skamil
3491.1Skamil		forkee_status_stopped(status, SIGSTOP);
3501.1Skamil
3511.1Skamil		/* Resume tracee with PT_CONTINUE */
3521.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
3531.1Skamil
3541.1Skamil		/* Inform parent that tracer has attached to tracee */
3551.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
3561.1Skamil
3571.1Skamil		/* Wait for parent to tell use that tracee should have exited */
3581.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
3591.1Skamil
3601.1Skamil		/* Wait for tracee and assert that it exited */
3611.1Skamil		FORKEE_REQUIRE_SUCCESS(
3621.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
3631.1Skamil
3641.1Skamil		forkee_status_exited(status, exitval_tracee);
3651.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
3661.1Skamil
3671.13Schristos		DPRINTF("Before exiting of the tracer process\n");
3681.1Skamil		_exit(exitval_tracer);
3691.1Skamil	}
3701.1Skamil
3711.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
3721.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
3731.1Skamil
3741.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
3751.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
3761.1Skamil
3771.13Schristos	DPRINTF("Detect that tracee is zombie\n");
3781.26Skamil	if (raw)
3791.26Skamil		await_zombie_raw(tracee, 0);
3801.26Skamil	else
3811.26Skamil		await_zombie(tracee);
3821.1Skamil
3831.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
3841.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
3851.1Skamil	    TWAIT_FNAME);
3861.1Skamil	TWAIT_REQUIRE_SUCCESS(
3871.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
3881.1Skamil
3891.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
3901.1Skamil	PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
3911.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
3921.1Skamil	    TWAIT_FNAME);
3931.1Skamil
3941.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
3951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
3961.1Skamil	    tracer);
3971.1Skamil
3981.1Skamil	validate_status_exited(status, exitval_tracer);
3991.1Skamil
4001.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
4011.1Skamil	    TWAIT_FNAME);
4021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
4031.1Skamil	    tracee);
4041.1Skamil
4051.1Skamil	validate_status_exited(status, exitval_tracee);
4061.1Skamil
4071.1Skamil	msg_close(&parent_tracer);
4081.1Skamil	msg_close(&parent_tracee);
4091.1Skamil}
4101.26Skamil
4111.26SkamilATF_TC_BODY(attach1, tc)
4121.26Skamil{
4131.26Skamil
4141.26Skamil	/* Reuse this test with race1 */
4151.26Skamil	attach1_raw(false);
4161.26Skamil}
4171.26Skamil
4181.1Skamil#endif
4191.1Skamil
4201.1Skamil#if defined(TWAIT_HAVE_PID)
4211.1SkamilATF_TC(attach2);
4221.1SkamilATF_TC_HEAD(attach2, tc)
4231.1Skamil{
4241.1Skamil	atf_tc_set_md_var(tc, "descr",
4251.1Skamil	    "Assert that any tracer sees process termination before its "
4261.1Skamil	    "parent");
4271.1Skamil}
4281.1Skamil
4291.1SkamilATF_TC_BODY(attach2, tc)
4301.1Skamil{
4311.1Skamil	struct msg_fds parent_tracer, parent_tracee;
4321.1Skamil	const int exitval_tracee = 5;
4331.1Skamil	const int exitval_tracer1 = 10, exitval_tracer2 = 20;
4341.1Skamil	pid_t tracee, tracer, wpid;
4351.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
4361.1Skamil#if defined(TWAIT_HAVE_STATUS)
4371.1Skamil	int status;
4381.1Skamil#endif
4391.1Skamil
4401.13Schristos	DPRINTF("Spawn tracee\n");
4411.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
4421.1Skamil	tracee = atf_utils_fork();
4431.1Skamil	if (tracee == 0) {
4441.1Skamil		/* Wait for message from the parent */
4451.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
4461.1Skamil		_exit(exitval_tracee);
4471.1Skamil	}
4481.1Skamil
4491.13Schristos	DPRINTF("Spawn debugger\n");
4501.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
4511.1Skamil	tracer = atf_utils_fork();
4521.1Skamil	if (tracer == 0) {
4531.1Skamil		/* Fork again and drop parent to reattach to PID 1 */
4541.1Skamil		tracer = atf_utils_fork();
4551.1Skamil		if (tracer != 0)
4561.1Skamil			_exit(exitval_tracer1);
4571.1Skamil
4581.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
4591.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
4601.1Skamil
4611.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
4621.1Skamil		FORKEE_REQUIRE_SUCCESS(
4631.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
4641.1Skamil
4651.1Skamil		forkee_status_stopped(status, SIGSTOP);
4661.1Skamil
4671.1Skamil		/* Resume tracee with PT_CONTINUE */
4681.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
4691.1Skamil
4701.1Skamil		/* Inform parent that tracer has attached to tracee */
4711.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
4721.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
4731.1Skamil
4741.1Skamil		/* Wait for tracee and assert that it exited */
4751.1Skamil		FORKEE_REQUIRE_SUCCESS(
4761.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
4771.1Skamil
4781.1Skamil		forkee_status_exited(status, exitval_tracee);
4791.1Skamil
4801.13Schristos		DPRINTF("Before exiting of the tracer process\n");
4811.1Skamil		_exit(exitval_tracer2);
4821.1Skamil	}
4831.13Schristos	DPRINTF("Wait for the tracer process (direct child) to exit calling "
4841.1Skamil	    "%s()\n", TWAIT_FNAME);
4851.1Skamil	TWAIT_REQUIRE_SUCCESS(
4861.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
4871.1Skamil
4881.1Skamil	validate_status_exited(status, exitval_tracer1);
4891.1Skamil
4901.13Schristos	DPRINTF("Wait for the non-exited tracee process with %s()\n",
4911.1Skamil	    TWAIT_FNAME);
4921.1Skamil	TWAIT_REQUIRE_SUCCESS(
4931.1Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
4941.1Skamil
4951.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
4961.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
4971.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
4981.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
4991.1Skamil
5001.13Schristos	DPRINTF("Detect that tracee is zombie\n");
5011.1Skamil	await_zombie(tracee);
5021.1Skamil
5031.13Schristos	DPRINTF("Assert that there is no status about tracee - "
5041.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
5051.1Skamil	TWAIT_REQUIRE_SUCCESS(
5061.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
5071.1Skamil
5081.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
5091.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
5101.1Skamil
5111.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
5121.1Skamil	    TWAIT_FNAME);
5131.24Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0),
5141.1Skamil	    tracee);
5151.1Skamil
5161.1Skamil	validate_status_exited(status, exitval_tracee);
5171.1Skamil
5181.1Skamil	msg_close(&parent_tracer);
5191.1Skamil	msg_close(&parent_tracee);
5201.1Skamil}
5211.1Skamil#endif
5221.1Skamil
5231.1SkamilATF_TC(attach3);
5241.1SkamilATF_TC_HEAD(attach3, tc)
5251.1Skamil{
5261.1Skamil	atf_tc_set_md_var(tc, "descr",
5271.1Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
5281.1Skamil}
5291.1Skamil
5301.1SkamilATF_TC_BODY(attach3, tc)
5311.1Skamil{
5321.1Skamil	struct msg_fds parent_tracee;
5331.1Skamil	const int exitval_tracee = 5;
5341.1Skamil	pid_t tracee, wpid;
5351.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
5361.1Skamil#if defined(TWAIT_HAVE_STATUS)
5371.1Skamil	int status;
5381.1Skamil#endif
5391.1Skamil
5401.13Schristos	DPRINTF("Spawn tracee\n");
5411.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
5421.1Skamil	tracee = atf_utils_fork();
5431.1Skamil	if (tracee == 0) {
5441.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
5451.13Schristos		DPRINTF("Parent should now attach to tracee\n");
5461.1Skamil
5471.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
5481.1Skamil		/* Wait for message from the parent */
5491.1Skamil		_exit(exitval_tracee);
5501.1Skamil	}
5511.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
5521.1Skamil
5531.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
5541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
5551.1Skamil
5561.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
5571.1Skamil	    TWAIT_FNAME);
5581.1Skamil	TWAIT_REQUIRE_SUCCESS(
5591.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
5601.1Skamil
5611.1Skamil	validate_status_stopped(status, SIGSTOP);
5621.1Skamil
5631.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
5641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
5651.1Skamil
5661.13Schristos	DPRINTF("Let the tracee exit now\n");
5671.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
5681.1Skamil
5691.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
5701.1Skamil	TWAIT_REQUIRE_SUCCESS(
5711.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
5721.1Skamil
5731.1Skamil	validate_status_exited(status, exitval_tracee);
5741.1Skamil
5751.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
5761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
5771.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
5781.1Skamil
5791.1Skamil	msg_close(&parent_tracee);
5801.1Skamil}
5811.1Skamil
5821.1SkamilATF_TC(attach4);
5831.1SkamilATF_TC_HEAD(attach4, tc)
5841.1Skamil{
5851.1Skamil	atf_tc_set_md_var(tc, "descr",
5861.1Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
5871.1Skamil}
5881.1Skamil
5891.1SkamilATF_TC_BODY(attach4, tc)
5901.1Skamil{
5911.1Skamil	struct msg_fds parent_tracee;
5921.1Skamil	const int exitval_tracer = 5;
5931.1Skamil	pid_t tracer, wpid;
5941.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
5951.1Skamil#if defined(TWAIT_HAVE_STATUS)
5961.1Skamil	int status;
5971.1Skamil#endif
5981.1Skamil
5991.13Schristos	DPRINTF("Spawn tracer\n");
6001.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
6011.1Skamil	tracer = atf_utils_fork();
6021.1Skamil	if (tracer == 0) {
6031.1Skamil
6041.1Skamil		/* Wait for message from the parent */
6051.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
6061.1Skamil
6071.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
6081.1Skamil		    getppid());
6091.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
6101.1Skamil
6111.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
6121.1Skamil		    TWAIT_FNAME);
6131.1Skamil		FORKEE_REQUIRE_SUCCESS(
6141.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
6151.1Skamil
6161.1Skamil		forkee_status_stopped(status, SIGSTOP);
6171.1Skamil
6181.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
6191.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
6201.1Skamil		    != -1);
6211.1Skamil
6221.1Skamil		/* Tell parent we are ready */
6231.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
6241.1Skamil
6251.1Skamil		_exit(exitval_tracer);
6261.1Skamil	}
6271.1Skamil
6281.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
6291.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
6301.13Schristos	DPRINTF("Allow the tracer to exit now\n");
6311.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
6321.1Skamil
6331.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
6341.1Skamil	TWAIT_REQUIRE_SUCCESS(
6351.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
6361.1Skamil
6371.1Skamil	validate_status_exited(status, exitval_tracer);
6381.1Skamil
6391.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
6401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
6411.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
6421.1Skamil
6431.1Skamil	msg_close(&parent_tracee);
6441.1Skamil}
6451.1Skamil
6461.1Skamil#if defined(TWAIT_HAVE_PID)
6471.1SkamilATF_TC(attach5);
6481.1SkamilATF_TC_HEAD(attach5, tc)
6491.1Skamil{
6501.1Skamil	atf_tc_set_md_var(tc, "descr",
6511.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
6521.1Skamil	    "(check getppid(2))");
6531.1Skamil}
6541.1Skamil
6551.1SkamilATF_TC_BODY(attach5, tc)
6561.1Skamil{
6571.1Skamil	struct msg_fds parent_tracer, parent_tracee;
6581.1Skamil	const int exitval_tracee = 5;
6591.1Skamil	const int exitval_tracer = 10;
6601.1Skamil	pid_t parent, tracee, tracer, wpid;
6611.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6621.1Skamil#if defined(TWAIT_HAVE_STATUS)
6631.1Skamil	int status;
6641.1Skamil#endif
6651.1Skamil
6661.13Schristos	DPRINTF("Spawn tracee\n");
6671.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
6681.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
6691.1Skamil	tracee = atf_utils_fork();
6701.1Skamil	if (tracee == 0) {
6711.1Skamil		parent = getppid();
6721.1Skamil
6731.1Skamil		/* Emit message to the parent */
6741.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
6751.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
6761.1Skamil
6771.1Skamil		FORKEE_ASSERT_EQ(parent, getppid());
6781.1Skamil
6791.1Skamil		_exit(exitval_tracee);
6801.1Skamil	}
6811.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
6821.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
6831.1Skamil
6841.13Schristos	DPRINTF("Spawn debugger\n");
6851.1Skamil	tracer = atf_utils_fork();
6861.1Skamil	if (tracer == 0) {
6871.1Skamil		/* No IPC to communicate with the child */
6881.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
6891.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
6901.1Skamil
6911.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
6921.1Skamil		FORKEE_REQUIRE_SUCCESS(
6931.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6941.1Skamil
6951.1Skamil		forkee_status_stopped(status, SIGSTOP);
6961.1Skamil
6971.1Skamil		/* Resume tracee with PT_CONTINUE */
6981.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
6991.1Skamil
7001.1Skamil		/* Inform parent that tracer has attached to tracee */
7011.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
7021.1Skamil
7031.1Skamil		/* Wait for parent to tell use that tracee should have exited */
7041.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
7051.1Skamil
7061.1Skamil		/* Wait for tracee and assert that it exited */
7071.1Skamil		FORKEE_REQUIRE_SUCCESS(
7081.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7091.1Skamil
7101.1Skamil		forkee_status_exited(status, exitval_tracee);
7111.1Skamil
7121.13Schristos		DPRINTF("Before exiting of the tracer process\n");
7131.1Skamil		_exit(exitval_tracer);
7141.1Skamil	}
7151.1Skamil
7161.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
7171.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
7181.1Skamil
7191.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
7201.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
7211.1Skamil
7221.13Schristos	DPRINTF("Detect that tracee is zombie\n");
7231.1Skamil	await_zombie(tracee);
7241.1Skamil
7251.13Schristos	DPRINTF("Assert that there is no status about tracee - "
7261.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
7271.1Skamil	TWAIT_REQUIRE_SUCCESS(
7281.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
7291.1Skamil
7301.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
7311.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
7321.1Skamil
7331.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
7341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
7351.1Skamil	    tracer);
7361.1Skamil
7371.1Skamil	validate_status_exited(status, exitval_tracer);
7381.1Skamil
7391.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
7401.1Skamil	    TWAIT_FNAME);
7411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
7421.1Skamil	    tracee);
7431.1Skamil
7441.1Skamil	validate_status_exited(status, exitval_tracee);
7451.1Skamil
7461.1Skamil	msg_close(&parent_tracer);
7471.1Skamil	msg_close(&parent_tracee);
7481.1Skamil}
7491.1Skamil#endif
7501.1Skamil
7511.1Skamil#if defined(TWAIT_HAVE_PID)
7521.1SkamilATF_TC(attach6);
7531.1SkamilATF_TC_HEAD(attach6, tc)
7541.1Skamil{
7551.1Skamil	atf_tc_set_md_var(tc, "descr",
7561.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
7571.1Skamil	    "(check sysctl(7) and struct kinfo_proc2)");
7581.1Skamil}
7591.1Skamil
7601.1SkamilATF_TC_BODY(attach6, tc)
7611.1Skamil{
7621.1Skamil	struct msg_fds parent_tracee, parent_tracer;
7631.1Skamil	const int exitval_tracee = 5;
7641.1Skamil	const int exitval_tracer = 10;
7651.1Skamil	pid_t parent, tracee, tracer, wpid;
7661.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7671.1Skamil#if defined(TWAIT_HAVE_STATUS)
7681.1Skamil	int status;
7691.1Skamil#endif
7701.1Skamil	int name[CTL_MAXNAME];
7711.1Skamil	struct kinfo_proc2 kp;
7721.1Skamil	size_t len = sizeof(kp);
7731.1Skamil	unsigned int namelen;
7741.1Skamil
7751.13Schristos	DPRINTF("Spawn tracee\n");
7761.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
7771.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
7781.1Skamil	tracee = atf_utils_fork();
7791.1Skamil	if (tracee == 0) {
7801.1Skamil		parent = getppid();
7811.1Skamil
7821.1Skamil		/* Emit message to the parent */
7831.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
7841.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
7851.1Skamil
7861.1Skamil		namelen = 0;
7871.1Skamil		name[namelen++] = CTL_KERN;
7881.1Skamil		name[namelen++] = KERN_PROC2;
7891.1Skamil		name[namelen++] = KERN_PROC_PID;
7901.1Skamil		name[namelen++] = getpid();
7911.1Skamil		name[namelen++] = len;
7921.1Skamil		name[namelen++] = 1;
7931.1Skamil
7941.1Skamil		FORKEE_ASSERT(sysctl(name, namelen, &kp, &len, NULL, 0) == 0);
7951.1Skamil		FORKEE_ASSERT_EQ(parent, kp.p_ppid);
7961.1Skamil
7971.1Skamil		_exit(exitval_tracee);
7981.1Skamil	}
7991.1Skamil
8001.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
8011.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
8021.1Skamil
8031.13Schristos	DPRINTF("Spawn debugger\n");
8041.1Skamil	tracer = atf_utils_fork();
8051.1Skamil	if (tracer == 0) {
8061.1Skamil		/* No IPC to communicate with the child */
8071.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
8081.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
8091.1Skamil
8101.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
8111.1Skamil		FORKEE_REQUIRE_SUCCESS(
8121.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8131.1Skamil
8141.1Skamil		forkee_status_stopped(status, SIGSTOP);
8151.1Skamil
8161.1Skamil		/* Resume tracee with PT_CONTINUE */
8171.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
8181.1Skamil
8191.1Skamil		/* Inform parent that tracer has attached to tracee */
8201.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
8211.1Skamil
8221.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
8231.1Skamil
8241.1Skamil		/* Wait for tracee and assert that it exited */
8251.1Skamil		FORKEE_REQUIRE_SUCCESS(
8261.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8271.1Skamil
8281.1Skamil		forkee_status_exited(status, exitval_tracee);
8291.1Skamil
8301.13Schristos		DPRINTF("Before exiting of the tracer process\n");
8311.1Skamil		_exit(exitval_tracer);
8321.1Skamil	}
8331.1Skamil
8341.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
8351.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
8361.1Skamil
8371.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
8381.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8391.1Skamil
8401.13Schristos	DPRINTF("Detect that tracee is zombie\n");
8411.1Skamil	await_zombie(tracee);
8421.1Skamil
8431.13Schristos	DPRINTF("Assert that there is no status about tracee - "
8441.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
8451.1Skamil	TWAIT_REQUIRE_SUCCESS(
8461.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
8471.1Skamil
8481.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
8491.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
8501.1Skamil
8511.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
8521.1Skamil	    TWAIT_FNAME);
8531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
8541.1Skamil	    tracer);
8551.1Skamil
8561.1Skamil	validate_status_exited(status, exitval_tracer);
8571.1Skamil
8581.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
8591.1Skamil	    TWAIT_FNAME);
8601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
8611.1Skamil	    tracee);
8621.1Skamil
8631.1Skamil	validate_status_exited(status, exitval_tracee);
8641.1Skamil
8651.1Skamil	msg_close(&parent_tracee);
8661.1Skamil	msg_close(&parent_tracer);
8671.1Skamil}
8681.1Skamil#endif
8691.1Skamil
8701.1Skamil#if defined(TWAIT_HAVE_PID)
8711.1SkamilATF_TC(attach7);
8721.1SkamilATF_TC_HEAD(attach7, tc)
8731.1Skamil{
8741.1Skamil	atf_tc_set_md_var(tc, "descr",
8751.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
8761.1Skamil	    "(check /proc/curproc/status 3rd column)");
8771.1Skamil}
8781.1Skamil
8791.1SkamilATF_TC_BODY(attach7, tc)
8801.1Skamil{
8811.1Skamil	struct msg_fds parent_tracee, parent_tracer;
8821.1Skamil	int rv;
8831.1Skamil	const int exitval_tracee = 5;
8841.1Skamil	const int exitval_tracer = 10;
8851.1Skamil	pid_t parent, tracee, tracer, wpid;
8861.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8871.1Skamil#if defined(TWAIT_HAVE_STATUS)
8881.1Skamil	int status;
8891.1Skamil#endif
8901.1Skamil	FILE *fp;
8911.1Skamil	struct stat st;
8921.1Skamil	const char *fname = "/proc/curproc/status";
8931.1Skamil	char s_executable[MAXPATHLEN];
8941.1Skamil	int s_pid, s_ppid;
8951.1Skamil	/*
8961.1Skamil	 * Format:
8971.1Skamil	 *  EXECUTABLE PID PPID ...
8981.1Skamil	 */
8991.1Skamil
9001.13Schristos	SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 || (errno == ENOENT));
9011.1Skamil	if (rv != 0) {
9021.1Skamil		atf_tc_skip("/proc/curproc/status not found");
9031.1Skamil	}
9041.1Skamil
9051.13Schristos	DPRINTF("Spawn tracee\n");
9061.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
9071.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
9081.1Skamil	tracee = atf_utils_fork();
9091.1Skamil	if (tracee == 0) {
9101.1Skamil		parent = getppid();
9111.1Skamil
9121.1Skamil		// Wait for parent to let us exit
9131.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
9141.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
9151.1Skamil
9161.1Skamil		FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
9171.1Skamil		fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
9181.1Skamil		FORKEE_ASSERT(fclose(fp) == 0);
9191.1Skamil		FORKEE_ASSERT_EQ(parent, s_ppid);
9201.1Skamil
9211.1Skamil		_exit(exitval_tracee);
9221.1Skamil	}
9231.1Skamil
9241.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
9251.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
9261.1Skamil
9271.13Schristos	DPRINTF("Spawn debugger\n");
9281.1Skamil	tracer = atf_utils_fork();
9291.1Skamil	if (tracer == 0) {
9301.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
9311.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
9321.1Skamil
9331.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
9341.1Skamil		FORKEE_REQUIRE_SUCCESS(
9351.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9361.1Skamil
9371.1Skamil		forkee_status_stopped(status, SIGSTOP);
9381.1Skamil
9391.1Skamil		/* Resume tracee with PT_CONTINUE */
9401.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
9411.1Skamil
9421.1Skamil		/* Inform parent that tracer has attached to tracee */
9431.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
9441.1Skamil
9451.1Skamil		/* Wait for parent to tell use that tracee should have exited */
9461.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
9471.1Skamil
9481.1Skamil		/* Wait for tracee and assert that it exited */
9491.1Skamil		FORKEE_REQUIRE_SUCCESS(
9501.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9511.1Skamil
9521.1Skamil		forkee_status_exited(status, exitval_tracee);
9531.1Skamil
9541.13Schristos		DPRINTF("Before exiting of the tracer process\n");
9551.1Skamil		_exit(exitval_tracer);
9561.1Skamil	}
9571.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
9581.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
9591.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
9601.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
9611.1Skamil
9621.13Schristos	DPRINTF("Detect that tracee is zombie\n");
9631.1Skamil	await_zombie(tracee);
9641.1Skamil
9651.13Schristos	DPRINTF("Assert that there is no status about tracee - "
9661.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
9671.1Skamil	TWAIT_REQUIRE_SUCCESS(
9681.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
9691.1Skamil
9701.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
9711.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
9721.1Skamil
9731.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
9741.1Skamil	    TWAIT_FNAME);
9751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
9761.1Skamil	    tracer);
9771.1Skamil
9781.1Skamil	validate_status_exited(status, exitval_tracer);
9791.1Skamil
9801.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
9811.1Skamil	    TWAIT_FNAME);
9821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
9831.1Skamil	    tracee);
9841.1Skamil
9851.1Skamil	validate_status_exited(status, exitval_tracee);
9861.1Skamil
9871.1Skamil	msg_close(&parent_tracee);
9881.1Skamil	msg_close(&parent_tracer);
9891.1Skamil}
9901.1Skamil#endif
9911.1Skamil
9921.1SkamilATF_TC(eventmask1);
9931.1SkamilATF_TC_HEAD(eventmask1, tc)
9941.1Skamil{
9951.1Skamil	atf_tc_set_md_var(tc, "descr",
9961.1Skamil	    "Verify that empty EVENT_MASK is preserved");
9971.1Skamil}
9981.1Skamil
9991.1SkamilATF_TC_BODY(eventmask1, tc)
10001.1Skamil{
10011.1Skamil	const int exitval = 5;
10021.1Skamil	const int sigval = SIGSTOP;
10031.1Skamil	pid_t child, wpid;
10041.1Skamil#if defined(TWAIT_HAVE_STATUS)
10051.1Skamil	int status;
10061.1Skamil#endif
10071.1Skamil	ptrace_event_t set_event, get_event;
10081.1Skamil	const int len = sizeof(ptrace_event_t);
10091.1Skamil
10101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
10111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
10121.1Skamil	if (child == 0) {
10131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10151.1Skamil
10161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10181.1Skamil
10191.13Schristos		DPRINTF("Before exiting of the child process\n");
10201.1Skamil		_exit(exitval);
10211.1Skamil	}
10221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10231.1Skamil
10241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10261.1Skamil
10271.1Skamil	validate_status_stopped(status, sigval);
10281.1Skamil
10291.1Skamil	set_event.pe_set_event = 0;
10301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
10311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
10321.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
10331.1Skamil
10341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
10351.1Skamil	    "without signal to be sent\n");
10361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
10371.1Skamil
10381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10401.1Skamil
10411.1Skamil	validate_status_exited(status, exitval);
10421.1Skamil
10431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10451.1Skamil}
10461.1Skamil
10471.1SkamilATF_TC(eventmask2);
10481.1SkamilATF_TC_HEAD(eventmask2, tc)
10491.1Skamil{
10501.1Skamil	atf_tc_set_md_var(tc, "descr",
10511.1Skamil	    "Verify that PTRACE_FORK in EVENT_MASK is preserved");
10521.1Skamil}
10531.1Skamil
10541.1SkamilATF_TC_BODY(eventmask2, tc)
10551.1Skamil{
10561.1Skamil	const int exitval = 5;
10571.1Skamil	const int sigval = SIGSTOP;
10581.1Skamil	pid_t child, wpid;
10591.1Skamil#if defined(TWAIT_HAVE_STATUS)
10601.1Skamil	int status;
10611.1Skamil#endif
10621.1Skamil	ptrace_event_t set_event, get_event;
10631.1Skamil	const int len = sizeof(ptrace_event_t);
10641.1Skamil
10651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
10661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
10671.1Skamil	if (child == 0) {
10681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10701.1Skamil
10711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
10731.1Skamil
10741.13Schristos		DPRINTF("Before exiting of the child process\n");
10751.1Skamil		_exit(exitval);
10761.1Skamil	}
10771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10781.1Skamil
10791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10811.1Skamil
10821.1Skamil	validate_status_stopped(status, sigval);
10831.1Skamil
10841.1Skamil	set_event.pe_set_event = PTRACE_FORK;
10851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
10861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
10871.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
10881.1Skamil
10891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
10901.1Skamil	    "without signal to be sent\n");
10911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
10921.1Skamil
10931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10951.1Skamil
10961.1Skamil	validate_status_exited(status, exitval);
10971.1Skamil
10981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11001.1Skamil}
11011.1Skamil
11021.1SkamilATF_TC(eventmask3);
11031.1SkamilATF_TC_HEAD(eventmask3, tc)
11041.1Skamil{
11051.1Skamil	atf_tc_set_md_var(tc, "descr",
11061.1Skamil	    "Verify that PTRACE_VFORK in EVENT_MASK is preserved");
11071.1Skamil}
11081.1Skamil
11091.1SkamilATF_TC_BODY(eventmask3, tc)
11101.1Skamil{
11111.1Skamil	const int exitval = 5;
11121.1Skamil	const int sigval = SIGSTOP;
11131.1Skamil	pid_t child, wpid;
11141.1Skamil#if defined(TWAIT_HAVE_STATUS)
11151.1Skamil	int status;
11161.1Skamil#endif
11171.1Skamil	ptrace_event_t set_event, get_event;
11181.1Skamil	const int len = sizeof(ptrace_event_t);
11191.1Skamil
11201.14Schristos	atf_tc_expect_fail("PR kern/51630");
11211.14Schristos
11221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
11231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
11241.1Skamil	if (child == 0) {
11251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11271.1Skamil
11281.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11291.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11301.1Skamil
11311.13Schristos		DPRINTF("Before exiting of the child process\n");
11321.1Skamil		_exit(exitval);
11331.1Skamil	}
11341.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11351.1Skamil
11361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11381.1Skamil
11391.1Skamil	validate_status_stopped(status, sigval);
11401.1Skamil
11411.1Skamil	set_event.pe_set_event = PTRACE_VFORK;
11421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1 || errno == ENOTSUP);
11431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
11441.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
11451.1Skamil
11461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
11471.1Skamil	    "without signal to be sent\n");
11481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
11491.1Skamil
11501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11521.1Skamil
11531.1Skamil	validate_status_exited(status, exitval);
11541.1Skamil
11551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11561.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11571.1Skamil}
11581.1Skamil
11591.1SkamilATF_TC(eventmask4);
11601.1SkamilATF_TC_HEAD(eventmask4, tc)
11611.1Skamil{
11621.1Skamil	atf_tc_set_md_var(tc, "descr",
11631.1Skamil	    "Verify that PTRACE_VFORK_DONE in EVENT_MASK is preserved");
11641.1Skamil}
11651.1Skamil
11661.1SkamilATF_TC_BODY(eventmask4, tc)
11671.1Skamil{
11681.1Skamil	const int exitval = 5;
11691.1Skamil	const int sigval = SIGSTOP;
11701.1Skamil	pid_t child, wpid;
11711.1Skamil#if defined(TWAIT_HAVE_STATUS)
11721.1Skamil	int status;
11731.1Skamil#endif
11741.1Skamil	ptrace_event_t set_event, get_event;
11751.1Skamil	const int len = sizeof(ptrace_event_t);
11761.1Skamil
11771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
11781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
11791.1Skamil	if (child == 0) {
11801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11821.1Skamil
11831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
11841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
11851.1Skamil
11861.13Schristos		DPRINTF("Before exiting of the child process\n");
11871.1Skamil		_exit(exitval);
11881.1Skamil	}
11891.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11901.1Skamil
11911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11931.1Skamil
11941.1Skamil	validate_status_stopped(status, sigval);
11951.1Skamil
11961.1Skamil	set_event.pe_set_event = PTRACE_VFORK_DONE;
11971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
11981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
11991.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
12001.1Skamil
12011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
12021.1Skamil	    "without signal to be sent\n");
12031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12041.1Skamil
12051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12071.1Skamil
12081.1Skamil	validate_status_exited(status, exitval);
12091.1Skamil
12101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12121.1Skamil}
12131.1Skamil
12141.1SkamilATF_TC(eventmask5);
12151.1SkamilATF_TC_HEAD(eventmask5, tc)
12161.1Skamil{
12171.1Skamil	atf_tc_set_md_var(tc, "descr",
12181.1Skamil	    "Verify that PTRACE_LWP_CREATE in EVENT_MASK is preserved");
12191.1Skamil}
12201.1Skamil
12211.1SkamilATF_TC_BODY(eventmask5, tc)
12221.1Skamil{
12231.1Skamil	const int exitval = 5;
12241.1Skamil	const int sigval = SIGSTOP;
12251.1Skamil	pid_t child, wpid;
12261.1Skamil#if defined(TWAIT_HAVE_STATUS)
12271.1Skamil	int status;
12281.1Skamil#endif
12291.1Skamil	ptrace_event_t set_event, get_event;
12301.1Skamil	const int len = sizeof(ptrace_event_t);
12311.1Skamil
12321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12341.1Skamil	if (child == 0) {
12351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12371.1Skamil
12381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12401.1Skamil
12411.13Schristos		DPRINTF("Before exiting of the child process\n");
12421.1Skamil		_exit(exitval);
12431.1Skamil	}
12441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12451.1Skamil
12461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12481.1Skamil
12491.1Skamil	validate_status_stopped(status, sigval);
12501.1Skamil
12511.1Skamil	set_event.pe_set_event = PTRACE_LWP_CREATE;
12521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
12531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
12541.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
12551.1Skamil
12561.13Schristos	DPRINTF("Before resuming the child process where it left off and "
12571.1Skamil	    "without signal to be sent\n");
12581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12591.1Skamil
12601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12621.1Skamil
12631.1Skamil	validate_status_exited(status, exitval);
12641.1Skamil
12651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12671.1Skamil}
12681.1Skamil
12691.1SkamilATF_TC(eventmask6);
12701.1SkamilATF_TC_HEAD(eventmask6, tc)
12711.1Skamil{
12721.1Skamil	atf_tc_set_md_var(tc, "descr",
12731.1Skamil	    "Verify that PTRACE_LWP_EXIT in EVENT_MASK is preserved");
12741.1Skamil}
12751.1Skamil
12761.1SkamilATF_TC_BODY(eventmask6, tc)
12771.1Skamil{
12781.1Skamil	const int exitval = 5;
12791.1Skamil	const int sigval = SIGSTOP;
12801.1Skamil	pid_t child, wpid;
12811.1Skamil#if defined(TWAIT_HAVE_STATUS)
12821.1Skamil	int status;
12831.1Skamil#endif
12841.1Skamil	ptrace_event_t set_event, get_event;
12851.1Skamil	const int len = sizeof(ptrace_event_t);
12861.1Skamil
12871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12891.1Skamil	if (child == 0) {
12901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12921.1Skamil
12931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12951.1Skamil
12961.13Schristos		DPRINTF("Before exiting of the child process\n");
12971.1Skamil		_exit(exitval);
12981.1Skamil	}
12991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13001.1Skamil
13011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13031.1Skamil
13041.1Skamil	validate_status_stopped(status, sigval);
13051.1Skamil
13061.1Skamil	set_event.pe_set_event = PTRACE_LWP_EXIT;
13071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13091.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13101.1Skamil
13111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13121.1Skamil	    "without signal to be sent\n");
13131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13141.1Skamil
13151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13171.1Skamil
13181.1Skamil	validate_status_exited(status, exitval);
13191.1Skamil
13201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13211.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13221.1Skamil}
13231.1Skamil
13241.1Skamil#if defined(TWAIT_HAVE_PID)
13251.28Skamilstatic void
13261.28Skamilfork_test(bool regular)
13271.1Skamil{
13281.1Skamil	const int exitval = 5;
13291.1Skamil	const int exitval2 = 15;
13301.1Skamil	const int sigval = SIGSTOP;
13311.1Skamil	pid_t child, child2, wpid;
13321.1Skamil#if defined(TWAIT_HAVE_STATUS)
13331.1Skamil	int status;
13341.1Skamil#endif
13351.1Skamil	ptrace_state_t state;
13361.1Skamil	const int slen = sizeof(state);
13371.1Skamil	ptrace_event_t event;
13381.1Skamil	const int elen = sizeof(event);
13391.1Skamil
13401.28Skamil	if (!regular) {
13411.28Skamil		atf_tc_expect_fail("PR kern/51630");
13421.28Skamil	}
13431.28Skamil
13441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13461.1Skamil	if (child == 0) {
13471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13491.1Skamil
13501.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13511.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13521.1Skamil
13531.28Skamil		FORKEE_ASSERT((child2 = (regular ? fork() : vfork())) != -1);
13541.1Skamil
13551.1Skamil		if (child2 == 0)
13561.1Skamil			_exit(exitval2);
13571.1Skamil
13581.1Skamil		FORKEE_REQUIRE_SUCCESS
13591.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
13601.1Skamil
13611.1Skamil		forkee_status_exited(status, exitval2);
13621.1Skamil
13631.13Schristos		DPRINTF("Before exiting of the child process\n");
13641.1Skamil		_exit(exitval);
13651.1Skamil	}
13661.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13671.1Skamil
13681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13701.1Skamil
13711.1Skamil	validate_status_stopped(status, sigval);
13721.1Skamil
13731.28Skamil	DPRINTF("Enable PTRACE_%sFORK in EVENT_MASK for the child %d\n",
13741.28Skamil	        regular ? "" : "V", child);
13751.28Skamil	event.pe_set_event = regular ? PTRACE_FORK : PTRACE_VFORK;
13761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
13771.1Skamil
13781.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13791.1Skamil	    "without signal to be sent\n");
13801.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
13811.28Skamil               "pe_report_event=PTRACE_%sFORK, state.pe_other_pid=child2) and "
13821.28Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_%sFORK, "
13831.28Skamil               "state.pe_other_pid=child)\n", child, regular ? "" : "V",
13841.28Skamil	       regular ? "" : "V");
13851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13861.1Skamil
13871.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
13881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13891.1Skamil
13901.1Skamil	validate_status_stopped(status, SIGTRAP);
13911.1Skamil
13921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
13931.28Skamil	ATF_REQUIRE_EQ(state.pe_report_event,
13941.28Skamil	               regular ? PTRACE_FORK : PTRACE_VFORK);
13951.1Skamil
13961.1Skamil	child2 = state.pe_other_pid;
13971.28Skamil	DPRINTF("Reported PTRACE_%sFORK event with forkee %d\n",
13981.28Skamil	        regular ? "" : "V", child2);
13991.1Skamil
14001.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
14011.1Skamil	    TWAIT_FNAME, child2, child);
14021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
14031.1Skamil	    child2);
14041.1Skamil
14051.1Skamil	validate_status_stopped(status, SIGTRAP);
14061.1Skamil
14071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
14081.28Skamil	ATF_REQUIRE_EQ(state.pe_report_event,
14091.28Skamil	               regular ? PTRACE_FORK : PTRACE_VFORK);
14101.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
14111.1Skamil
14121.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
14131.1Skamil	    "without signal to be sent\n");
14141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
14151.1Skamil
14161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14171.1Skamil	    "without signal to be sent\n");
14181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14191.1Skamil
14201.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
14211.1Skamil	    TWAIT_FNAME);
14221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
14231.1Skamil	    child2);
14241.1Skamil
14251.1Skamil	validate_status_exited(status, exitval2);
14261.1Skamil
14271.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
14281.1Skamil	    TWAIT_FNAME);
14291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
14301.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
14311.1Skamil
14321.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
14331.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
14341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14351.1Skamil
14361.1Skamil	validate_status_stopped(status, SIGCHLD);
14371.1Skamil
14381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14391.1Skamil	    "without signal to be sent\n");
14401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14411.1Skamil
14421.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
14431.1Skamil	    TWAIT_FNAME);
14441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14451.1Skamil
14461.1Skamil	validate_status_exited(status, exitval);
14471.1Skamil
14481.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
14491.1Skamil	    TWAIT_FNAME);
14501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14511.1Skamil}
14521.28Skamil
14531.28SkamilATF_TC(fork1);
14541.28SkamilATF_TC_HEAD(fork1, tc)
14551.28Skamil{
14561.28Skamil	atf_tc_set_md_var(tc, "descr",
14571.28Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
14581.28Skamil	    "set to PTRACE_FORK");
14591.28Skamil}
14601.28Skamil
14611.28SkamilATF_TC_BODY(fork1, tc)
14621.28Skamil{
14631.28Skamil
14641.28Skamil	fork_test(true);
14651.28Skamil}
14661.1Skamil#endif
14671.1Skamil
14681.1SkamilATF_TC(fork2);
14691.1SkamilATF_TC_HEAD(fork2, tc)
14701.1Skamil{
14711.1Skamil	atf_tc_set_md_var(tc, "descr",
14721.1Skamil	    "Verify that fork(2) is not intercepted by ptrace(2) with empty "
14731.1Skamil	    "EVENT_MASK");
14741.1Skamil}
14751.1Skamil
14761.1SkamilATF_TC_BODY(fork2, tc)
14771.1Skamil{
14781.1Skamil	const int exitval = 5;
14791.1Skamil	const int exitval2 = 15;
14801.1Skamil	const int sigval = SIGSTOP;
14811.1Skamil	pid_t child, child2, wpid;
14821.1Skamil#if defined(TWAIT_HAVE_STATUS)
14831.1Skamil	int status;
14841.1Skamil#endif
14851.1Skamil	ptrace_event_t event;
14861.1Skamil	const int elen = sizeof(event);
14871.1Skamil
14881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14901.1Skamil	if (child == 0) {
14911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14931.1Skamil
14941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14961.1Skamil
14971.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
14981.1Skamil
14991.1Skamil		if (child2 == 0)
15001.1Skamil			_exit(exitval2);
15011.1Skamil
15021.1Skamil		FORKEE_REQUIRE_SUCCESS
15031.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
15041.1Skamil
15051.1Skamil		forkee_status_exited(status, exitval2);
15061.1Skamil
15071.13Schristos		DPRINTF("Before exiting of the child process\n");
15081.1Skamil		_exit(exitval);
15091.1Skamil	}
15101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15111.1Skamil
15121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15141.1Skamil
15151.1Skamil	validate_status_stopped(status, sigval);
15161.1Skamil
15171.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
15181.1Skamil	event.pe_set_event = 0;
15191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
15201.1Skamil
15211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15221.1Skamil	    "without signal to be sent\n");
15231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15241.1Skamil
15251.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
15261.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
15271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15281.1Skamil
15291.1Skamil	validate_status_stopped(status, SIGCHLD);
15301.1Skamil
15311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15321.1Skamil	    "without signal to be sent\n");
15331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15341.1Skamil
15351.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
15361.1Skamil	    TWAIT_FNAME);
15371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15381.1Skamil
15391.1Skamil	validate_status_exited(status, exitval);
15401.1Skamil
15411.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
15421.1Skamil	    TWAIT_FNAME);
15431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15441.1Skamil}
15451.1Skamil
15461.1Skamil#if defined(TWAIT_HAVE_PID)
15471.1SkamilATF_TC(vfork1);
15481.1SkamilATF_TC_HEAD(vfork1, tc)
15491.1Skamil{
15501.1Skamil	atf_tc_set_md_var(tc, "descr",
15511.1Skamil	    "Verify that vfork(2) is intercepted by ptrace(2) with EVENT_MASK "
15521.1Skamil	    "set to PTRACE_VFORK");
15531.1Skamil}
15541.1Skamil
15551.1SkamilATF_TC_BODY(vfork1, tc)
15561.1Skamil{
15571.1Skamil
15581.28Skamil	fork_test(false);
15591.1Skamil}
15601.1Skamil#endif
15611.1Skamil
15621.1SkamilATF_TC(vfork2);
15631.1SkamilATF_TC_HEAD(vfork2, tc)
15641.1Skamil{
15651.1Skamil	atf_tc_set_md_var(tc, "descr",
15661.1Skamil	    "Verify that vfork(2) is not intercepted by ptrace(2) with empty "
15671.1Skamil	    "EVENT_MASK");
15681.1Skamil}
15691.1Skamil
15701.1SkamilATF_TC_BODY(vfork2, tc)
15711.1Skamil{
15721.1Skamil	const int exitval = 5;
15731.1Skamil	const int exitval2 = 15;
15741.1Skamil	const int sigval = SIGSTOP;
15751.1Skamil	pid_t child, child2, wpid;
15761.1Skamil#if defined(TWAIT_HAVE_STATUS)
15771.1Skamil	int status;
15781.1Skamil#endif
15791.1Skamil	ptrace_event_t event;
15801.1Skamil	const int elen = sizeof(event);
15811.1Skamil
15821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15841.1Skamil	if (child == 0) {
15851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15871.1Skamil
15881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
15891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
15901.1Skamil
15911.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
15921.1Skamil
15931.1Skamil		if (child2 == 0)
15941.1Skamil			_exit(exitval2);
15951.1Skamil
15961.1Skamil		FORKEE_REQUIRE_SUCCESS
15971.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
15981.1Skamil
15991.1Skamil		forkee_status_exited(status, exitval2);
16001.1Skamil
16011.13Schristos		DPRINTF("Before exiting of the child process\n");
16021.1Skamil		_exit(exitval);
16031.1Skamil	}
16041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16051.1Skamil
16061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16081.1Skamil
16091.1Skamil	validate_status_stopped(status, sigval);
16101.1Skamil
16111.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
16121.1Skamil	event.pe_set_event = 0;
16131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
16141.1Skamil
16151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16161.1Skamil	    "without signal to be sent\n");
16171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16181.1Skamil
16191.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
16201.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
16211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16221.1Skamil
16231.1Skamil	validate_status_stopped(status, SIGCHLD);
16241.1Skamil
16251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16261.1Skamil	    "without signal to be sent\n");
16271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16281.1Skamil
16291.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
16301.1Skamil	    TWAIT_FNAME);
16311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16321.1Skamil
16331.1Skamil	validate_status_exited(status, exitval);
16341.1Skamil
16351.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
16361.1Skamil	    TWAIT_FNAME);
16371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16381.1Skamil}
16391.1Skamil
16401.1SkamilATF_TC(vforkdone1);
16411.1SkamilATF_TC_HEAD(vforkdone1, tc)
16421.1Skamil{
16431.1Skamil	atf_tc_set_md_var(tc, "descr",
16441.1Skamil	    "Verify that vfork(2) is intercepted by ptrace(2) with EVENT_MASK "
16451.1Skamil	    "set to PTRACE_VFORK_DONE");
16461.1Skamil}
16471.1Skamil
16481.1SkamilATF_TC_BODY(vforkdone1, tc)
16491.1Skamil{
16501.1Skamil	const int exitval = 5;
16511.1Skamil	const int exitval2 = 15;
16521.1Skamil	const int sigval = SIGSTOP;
16531.1Skamil	pid_t child, child2, wpid;
16541.1Skamil#if defined(TWAIT_HAVE_STATUS)
16551.1Skamil	int status;
16561.1Skamil#endif
16571.1Skamil	ptrace_state_t state;
16581.1Skamil	const int slen = sizeof(state);
16591.1Skamil	ptrace_event_t event;
16601.1Skamil	const int elen = sizeof(event);
16611.1Skamil
16621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
16631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
16641.1Skamil	if (child == 0) {
16651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16671.1Skamil
16681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
16691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
16701.1Skamil
16711.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
16721.1Skamil
16731.1Skamil		if (child2 == 0)
16741.1Skamil			_exit(exitval2);
16751.1Skamil
16761.1Skamil		FORKEE_REQUIRE_SUCCESS
16771.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
16781.1Skamil
16791.1Skamil		forkee_status_exited(status, exitval2);
16801.1Skamil
16811.13Schristos		DPRINTF("Before exiting of the child process\n");
16821.1Skamil		_exit(exitval);
16831.1Skamil	}
16841.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16851.1Skamil
16861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16881.1Skamil
16891.1Skamil	validate_status_stopped(status, sigval);
16901.1Skamil
16911.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
16921.1Skamil	    child);
16931.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
16941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
16951.1Skamil
16961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16971.1Skamil	    "without signal to be sent\n");
16981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16991.1Skamil
17001.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
17011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17021.1Skamil
17031.1Skamil	validate_status_stopped(status, SIGTRAP);
17041.1Skamil
17051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
17061.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
17071.1Skamil
17081.1Skamil	child2 = state.pe_other_pid;
17091.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
17101.1Skamil
17111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
17121.1Skamil	    "without signal to be sent\n");
17131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17141.1Skamil
17151.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
17161.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
17171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17181.1Skamil
17191.1Skamil	validate_status_stopped(status, SIGCHLD);
17201.1Skamil
17211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
17221.1Skamil	    "without signal to be sent\n");
17231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17241.1Skamil
17251.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
17261.1Skamil	    TWAIT_FNAME);
17271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17281.1Skamil
17291.1Skamil	validate_status_exited(status, exitval);
17301.1Skamil
17311.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
17321.1Skamil	    TWAIT_FNAME);
17331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17341.1Skamil}
17351.1Skamil
17361.1SkamilATF_TC(vforkdone2);
17371.1SkamilATF_TC_HEAD(vforkdone2, tc)
17381.1Skamil{
17391.1Skamil	atf_tc_set_md_var(tc, "descr",
17401.1Skamil	    "Verify that vfork(2) is intercepted by ptrace(2) with EVENT_MASK "
17411.1Skamil	    "set to PTRACE_FORK | PTRACE_VFORK_DONE");
17421.1Skamil}
17431.1Skamil
17441.1SkamilATF_TC_BODY(vforkdone2, tc)
17451.1Skamil{
17461.1Skamil	const int exitval = 5;
17471.1Skamil	const int exitval2 = 15;
17481.1Skamil	const int sigval = SIGSTOP;
17491.1Skamil	pid_t child, child2, wpid;
17501.1Skamil#if defined(TWAIT_HAVE_STATUS)
17511.1Skamil	int status;
17521.1Skamil#endif
17531.1Skamil	ptrace_state_t state;
17541.1Skamil	const int slen = sizeof(state);
17551.1Skamil	ptrace_event_t event;
17561.1Skamil	const int elen = sizeof(event);
17571.1Skamil
17581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
17591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
17601.1Skamil	if (child == 0) {
17611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17631.1Skamil
17641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
17651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
17661.1Skamil
17671.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
17681.1Skamil
17691.1Skamil		if (child2 == 0)
17701.1Skamil			_exit(exitval2);
17711.1Skamil
17721.1Skamil		FORKEE_REQUIRE_SUCCESS
17731.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
17741.1Skamil
17751.1Skamil		forkee_status_exited(status, exitval2);
17761.1Skamil
17771.13Schristos		DPRINTF("Before exiting of the child process\n");
17781.1Skamil		_exit(exitval);
17791.1Skamil	}
17801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17811.1Skamil
17821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17841.1Skamil
17851.1Skamil	validate_status_stopped(status, sigval);
17861.1Skamil
17871.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
17881.1Skamil	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK_DONE;
17891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
17901.1Skamil
17911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
17921.1Skamil	    "without signal to be sent\n");
17931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17941.1Skamil
17951.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
17961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17971.1Skamil
17981.1Skamil	validate_status_stopped(status, SIGTRAP);
17991.1Skamil
18001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
18011.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
18021.1Skamil
18031.1Skamil	child2 = state.pe_other_pid;
18041.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
18051.1Skamil
18061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18071.1Skamil	    "without signal to be sent\n");
18081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18091.1Skamil
18101.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
18111.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
18121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18131.1Skamil
18141.1Skamil	validate_status_stopped(status, SIGCHLD);
18151.1Skamil
18161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18171.1Skamil	    "without signal to be sent\n");
18181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18191.1Skamil
18201.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
18211.1Skamil	    TWAIT_FNAME);
18221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18231.1Skamil
18241.1Skamil	validate_status_exited(status, exitval);
18251.1Skamil
18261.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
18271.1Skamil	    TWAIT_FNAME);
18281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18291.1Skamil}
18301.1Skamil
18311.1SkamilATF_TC(io_read_d1);
18321.1SkamilATF_TC_HEAD(io_read_d1, tc)
18331.1Skamil{
18341.1Skamil	atf_tc_set_md_var(tc, "descr",
18351.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint8_t)");
18361.1Skamil}
18371.1Skamil
18381.1SkamilATF_TC_BODY(io_read_d1, tc)
18391.1Skamil{
18401.1Skamil	const int exitval = 5;
18411.1Skamil	const int sigval = SIGSTOP;
18421.1Skamil	pid_t child, wpid;
18431.1Skamil	uint8_t lookup_me = 0;
18441.1Skamil	const uint8_t magic = 0xab;
18451.1Skamil	struct ptrace_io_desc io = {
18461.1Skamil		.piod_op = PIOD_READ_D,
18471.1Skamil		.piod_offs = &lookup_me,
18481.1Skamil		.piod_addr = &lookup_me,
18491.1Skamil		.piod_len = sizeof(lookup_me)
18501.1Skamil	};
18511.1Skamil#if defined(TWAIT_HAVE_STATUS)
18521.1Skamil	int status;
18531.1Skamil#endif
18541.1Skamil
18551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18571.1Skamil	if (child == 0) {
18581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18601.1Skamil
18611.1Skamil		lookup_me = magic;
18621.1Skamil
18631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18651.1Skamil
18661.13Schristos		DPRINTF("Before exiting of the child process\n");
18671.1Skamil		_exit(exitval);
18681.1Skamil	}
18691.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18701.1Skamil
18711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18731.1Skamil
18741.1Skamil	validate_status_stopped(status, sigval);
18751.1Skamil
18761.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
18771.1Skamil	    child, getpid());
18781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
18791.1Skamil
18801.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
18811.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
18821.1Skamil
18831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18841.1Skamil	    "without signal to be sent\n");
18851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18861.1Skamil
18871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18891.1Skamil
18901.1Skamil	validate_status_exited(status, exitval);
18911.1Skamil
18921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18941.1Skamil}
18951.1Skamil
18961.1SkamilATF_TC(io_read_d2);
18971.1SkamilATF_TC_HEAD(io_read_d2, tc)
18981.1Skamil{
18991.1Skamil	atf_tc_set_md_var(tc, "descr",
19001.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint16_t)");
19011.1Skamil}
19021.1Skamil
19031.1SkamilATF_TC_BODY(io_read_d2, tc)
19041.1Skamil{
19051.1Skamil	const int exitval = 5;
19061.1Skamil	const int sigval = SIGSTOP;
19071.1Skamil	pid_t child, wpid;
19081.1Skamil	uint16_t lookup_me = 0;
19091.1Skamil	const uint16_t magic = 0x1234;
19101.1Skamil	struct ptrace_io_desc io = {
19111.1Skamil		.piod_op = PIOD_READ_D,
19121.1Skamil		.piod_offs = &lookup_me,
19131.1Skamil		.piod_addr = &lookup_me,
19141.1Skamil		.piod_len = sizeof(lookup_me)
19151.1Skamil	};
19161.1Skamil#if defined(TWAIT_HAVE_STATUS)
19171.1Skamil	int status;
19181.1Skamil#endif
19191.1Skamil
19201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19221.1Skamil	if (child == 0) {
19231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19251.1Skamil
19261.1Skamil		lookup_me = magic;
19271.1Skamil
19281.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19291.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19301.1Skamil
19311.13Schristos		DPRINTF("Before exiting of the child process\n");
19321.1Skamil		_exit(exitval);
19331.1Skamil	}
19341.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19351.1Skamil
19361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19381.1Skamil
19391.1Skamil	validate_status_stopped(status, sigval);
19401.1Skamil
19411.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19421.1Skamil	    child, getpid());
19431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19441.1Skamil
19451.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19461.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
19471.1Skamil
19481.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19491.1Skamil	    "without signal to be sent\n");
19501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19511.1Skamil
19521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19541.1Skamil
19551.1Skamil	validate_status_exited(status, exitval);
19561.1Skamil
19571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19591.1Skamil}
19601.1Skamil
19611.1SkamilATF_TC(io_read_d3);
19621.1SkamilATF_TC_HEAD(io_read_d3, tc)
19631.1Skamil{
19641.1Skamil	atf_tc_set_md_var(tc, "descr",
19651.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint32_t)");
19661.1Skamil}
19671.1Skamil
19681.1SkamilATF_TC_BODY(io_read_d3, tc)
19691.1Skamil{
19701.1Skamil	const int exitval = 5;
19711.1Skamil	const int sigval = SIGSTOP;
19721.1Skamil	pid_t child, wpid;
19731.1Skamil	uint32_t lookup_me = 0;
19741.1Skamil	const uint32_t magic = 0x1234abcd;
19751.1Skamil	struct ptrace_io_desc io = {
19761.1Skamil		.piod_op = PIOD_READ_D,
19771.1Skamil		.piod_offs = &lookup_me,
19781.1Skamil		.piod_addr = &lookup_me,
19791.1Skamil		.piod_len = sizeof(lookup_me)
19801.1Skamil	};
19811.1Skamil#if defined(TWAIT_HAVE_STATUS)
19821.1Skamil	int status;
19831.1Skamil#endif
19841.1Skamil
19851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19871.1Skamil	if (child == 0) {
19881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19901.1Skamil
19911.1Skamil		lookup_me = magic;
19921.1Skamil
19931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19951.1Skamil
19961.13Schristos		DPRINTF("Before exiting of the child process\n");
19971.1Skamil		_exit(exitval);
19981.1Skamil	}
19991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20001.1Skamil
20011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20031.1Skamil
20041.1Skamil	validate_status_stopped(status, sigval);
20051.1Skamil
20061.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
20071.1Skamil	    child, getpid());
20081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
20091.1Skamil
20101.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
20111.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
20121.1Skamil
20131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20141.1Skamil	    "without signal to be sent\n");
20151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20161.1Skamil
20171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20191.1Skamil
20201.1Skamil	validate_status_exited(status, exitval);
20211.1Skamil
20221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20241.1Skamil}
20251.1Skamil
20261.1SkamilATF_TC(io_read_d4);
20271.1SkamilATF_TC_HEAD(io_read_d4, tc)
20281.1Skamil{
20291.1Skamil	atf_tc_set_md_var(tc, "descr",
20301.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint64_t)");
20311.1Skamil}
20321.1Skamil
20331.1SkamilATF_TC_BODY(io_read_d4, tc)
20341.1Skamil{
20351.1Skamil	const int exitval = 5;
20361.1Skamil	const int sigval = SIGSTOP;
20371.1Skamil	pid_t child, wpid;
20381.1Skamil	uint64_t lookup_me = 0;
20391.1Skamil	const uint64_t magic = 0x1234abcd9876dcfa;
20401.1Skamil	struct ptrace_io_desc io = {
20411.1Skamil		.piod_op = PIOD_READ_D,
20421.1Skamil		.piod_offs = &lookup_me,
20431.1Skamil		.piod_addr = &lookup_me,
20441.1Skamil		.piod_len = sizeof(lookup_me)
20451.1Skamil	};
20461.1Skamil#if defined(TWAIT_HAVE_STATUS)
20471.1Skamil	int status;
20481.1Skamil#endif
20491.1Skamil
20501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20521.1Skamil	if (child == 0) {
20531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20551.1Skamil
20561.1Skamil		lookup_me = magic;
20571.1Skamil
20581.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20591.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20601.1Skamil
20611.13Schristos		DPRINTF("Before exiting of the child process\n");
20621.1Skamil		_exit(exitval);
20631.1Skamil	}
20641.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20651.1Skamil
20661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20681.1Skamil
20691.1Skamil	validate_status_stopped(status, sigval);
20701.1Skamil
20711.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
20721.1Skamil	    child, getpid());
20731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
20741.1Skamil
20751.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
20761.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
20771.1Skamil
20781.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20791.1Skamil	    "without signal to be sent\n");
20801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20811.1Skamil
20821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20841.1Skamil
20851.1Skamil	validate_status_exited(status, exitval);
20861.1Skamil
20871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20881.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20891.1Skamil}
20901.1Skamil
20911.1SkamilATF_TC(io_write_d1);
20921.1SkamilATF_TC_HEAD(io_write_d1, tc)
20931.1Skamil{
20941.1Skamil	atf_tc_set_md_var(tc, "descr",
20951.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint8_t)");
20961.1Skamil}
20971.1Skamil
20981.1SkamilATF_TC_BODY(io_write_d1, tc)
20991.1Skamil{
21001.1Skamil	const int exitval = 5;
21011.1Skamil	const int sigval = SIGSTOP;
21021.1Skamil	pid_t child, wpid;
21031.1Skamil	uint8_t lookup_me = 0;
21041.1Skamil	const uint8_t magic = 0xab;
21051.1Skamil	struct ptrace_io_desc io = {
21061.1Skamil		.piod_op = PIOD_WRITE_D,
21071.1Skamil		.piod_offs = &lookup_me,
21081.1Skamil		.piod_addr = &lookup_me,
21091.1Skamil		.piod_len = sizeof(lookup_me)
21101.1Skamil	};
21111.1Skamil#if defined(TWAIT_HAVE_STATUS)
21121.1Skamil	int status;
21131.1Skamil#endif
21141.1Skamil
21151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21171.1Skamil	if (child == 0) {
21181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21201.1Skamil
21211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21231.1Skamil
21241.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21251.1Skamil
21261.13Schristos		DPRINTF("Before exiting of the child process\n");
21271.1Skamil		_exit(exitval);
21281.1Skamil	}
21291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21301.1Skamil
21311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21331.1Skamil
21341.1Skamil	validate_status_stopped(status, sigval);
21351.1Skamil
21361.1Skamil	lookup_me = magic;
21371.1Skamil
21381.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21391.1Skamil	    child, getpid());
21401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21411.1Skamil
21421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21431.1Skamil	    "without signal to be sent\n");
21441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21451.1Skamil
21461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21481.1Skamil
21491.1Skamil	validate_status_exited(status, exitval);
21501.1Skamil
21511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21531.1Skamil}
21541.1Skamil
21551.1SkamilATF_TC(io_write_d2);
21561.1SkamilATF_TC_HEAD(io_write_d2, tc)
21571.1Skamil{
21581.1Skamil	atf_tc_set_md_var(tc, "descr",
21591.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint16_t)");
21601.1Skamil}
21611.1Skamil
21621.1SkamilATF_TC_BODY(io_write_d2, tc)
21631.1Skamil{
21641.1Skamil	const int exitval = 5;
21651.1Skamil	const int sigval = SIGSTOP;
21661.1Skamil	pid_t child, wpid;
21671.1Skamil	uint16_t lookup_me = 0;
21681.1Skamil	const uint16_t magic = 0xab12;
21691.1Skamil	struct ptrace_io_desc io = {
21701.1Skamil		.piod_op = PIOD_WRITE_D,
21711.1Skamil		.piod_offs = &lookup_me,
21721.1Skamil		.piod_addr = &lookup_me,
21731.1Skamil		.piod_len = sizeof(lookup_me)
21741.1Skamil	};
21751.1Skamil#if defined(TWAIT_HAVE_STATUS)
21761.1Skamil	int status;
21771.1Skamil#endif
21781.1Skamil
21791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21811.1Skamil	if (child == 0) {
21821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21841.1Skamil
21851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21871.1Skamil
21881.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21891.1Skamil
21901.13Schristos		DPRINTF("Before exiting of the child process\n");
21911.1Skamil		_exit(exitval);
21921.1Skamil	}
21931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21941.1Skamil
21951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21971.1Skamil
21981.1Skamil	validate_status_stopped(status, sigval);
21991.1Skamil
22001.1Skamil	lookup_me = magic;
22011.1Skamil
22021.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
22031.1Skamil	    child, getpid());
22041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
22051.1Skamil
22061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22071.1Skamil	    "without signal to be sent\n");
22081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22091.1Skamil
22101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22121.1Skamil
22131.1Skamil	validate_status_exited(status, exitval);
22141.1Skamil
22151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22171.1Skamil}
22181.1Skamil
22191.1SkamilATF_TC(io_write_d3);
22201.1SkamilATF_TC_HEAD(io_write_d3, tc)
22211.1Skamil{
22221.1Skamil	atf_tc_set_md_var(tc, "descr",
22231.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint32_t)");
22241.1Skamil}
22251.1Skamil
22261.1SkamilATF_TC_BODY(io_write_d3, tc)
22271.1Skamil{
22281.1Skamil	const int exitval = 5;
22291.1Skamil	const int sigval = SIGSTOP;
22301.1Skamil	pid_t child, wpid;
22311.1Skamil	uint32_t lookup_me = 0;
22321.1Skamil	const uint32_t magic = 0xab127643;
22331.1Skamil	struct ptrace_io_desc io = {
22341.1Skamil		.piod_op = PIOD_WRITE_D,
22351.1Skamil		.piod_offs = &lookup_me,
22361.1Skamil		.piod_addr = &lookup_me,
22371.1Skamil		.piod_len = sizeof(lookup_me)
22381.1Skamil	};
22391.1Skamil#if defined(TWAIT_HAVE_STATUS)
22401.1Skamil	int status;
22411.1Skamil#endif
22421.1Skamil
22431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22451.1Skamil	if (child == 0) {
22461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22481.1Skamil
22491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22511.1Skamil
22521.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22531.1Skamil
22541.13Schristos		DPRINTF("Before exiting of the child process\n");
22551.1Skamil		_exit(exitval);
22561.1Skamil	}
22571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22581.1Skamil
22591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22611.1Skamil
22621.1Skamil	validate_status_stopped(status, sigval);
22631.1Skamil
22641.1Skamil	lookup_me = magic;
22651.1Skamil
22661.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
22671.1Skamil	    child, getpid());
22681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
22691.1Skamil
22701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22711.1Skamil	    "without signal to be sent\n");
22721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22731.1Skamil
22741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22761.1Skamil
22771.1Skamil	validate_status_exited(status, exitval);
22781.1Skamil
22791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22811.1Skamil}
22821.1Skamil
22831.1SkamilATF_TC(io_write_d4);
22841.1SkamilATF_TC_HEAD(io_write_d4, tc)
22851.1Skamil{
22861.1Skamil	atf_tc_set_md_var(tc, "descr",
22871.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint64_t)");
22881.1Skamil}
22891.1Skamil
22901.1SkamilATF_TC_BODY(io_write_d4, tc)
22911.1Skamil{
22921.1Skamil	const int exitval = 5;
22931.1Skamil	const int sigval = SIGSTOP;
22941.1Skamil	pid_t child, wpid;
22951.1Skamil	uint64_t lookup_me = 0;
22961.1Skamil	const uint64_t magic = 0xab12764376490123;
22971.1Skamil	struct ptrace_io_desc io = {
22981.1Skamil		.piod_op = PIOD_WRITE_D,
22991.1Skamil		.piod_offs = &lookup_me,
23001.1Skamil		.piod_addr = &lookup_me,
23011.1Skamil		.piod_len = sizeof(lookup_me)
23021.1Skamil	};
23031.1Skamil#if defined(TWAIT_HAVE_STATUS)
23041.1Skamil	int status;
23051.1Skamil#endif
23061.1Skamil
23071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23091.1Skamil	if (child == 0) {
23101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23121.1Skamil
23131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23151.1Skamil
23161.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
23171.1Skamil
23181.13Schristos		DPRINTF("Before exiting of the child process\n");
23191.1Skamil		_exit(exitval);
23201.1Skamil	}
23211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23221.1Skamil
23231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23251.1Skamil
23261.1Skamil	validate_status_stopped(status, sigval);
23271.1Skamil
23281.1Skamil	lookup_me = magic;
23291.1Skamil
23301.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
23311.1Skamil	    child, getpid());
23321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23331.1Skamil
23341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23351.1Skamil	    "without signal to be sent\n");
23361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23371.1Skamil
23381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23401.1Skamil
23411.1Skamil	validate_status_exited(status, exitval);
23421.1Skamil
23431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23451.1Skamil}
23461.1Skamil
23471.1SkamilATF_TC(io_read_auxv1);
23481.1SkamilATF_TC_HEAD(io_read_auxv1, tc)
23491.1Skamil{
23501.1Skamil	atf_tc_set_md_var(tc, "descr",
23511.1Skamil	    "Verify PT_READ_AUXV called for tracee");
23521.1Skamil}
23531.1Skamil
23541.1SkamilATF_TC_BODY(io_read_auxv1, tc)
23551.1Skamil{
23561.1Skamil	const int exitval = 5;
23571.1Skamil	const int sigval = SIGSTOP;
23581.1Skamil	pid_t child, wpid;
23591.1Skamil#if defined(TWAIT_HAVE_STATUS)
23601.1Skamil	int status;
23611.1Skamil#endif
23621.1Skamil	AuxInfo ai[100], *aip;
23631.1Skamil	struct ptrace_io_desc io = {
23641.1Skamil		.piod_op = PIOD_READ_AUXV,
23651.1Skamil		.piod_offs = 0,
23661.1Skamil		.piod_addr = ai,
23671.1Skamil		.piod_len = sizeof(ai)
23681.1Skamil	};
23691.1Skamil
23701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23721.1Skamil	if (child == 0) {
23731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23751.1Skamil
23761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23781.1Skamil
23791.13Schristos		DPRINTF("Before exiting of the child process\n");
23801.1Skamil		_exit(exitval);
23811.1Skamil	}
23821.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23831.1Skamil
23841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23861.1Skamil
23871.1Skamil	validate_status_stopped(status, sigval);
23881.1Skamil
23891.13Schristos	DPRINTF("Read new AUXV from tracee (PID=%d) by tracer (PID=%d)\n",
23901.1Skamil	    child, getpid());
23911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23921.1Skamil
23931.13Schristos	DPRINTF("Asserting that AUXV length (%zu) is > 0\n", io.piod_len);
23941.1Skamil	ATF_REQUIRE(io.piod_len > 0);
23951.1Skamil
23961.1Skamil	for (aip = ai; aip->a_type != AT_NULL; aip++)
23971.13Schristos		DPRINTF("a_type=%#llx a_v=%#llx\n",
23981.1Skamil		    (long long int)aip->a_type, (long long int)aip->a_v);
23991.1Skamil
24001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24011.1Skamil	    "without signal to be sent\n");
24021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24031.1Skamil
24041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24061.1Skamil
24071.1Skamil	validate_status_exited(status, exitval);
24081.1Skamil
24091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24111.1Skamil}
24121.1Skamil
24131.1SkamilATF_TC(read_d1);
24141.1SkamilATF_TC_HEAD(read_d1, tc)
24151.1Skamil{
24161.1Skamil	atf_tc_set_md_var(tc, "descr",
24171.1Skamil	    "Verify PT_READ_D called once");
24181.1Skamil}
24191.1Skamil
24201.1SkamilATF_TC_BODY(read_d1, tc)
24211.1Skamil{
24221.1Skamil	const int exitval = 5;
24231.1Skamil	const int sigval = SIGSTOP;
24241.1Skamil	pid_t child, wpid;
24251.1Skamil	int lookup_me = 0;
24261.1Skamil	const int magic = (int)random();
24271.1Skamil#if defined(TWAIT_HAVE_STATUS)
24281.1Skamil	int status;
24291.1Skamil#endif
24301.1Skamil
24311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24331.1Skamil	if (child == 0) {
24341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24361.1Skamil
24371.1Skamil		lookup_me = magic;
24381.1Skamil
24391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24411.1Skamil
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.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
24531.1Skamil	    child, getpid());
24541.1Skamil	errno = 0;
24551.1Skamil	lookup_me = ptrace(PT_READ_D, child, &lookup_me, 0);
24561.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
24571.1Skamil
24581.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
24591.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
24601.1Skamil
24611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24621.1Skamil	    "without signal to be sent\n");
24631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24641.1Skamil
24651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24671.1Skamil
24681.1Skamil	validate_status_exited(status, exitval);
24691.1Skamil
24701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24721.1Skamil}
24731.1Skamil
24741.1SkamilATF_TC(read_d2);
24751.1SkamilATF_TC_HEAD(read_d2, tc)
24761.1Skamil{
24771.1Skamil	atf_tc_set_md_var(tc, "descr",
24781.1Skamil	    "Verify PT_READ_D called twice");
24791.1Skamil}
24801.1Skamil
24811.1SkamilATF_TC_BODY(read_d2, tc)
24821.1Skamil{
24831.1Skamil	const int exitval = 5;
24841.1Skamil	const int sigval = SIGSTOP;
24851.1Skamil	pid_t child, wpid;
24861.1Skamil	int lookup_me1 = 0;
24871.1Skamil	int lookup_me2 = 0;
24881.1Skamil	const int magic1 = (int)random();
24891.1Skamil	const int magic2 = (int)random();
24901.1Skamil#if defined(TWAIT_HAVE_STATUS)
24911.1Skamil	int status;
24921.1Skamil#endif
24931.1Skamil
24941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24961.1Skamil	if (child == 0) {
24971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24991.1Skamil
25001.1Skamil		lookup_me1 = magic1;
25011.1Skamil		lookup_me2 = magic2;
25021.1Skamil
25031.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25041.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25051.1Skamil
25061.13Schristos		DPRINTF("Before exiting of the child process\n");
25071.1Skamil		_exit(exitval);
25081.1Skamil	}
25091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25101.1Skamil
25111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25131.1Skamil
25141.1Skamil	validate_status_stopped(status, sigval);
25151.1Skamil
25161.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
25171.1Skamil	    child, getpid());
25181.1Skamil	errno = 0;
25191.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25201.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25211.1Skamil
25221.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25231.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
25241.1Skamil
25251.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
25261.1Skamil	    child, getpid());
25271.1Skamil	errno = 0;
25281.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
25291.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25301.1Skamil
25311.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
25321.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
25331.1Skamil
25341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25351.1Skamil	    "without signal to be sent\n");
25361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25371.1Skamil
25381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25401.1Skamil
25411.1Skamil	validate_status_exited(status, exitval);
25421.1Skamil
25431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25451.1Skamil}
25461.1Skamil
25471.1SkamilATF_TC(read_d3);
25481.1SkamilATF_TC_HEAD(read_d3, tc)
25491.1Skamil{
25501.1Skamil	atf_tc_set_md_var(tc, "descr",
25511.1Skamil	    "Verify PT_READ_D called three times");
25521.1Skamil}
25531.1Skamil
25541.1SkamilATF_TC_BODY(read_d3, tc)
25551.1Skamil{
25561.1Skamil	const int exitval = 5;
25571.1Skamil	const int sigval = SIGSTOP;
25581.1Skamil	pid_t child, wpid;
25591.1Skamil	int lookup_me1 = 0;
25601.1Skamil	int lookup_me2 = 0;
25611.1Skamil	int lookup_me3 = 0;
25621.1Skamil	const int magic1 = (int)random();
25631.1Skamil	const int magic2 = (int)random();
25641.1Skamil	const int magic3 = (int)random();
25651.1Skamil#if defined(TWAIT_HAVE_STATUS)
25661.1Skamil	int status;
25671.1Skamil#endif
25681.1Skamil
25691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25711.1Skamil	if (child == 0) {
25721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25741.1Skamil
25751.1Skamil		lookup_me1 = magic1;
25761.1Skamil		lookup_me2 = magic2;
25771.1Skamil		lookup_me3 = magic3;
25781.1Skamil
25791.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25801.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25811.1Skamil
25821.13Schristos		DPRINTF("Before exiting of the child process\n");
25831.1Skamil		_exit(exitval);
25841.1Skamil	}
25851.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25861.1Skamil
25871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25891.1Skamil
25901.1Skamil	validate_status_stopped(status, sigval);
25911.1Skamil
25921.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
25931.1Skamil	    child, getpid());
25941.1Skamil	errno = 0;
25951.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25961.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25971.1Skamil
25981.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25991.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
26001.1Skamil
26011.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
26021.1Skamil	    child, getpid());
26031.1Skamil	errno = 0;
26041.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
26051.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26061.1Skamil
26071.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
26081.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
26091.1Skamil
26101.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
26111.1Skamil	    child, getpid());
26121.1Skamil	errno = 0;
26131.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
26141.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26151.1Skamil
26161.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
26171.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
26181.1Skamil
26191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26201.1Skamil	    "without signal to be sent\n");
26211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26221.1Skamil
26231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26251.1Skamil
26261.1Skamil	validate_status_exited(status, exitval);
26271.1Skamil
26281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26301.1Skamil}
26311.1Skamil
26321.1SkamilATF_TC(read_d4);
26331.1SkamilATF_TC_HEAD(read_d4, tc)
26341.1Skamil{
26351.1Skamil	atf_tc_set_md_var(tc, "descr",
26361.1Skamil	    "Verify PT_READ_D called four times");
26371.1Skamil}
26381.1Skamil
26391.1SkamilATF_TC_BODY(read_d4, tc)
26401.1Skamil{
26411.1Skamil	const int exitval = 5;
26421.1Skamil	const int sigval = SIGSTOP;
26431.1Skamil	pid_t child, wpid;
26441.1Skamil	int lookup_me1 = 0;
26451.1Skamil	int lookup_me2 = 0;
26461.1Skamil	int lookup_me3 = 0;
26471.1Skamil	int lookup_me4 = 0;
26481.1Skamil	const int magic1 = (int)random();
26491.1Skamil	const int magic2 = (int)random();
26501.1Skamil	const int magic3 = (int)random();
26511.1Skamil	const int magic4 = (int)random();
26521.1Skamil#if defined(TWAIT_HAVE_STATUS)
26531.1Skamil	int status;
26541.1Skamil#endif
26551.1Skamil
26561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26581.1Skamil	if (child == 0) {
26591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26611.1Skamil
26621.1Skamil		lookup_me1 = magic1;
26631.1Skamil		lookup_me2 = magic2;
26641.1Skamil		lookup_me3 = magic3;
26651.1Skamil		lookup_me4 = magic4;
26661.1Skamil
26671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26691.1Skamil
26701.13Schristos		DPRINTF("Before exiting of the child process\n");
26711.1Skamil		_exit(exitval);
26721.1Skamil	}
26731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26741.1Skamil
26751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26771.1Skamil
26781.1Skamil	validate_status_stopped(status, sigval);
26791.1Skamil
26801.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
26811.1Skamil	    child, getpid());
26821.1Skamil	errno = 0;
26831.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
26841.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26851.1Skamil
26861.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
26871.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
26881.1Skamil
26891.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
26901.1Skamil	    child, getpid());
26911.1Skamil	errno = 0;
26921.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
26931.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26941.1Skamil
26951.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
26961.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
26971.1Skamil
26981.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
26991.1Skamil	    child, getpid());
27001.1Skamil	errno = 0;
27011.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
27021.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
27031.1Skamil
27041.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
27051.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
27061.1Skamil
27071.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
27081.1Skamil	    child, getpid());
27091.1Skamil	errno = 0;
27101.1Skamil	lookup_me4 = ptrace(PT_READ_D, child, &lookup_me4, 0);
27111.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
27121.1Skamil
27131.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
27141.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
27151.1Skamil
27161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27171.1Skamil	    "without signal to be sent\n");
27181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27191.1Skamil
27201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27221.1Skamil
27231.1Skamil	validate_status_exited(status, exitval);
27241.1Skamil
27251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27271.1Skamil}
27281.1Skamil
27291.1SkamilATF_TC(write_d1);
27301.1SkamilATF_TC_HEAD(write_d1, tc)
27311.1Skamil{
27321.1Skamil	atf_tc_set_md_var(tc, "descr",
27331.1Skamil	    "Verify PT_WRITE_D called once");
27341.1Skamil}
27351.1Skamil
27361.1SkamilATF_TC_BODY(write_d1, tc)
27371.1Skamil{
27381.1Skamil	const int exitval = 5;
27391.1Skamil	const int sigval = SIGSTOP;
27401.1Skamil	pid_t child, wpid;
27411.1Skamil	int lookup_me = 0;
27421.1Skamil	const int magic = (int)random();
27431.1Skamil#if defined(TWAIT_HAVE_STATUS)
27441.1Skamil	int status;
27451.1Skamil#endif
27461.1Skamil
27471.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27481.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27491.1Skamil	if (child == 0) {
27501.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27511.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27521.1Skamil
27531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27551.1Skamil
27561.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
27571.1Skamil
27581.13Schristos		DPRINTF("Before exiting of the child process\n");
27591.1Skamil		_exit(exitval);
27601.1Skamil	}
27611.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27621.1Skamil
27631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27651.1Skamil
27661.1Skamil	validate_status_stopped(status, sigval);
27671.1Skamil
27681.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
27691.1Skamil	    child, getpid());
27701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me, magic) != -1);
27711.1Skamil
27721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27731.1Skamil	    "without signal to be sent\n");
27741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27751.1Skamil
27761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27781.1Skamil
27791.1Skamil	validate_status_exited(status, exitval);
27801.1Skamil
27811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27831.1Skamil}
27841.1Skamil
27851.1SkamilATF_TC(write_d2);
27861.1SkamilATF_TC_HEAD(write_d2, tc)
27871.1Skamil{
27881.1Skamil	atf_tc_set_md_var(tc, "descr",
27891.1Skamil	    "Verify PT_WRITE_D called twice");
27901.1Skamil}
27911.1Skamil
27921.1SkamilATF_TC_BODY(write_d2, tc)
27931.1Skamil{
27941.1Skamil	const int exitval = 5;
27951.1Skamil	const int sigval = SIGSTOP;
27961.1Skamil	pid_t child, wpid;
27971.1Skamil	int lookup_me1 = 0;
27981.1Skamil	int lookup_me2 = 0;
27991.1Skamil	const int magic1 = (int)random();
28001.1Skamil	const int magic2 = (int)random();
28011.1Skamil#if defined(TWAIT_HAVE_STATUS)
28021.1Skamil	int status;
28031.1Skamil#endif
28041.1Skamil
28051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28071.1Skamil	if (child == 0) {
28081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28101.1Skamil
28111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28131.1Skamil
28141.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
28151.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
28161.1Skamil
28171.13Schristos		DPRINTF("Before exiting of the child process\n");
28181.1Skamil		_exit(exitval);
28191.1Skamil	}
28201.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28211.1Skamil
28221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28241.1Skamil
28251.1Skamil	validate_status_stopped(status, sigval);
28261.1Skamil
28271.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28281.1Skamil	    child, getpid());
28291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28301.1Skamil
28311.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28321.1Skamil	    child, getpid());
28331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28341.1Skamil
28351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28361.1Skamil	    "without signal to be sent\n");
28371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28381.1Skamil
28391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28411.1Skamil
28421.1Skamil	validate_status_exited(status, exitval);
28431.1Skamil
28441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28461.1Skamil}
28471.1Skamil
28481.1SkamilATF_TC(write_d3);
28491.1SkamilATF_TC_HEAD(write_d3, tc)
28501.1Skamil{
28511.1Skamil	atf_tc_set_md_var(tc, "descr",
28521.1Skamil	    "Verify PT_WRITE_D called three times");
28531.1Skamil}
28541.1Skamil
28551.1SkamilATF_TC_BODY(write_d3, tc)
28561.1Skamil{
28571.1Skamil	const int exitval = 5;
28581.1Skamil	const int sigval = SIGSTOP;
28591.1Skamil	pid_t child, wpid;
28601.1Skamil	int lookup_me1 = 0;
28611.1Skamil	int lookup_me2 = 0;
28621.1Skamil	int lookup_me3 = 0;
28631.1Skamil	const int magic1 = (int)random();
28641.1Skamil	const int magic2 = (int)random();
28651.1Skamil	const int magic3 = (int)random();
28661.1Skamil#if defined(TWAIT_HAVE_STATUS)
28671.1Skamil	int status;
28681.1Skamil#endif
28691.1Skamil
28701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28721.1Skamil	if (child == 0) {
28731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28751.1Skamil
28761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28781.1Skamil
28791.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
28801.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
28811.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
28821.1Skamil
28831.13Schristos		DPRINTF("Before exiting of the child process\n");
28841.1Skamil		_exit(exitval);
28851.1Skamil	}
28861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28871.1Skamil
28881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28901.1Skamil
28911.1Skamil	validate_status_stopped(status, sigval);
28921.1Skamil
28931.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28941.1Skamil	    child, getpid());
28951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28961.1Skamil
28971.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28981.1Skamil	    child, getpid());
28991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
29001.1Skamil
29011.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
29021.1Skamil	    child, getpid());
29031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
29041.1Skamil
29051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29061.1Skamil	    "without signal to be sent\n");
29071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29081.1Skamil
29091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29111.1Skamil
29121.1Skamil	validate_status_exited(status, exitval);
29131.1Skamil
29141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29161.1Skamil}
29171.1Skamil
29181.1SkamilATF_TC(write_d4);
29191.1SkamilATF_TC_HEAD(write_d4, tc)
29201.1Skamil{
29211.1Skamil	atf_tc_set_md_var(tc, "descr",
29221.1Skamil	    "Verify PT_WRITE_D called four times");
29231.1Skamil}
29241.1Skamil
29251.1SkamilATF_TC_BODY(write_d4, tc)
29261.1Skamil{
29271.1Skamil	const int exitval = 5;
29281.1Skamil	const int sigval = SIGSTOP;
29291.1Skamil	pid_t child, wpid;
29301.1Skamil	int lookup_me1 = 0;
29311.1Skamil	int lookup_me2 = 0;
29321.1Skamil	int lookup_me3 = 0;
29331.1Skamil	int lookup_me4 = 0;
29341.1Skamil	const int magic1 = (int)random();
29351.1Skamil	const int magic2 = (int)random();
29361.1Skamil	const int magic3 = (int)random();
29371.1Skamil	const int magic4 = (int)random();
29381.1Skamil#if defined(TWAIT_HAVE_STATUS)
29391.1Skamil	int status;
29401.1Skamil#endif
29411.1Skamil
29421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29441.1Skamil	if (child == 0) {
29451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29471.1Skamil
29481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29501.1Skamil
29511.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
29521.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
29531.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
29541.1Skamil		FORKEE_ASSERT_EQ(lookup_me4, magic4);
29551.1Skamil
29561.13Schristos		DPRINTF("Before exiting of the child process\n");
29571.1Skamil		_exit(exitval);
29581.1Skamil	}
29591.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29601.1Skamil
29611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29631.1Skamil
29641.1Skamil	validate_status_stopped(status, sigval);
29651.1Skamil
29661.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
29671.1Skamil	    child, getpid());
29681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
29691.1Skamil
29701.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
29711.1Skamil	    child, getpid());
29721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
29731.1Skamil
29741.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
29751.1Skamil	    child, getpid());
29761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
29771.1Skamil
29781.13Schristos	DPRINTF("Write new lookup_me4 to tracee (PID=%d) from tracer (PID=%d)\n",
29791.1Skamil	    child, getpid());
29801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me4, magic4) != -1);
29811.1Skamil
29821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29831.1Skamil	    "without signal to be sent\n");
29841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29851.1Skamil
29861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29881.1Skamil
29891.1Skamil	validate_status_exited(status, exitval);
29901.1Skamil
29911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29931.1Skamil}
29941.1Skamil
29951.1SkamilATF_TC(io_read_d_write_d_handshake1);
29961.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake1, tc)
29971.1Skamil{
29981.1Skamil	atf_tc_set_md_var(tc, "descr",
29991.1Skamil	    "Verify PT_IO with PIOD_READ_D and PIOD_WRITE_D handshake");
30001.1Skamil}
30011.1Skamil
30021.1SkamilATF_TC_BODY(io_read_d_write_d_handshake1, tc)
30031.1Skamil{
30041.1Skamil	const int exitval = 5;
30051.1Skamil	const int sigval = SIGSTOP;
30061.1Skamil	pid_t child, wpid;
30071.1Skamil	uint8_t lookup_me_fromtracee = 0;
30081.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
30091.1Skamil	uint8_t lookup_me_totracee = 0;
30101.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
30111.1Skamil	struct ptrace_io_desc io_fromtracee = {
30121.1Skamil		.piod_op = PIOD_READ_D,
30131.1Skamil		.piod_offs = &lookup_me_fromtracee,
30141.1Skamil		.piod_addr = &lookup_me_fromtracee,
30151.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
30161.1Skamil	};
30171.1Skamil	struct ptrace_io_desc io_totracee = {
30181.1Skamil		.piod_op = PIOD_WRITE_D,
30191.1Skamil		.piod_offs = &lookup_me_totracee,
30201.1Skamil		.piod_addr = &lookup_me_totracee,
30211.1Skamil		.piod_len = sizeof(lookup_me_totracee)
30221.1Skamil	};
30231.1Skamil#if defined(TWAIT_HAVE_STATUS)
30241.1Skamil	int status;
30251.1Skamil#endif
30261.1Skamil
30271.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30281.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30291.1Skamil	if (child == 0) {
30301.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30311.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30321.1Skamil
30331.1Skamil		lookup_me_fromtracee = magic_fromtracee;
30341.1Skamil
30351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30371.1Skamil
30381.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
30391.1Skamil
30401.13Schristos		DPRINTF("Before exiting of the child process\n");
30411.1Skamil		_exit(exitval);
30421.1Skamil	}
30431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30441.1Skamil
30451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30471.1Skamil
30481.1Skamil	validate_status_stopped(status, sigval);
30491.1Skamil
30501.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
30511.1Skamil	    child, getpid());
30521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
30531.1Skamil
30541.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
30551.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
30561.1Skamil	    magic_fromtracee);
30571.1Skamil
30581.1Skamil	lookup_me_totracee = magic_totracee;
30591.1Skamil
30601.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
30611.1Skamil	    child, getpid());
30621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
30631.1Skamil
30641.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
30651.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
30661.1Skamil	    magic_totracee);
30671.1Skamil
30681.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30691.1Skamil	    "without signal to be sent\n");
30701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30711.1Skamil
30721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30741.1Skamil
30751.1Skamil	validate_status_exited(status, exitval);
30761.1Skamil
30771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30791.1Skamil}
30801.1Skamil
30811.1SkamilATF_TC(io_read_d_write_d_handshake2);
30821.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake2, tc)
30831.1Skamil{
30841.1Skamil	atf_tc_set_md_var(tc, "descr",
30851.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and PIOD_READ_D handshake");
30861.1Skamil}
30871.1Skamil
30881.1SkamilATF_TC_BODY(io_read_d_write_d_handshake2, tc)
30891.1Skamil{
30901.1Skamil	const int exitval = 5;
30911.1Skamil	const int sigval = SIGSTOP;
30921.1Skamil	pid_t child, wpid;
30931.1Skamil	uint8_t lookup_me_fromtracee = 0;
30941.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
30951.1Skamil	uint8_t lookup_me_totracee = 0;
30961.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
30971.1Skamil	struct ptrace_io_desc io_fromtracee = {
30981.1Skamil		.piod_op = PIOD_READ_D,
30991.1Skamil		.piod_offs = &lookup_me_fromtracee,
31001.1Skamil		.piod_addr = &lookup_me_fromtracee,
31011.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
31021.1Skamil	};
31031.1Skamil	struct ptrace_io_desc io_totracee = {
31041.1Skamil		.piod_op = PIOD_WRITE_D,
31051.1Skamil		.piod_offs = &lookup_me_totracee,
31061.1Skamil		.piod_addr = &lookup_me_totracee,
31071.1Skamil		.piod_len = sizeof(lookup_me_totracee)
31081.1Skamil	};
31091.1Skamil#if defined(TWAIT_HAVE_STATUS)
31101.1Skamil	int status;
31111.1Skamil#endif
31121.1Skamil
31131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31151.1Skamil	if (child == 0) {
31161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31181.1Skamil
31191.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31201.1Skamil
31211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31231.1Skamil
31241.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31251.1Skamil
31261.13Schristos		DPRINTF("Before exiting of the child process\n");
31271.1Skamil		_exit(exitval);
31281.1Skamil	}
31291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31301.1Skamil
31311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31331.1Skamil
31341.1Skamil	validate_status_stopped(status, sigval);
31351.1Skamil
31361.1Skamil	lookup_me_totracee = magic_totracee;
31371.1Skamil
31381.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
31391.1Skamil	    child, getpid());
31401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
31411.1Skamil
31421.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
31431.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
31441.1Skamil	    magic_totracee);
31451.1Skamil
31461.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
31471.1Skamil	    child, getpid());
31481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
31491.1Skamil
31501.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
31511.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
31521.1Skamil	    magic_fromtracee);
31531.1Skamil
31541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31551.1Skamil	    "without signal to be sent\n");
31561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31571.1Skamil
31581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31601.1Skamil
31611.1Skamil	validate_status_exited(status, exitval);
31621.1Skamil
31631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31651.1Skamil}
31661.1Skamil
31671.1SkamilATF_TC(read_d_write_d_handshake1);
31681.1SkamilATF_TC_HEAD(read_d_write_d_handshake1, tc)
31691.1Skamil{
31701.1Skamil	atf_tc_set_md_var(tc, "descr",
31711.1Skamil	    "Verify PT_READ_D with PT_WRITE_D handshake");
31721.1Skamil}
31731.1Skamil
31741.1SkamilATF_TC_BODY(read_d_write_d_handshake1, tc)
31751.1Skamil{
31761.1Skamil	const int exitval = 5;
31771.1Skamil	const int sigval = SIGSTOP;
31781.1Skamil	pid_t child, wpid;
31791.1Skamil	int lookup_me_fromtracee = 0;
31801.1Skamil	const int magic_fromtracee = (int)random();
31811.1Skamil	int lookup_me_totracee = 0;
31821.1Skamil	const int magic_totracee = (int)random();
31831.1Skamil#if defined(TWAIT_HAVE_STATUS)
31841.1Skamil	int status;
31851.1Skamil#endif
31861.1Skamil
31871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31891.1Skamil	if (child == 0) {
31901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31921.1Skamil
31931.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31941.1Skamil
31951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31971.1Skamil
31981.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31991.1Skamil
32001.13Schristos		DPRINTF("Before exiting of the child process\n");
32011.1Skamil		_exit(exitval);
32021.1Skamil	}
32031.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32041.1Skamil
32051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32071.1Skamil
32081.1Skamil	validate_status_stopped(status, sigval);
32091.1Skamil
32101.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
32111.1Skamil	    child, getpid());
32121.1Skamil	errno = 0;
32131.1Skamil	lookup_me_fromtracee =
32141.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
32151.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
32161.1Skamil
32171.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
32181.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
32191.1Skamil	    magic_fromtracee);
32201.1Skamil
32211.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32221.1Skamil	    child, getpid());
32231.1Skamil	ATF_REQUIRE
32241.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32251.1Skamil	    != -1);
32261.1Skamil
32271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32281.1Skamil	    "without signal to be sent\n");
32291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32301.1Skamil
32311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32331.1Skamil
32341.1Skamil	validate_status_exited(status, exitval);
32351.1Skamil
32361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32381.1Skamil}
32391.1Skamil
32401.1SkamilATF_TC(read_d_write_d_handshake2);
32411.1SkamilATF_TC_HEAD(read_d_write_d_handshake2, tc)
32421.1Skamil{
32431.1Skamil	atf_tc_set_md_var(tc, "descr",
32441.1Skamil	    "Verify PT_WRITE_D with PT_READ_D handshake");
32451.1Skamil}
32461.1Skamil
32471.1SkamilATF_TC_BODY(read_d_write_d_handshake2, tc)
32481.1Skamil{
32491.1Skamil	const int exitval = 5;
32501.1Skamil	const int sigval = SIGSTOP;
32511.1Skamil	pid_t child, wpid;
32521.1Skamil	int lookup_me_fromtracee = 0;
32531.1Skamil	const int magic_fromtracee = (int)random();
32541.1Skamil	int lookup_me_totracee = 0;
32551.1Skamil	const int magic_totracee = (int)random();
32561.1Skamil#if defined(TWAIT_HAVE_STATUS)
32571.1Skamil	int status;
32581.1Skamil#endif
32591.1Skamil
32601.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32611.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32621.1Skamil	if (child == 0) {
32631.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32641.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32651.1Skamil
32661.1Skamil		lookup_me_fromtracee = magic_fromtracee;
32671.1Skamil
32681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32701.1Skamil
32711.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
32721.1Skamil
32731.13Schristos		DPRINTF("Before exiting of the child process\n");
32741.1Skamil		_exit(exitval);
32751.1Skamil	}
32761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32771.1Skamil
32781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32801.1Skamil
32811.1Skamil	validate_status_stopped(status, sigval);
32821.1Skamil
32831.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32841.1Skamil	    child, getpid());
32851.1Skamil	ATF_REQUIRE
32861.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32871.1Skamil	    != -1);
32881.1Skamil
32891.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
32901.1Skamil	    child, getpid());
32911.1Skamil	errno = 0;
32921.1Skamil	lookup_me_fromtracee =
32931.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
32941.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
32951.1Skamil
32961.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
32971.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
32981.1Skamil	    magic_fromtracee);
32991.1Skamil
33001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33011.1Skamil	    "without signal to be sent\n");
33021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33031.1Skamil
33041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33061.1Skamil
33071.1Skamil	validate_status_exited(status, exitval);
33081.1Skamil
33091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33111.1Skamil}
33121.1Skamil
33131.1Skamil/* These dummy functions are used to be copied with ptrace(2) calls */
33141.1Skamilstatic int __used
33151.1Skamildummy_fn1(int a, int b, int c, int d)
33161.1Skamil{
33171.1Skamil
33181.1Skamil	a *= 1;
33191.1Skamil	b += 2;
33201.1Skamil	c -= 3;
33211.1Skamil	d /= 4;
33221.1Skamil
33231.1Skamil	return a + b * c - d;
33241.1Skamil}
33251.1Skamil
33261.1Skamilstatic int __used
33271.1Skamildummy_fn2(int a, int b, int c, int d)
33281.1Skamil{
33291.1Skamil
33301.1Skamil	a *= 4;
33311.1Skamil	b += 3;
33321.1Skamil	c -= 2;
33331.1Skamil	d /= 1;
33341.1Skamil
33351.1Skamil	return a + b * c - d;
33361.1Skamil}
33371.1Skamil
33381.1Skamilstatic int __used
33391.1Skamildummy_fn3(int a, int b, int c, int d)
33401.1Skamil{
33411.1Skamil
33421.1Skamil	a *= 10;
33431.1Skamil	b += 20;
33441.1Skamil	c -= 30;
33451.1Skamil	d /= 40;
33461.1Skamil
33471.1Skamil	return a + b * c - d;
33481.1Skamil}
33491.1Skamil
33501.1Skamilstatic int __used
33511.1Skamildummy_fn4(int a, int b, int c, int d)
33521.1Skamil{
33531.1Skamil
33541.1Skamil	a *= 40;
33551.1Skamil	b += 30;
33561.1Skamil	c -= 20;
33571.1Skamil	d /= 10;
33581.1Skamil
33591.1Skamil	return a + b * c - d;
33601.1Skamil}
33611.1Skamil
33621.1SkamilATF_TC(io_read_i1);
33631.1SkamilATF_TC_HEAD(io_read_i1, tc)
33641.1Skamil{
33651.1Skamil	atf_tc_set_md_var(tc, "descr",
33661.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint8_t)");
33671.1Skamil}
33681.1Skamil
33691.1SkamilATF_TC_BODY(io_read_i1, tc)
33701.1Skamil{
33711.1Skamil	const int exitval = 5;
33721.1Skamil	const int sigval = SIGSTOP;
33731.1Skamil	pid_t child, wpid;
33741.1Skamil	uint8_t lookup_me = 0;
33751.1Skamil	uint8_t magic;
33761.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
33771.1Skamil	struct ptrace_io_desc io = {
33781.1Skamil		.piod_op = PIOD_READ_I,
33791.1Skamil		.piod_offs = dummy_fn1,
33801.1Skamil		.piod_addr = &lookup_me,
33811.1Skamil		.piod_len = sizeof(lookup_me)
33821.1Skamil	};
33831.1Skamil#if defined(TWAIT_HAVE_STATUS)
33841.1Skamil	int status;
33851.1Skamil#endif
33861.1Skamil
33871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33891.1Skamil	if (child == 0) {
33901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33921.1Skamil
33931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33951.1Skamil
33961.13Schristos		DPRINTF("Before exiting of the child process\n");
33971.1Skamil		_exit(exitval);
33981.1Skamil	}
33991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34001.1Skamil
34011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34031.1Skamil
34041.1Skamil	validate_status_stopped(status, sigval);
34051.1Skamil
34061.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
34071.1Skamil	    child, getpid());
34081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
34091.1Skamil
34101.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
34111.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
34121.1Skamil
34131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34141.1Skamil	    "without signal to be sent\n");
34151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34161.1Skamil
34171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34191.1Skamil
34201.1Skamil	validate_status_exited(status, exitval);
34211.1Skamil
34221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34241.1Skamil}
34251.1Skamil
34261.1SkamilATF_TC(io_read_i2);
34271.1SkamilATF_TC_HEAD(io_read_i2, tc)
34281.1Skamil{
34291.1Skamil	atf_tc_set_md_var(tc, "descr",
34301.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint16_t)");
34311.1Skamil}
34321.1Skamil
34331.1SkamilATF_TC_BODY(io_read_i2, tc)
34341.1Skamil{
34351.1Skamil	const int exitval = 5;
34361.1Skamil	const int sigval = SIGSTOP;
34371.1Skamil	pid_t child, wpid;
34381.1Skamil	uint16_t lookup_me = 0;
34391.1Skamil	uint16_t magic;
34401.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34411.1Skamil	struct ptrace_io_desc io = {
34421.1Skamil		.piod_op = PIOD_READ_I,
34431.1Skamil		.piod_offs = dummy_fn1,
34441.1Skamil		.piod_addr = &lookup_me,
34451.1Skamil		.piod_len = sizeof(lookup_me)
34461.1Skamil	};
34471.1Skamil#if defined(TWAIT_HAVE_STATUS)
34481.1Skamil	int status;
34491.1Skamil#endif
34501.1Skamil
34511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34531.1Skamil	if (child == 0) {
34541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34561.1Skamil
34571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34591.1Skamil
34601.13Schristos		DPRINTF("Before exiting of the child process\n");
34611.1Skamil		_exit(exitval);
34621.1Skamil	}
34631.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34641.1Skamil
34651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34671.1Skamil
34681.1Skamil	validate_status_stopped(status, sigval);
34691.1Skamil
34701.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
34711.1Skamil	    child, getpid());
34721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
34731.1Skamil
34741.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
34751.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
34761.1Skamil
34771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34781.1Skamil	    "without signal to be sent\n");
34791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34801.1Skamil
34811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34831.1Skamil
34841.1Skamil	validate_status_exited(status, exitval);
34851.1Skamil
34861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34881.1Skamil}
34891.1Skamil
34901.1SkamilATF_TC(io_read_i3);
34911.1SkamilATF_TC_HEAD(io_read_i3, tc)
34921.1Skamil{
34931.1Skamil	atf_tc_set_md_var(tc, "descr",
34941.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint32_t)");
34951.1Skamil}
34961.1Skamil
34971.1SkamilATF_TC_BODY(io_read_i3, tc)
34981.1Skamil{
34991.1Skamil	const int exitval = 5;
35001.1Skamil	const int sigval = SIGSTOP;
35011.1Skamil	pid_t child, wpid;
35021.1Skamil	uint32_t lookup_me = 0;
35031.1Skamil	uint32_t magic;
35041.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
35051.1Skamil	struct ptrace_io_desc io = {
35061.1Skamil		.piod_op = PIOD_READ_I,
35071.1Skamil		.piod_offs = dummy_fn1,
35081.1Skamil		.piod_addr = &lookup_me,
35091.1Skamil		.piod_len = sizeof(lookup_me)
35101.1Skamil	};
35111.1Skamil#if defined(TWAIT_HAVE_STATUS)
35121.1Skamil	int status;
35131.1Skamil#endif
35141.1Skamil
35151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35171.1Skamil	if (child == 0) {
35181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35201.1Skamil
35211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35231.1Skamil
35241.13Schristos		DPRINTF("Before exiting of the child process\n");
35251.1Skamil		_exit(exitval);
35261.1Skamil	}
35271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35281.1Skamil
35291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35311.1Skamil
35321.1Skamil	validate_status_stopped(status, sigval);
35331.1Skamil
35341.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35351.1Skamil	    child, getpid());
35361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35371.1Skamil
35381.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35391.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
35401.1Skamil
35411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35421.1Skamil	    "without signal to be sent\n");
35431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35441.1Skamil
35451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35471.1Skamil
35481.1Skamil	validate_status_exited(status, exitval);
35491.1Skamil
35501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35521.1Skamil}
35531.1Skamil
35541.1SkamilATF_TC(io_read_i4);
35551.1SkamilATF_TC_HEAD(io_read_i4, tc)
35561.1Skamil{
35571.1Skamil	atf_tc_set_md_var(tc, "descr",
35581.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint64_t)");
35591.1Skamil}
35601.1Skamil
35611.1SkamilATF_TC_BODY(io_read_i4, tc)
35621.1Skamil{
35631.1Skamil	const int exitval = 5;
35641.1Skamil	const int sigval = SIGSTOP;
35651.1Skamil	pid_t child, wpid;
35661.1Skamil	uint64_t lookup_me = 0;
35671.1Skamil	uint64_t magic;
35681.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
35691.1Skamil	struct ptrace_io_desc io = {
35701.1Skamil		.piod_op = PIOD_READ_I,
35711.1Skamil		.piod_offs = dummy_fn1,
35721.1Skamil		.piod_addr = &lookup_me,
35731.1Skamil		.piod_len = sizeof(lookup_me)
35741.1Skamil	};
35751.1Skamil#if defined(TWAIT_HAVE_STATUS)
35761.1Skamil	int status;
35771.1Skamil#endif
35781.1Skamil
35791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35811.1Skamil	if (child == 0) {
35821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35841.1Skamil
35851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35871.1Skamil
35881.13Schristos		DPRINTF("Before exiting of the child process\n");
35891.1Skamil		_exit(exitval);
35901.1Skamil	}
35911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35921.1Skamil
35931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35951.1Skamil
35961.1Skamil	validate_status_stopped(status, sigval);
35971.1Skamil
35981.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35991.1Skamil	    child, getpid());
36001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
36011.1Skamil
36021.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
36031.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
36041.1Skamil
36051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36061.1Skamil	    "without signal to be sent\n");
36071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36081.1Skamil
36091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36111.1Skamil
36121.1Skamil	validate_status_exited(status, exitval);
36131.1Skamil
36141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36161.1Skamil}
36171.1Skamil
36181.1SkamilATF_TC(read_i1);
36191.1SkamilATF_TC_HEAD(read_i1, tc)
36201.1Skamil{
36211.1Skamil	atf_tc_set_md_var(tc, "descr",
36221.1Skamil	    "Verify PT_READ_I called once");
36231.1Skamil}
36241.1Skamil
36251.1SkamilATF_TC_BODY(read_i1, tc)
36261.1Skamil{
36271.1Skamil	const int exitval = 5;
36281.1Skamil	const int sigval = SIGSTOP;
36291.1Skamil	pid_t child, wpid;
36301.1Skamil	int lookup_me = 0;
36311.1Skamil	int magic;
36321.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
36331.1Skamil#if defined(TWAIT_HAVE_STATUS)
36341.1Skamil	int status;
36351.1Skamil#endif
36361.1Skamil
36371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36391.1Skamil	if (child == 0) {
36401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36421.1Skamil
36431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36451.1Skamil
36461.13Schristos		DPRINTF("Before exiting of the child process\n");
36471.1Skamil		_exit(exitval);
36481.1Skamil	}
36491.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36501.1Skamil
36511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36531.1Skamil
36541.1Skamil	validate_status_stopped(status, sigval);
36551.1Skamil
36561.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
36571.1Skamil	    child, getpid());
36581.1Skamil	errno = 0;
36591.1Skamil	lookup_me = ptrace(PT_READ_I, child, dummy_fn1, 0);
36601.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
36611.1Skamil
36621.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
36631.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
36641.1Skamil
36651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36661.1Skamil	    "without signal to be sent\n");
36671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36681.1Skamil
36691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36711.1Skamil
36721.1Skamil	validate_status_exited(status, exitval);
36731.1Skamil
36741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36751.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36761.1Skamil}
36771.1Skamil
36781.1SkamilATF_TC(read_i2);
36791.1SkamilATF_TC_HEAD(read_i2, tc)
36801.1Skamil{
36811.1Skamil	atf_tc_set_md_var(tc, "descr",
36821.1Skamil	    "Verify PT_READ_I called twice");
36831.1Skamil}
36841.1Skamil
36851.1SkamilATF_TC_BODY(read_i2, tc)
36861.1Skamil{
36871.1Skamil	const int exitval = 5;
36881.1Skamil	const int sigval = SIGSTOP;
36891.1Skamil	pid_t child, wpid;
36901.1Skamil	int lookup_me1 = 0;
36911.1Skamil	int lookup_me2 = 0;
36921.1Skamil	int magic1;
36931.1Skamil	int magic2;
36941.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
36951.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
36961.1Skamil#if defined(TWAIT_HAVE_STATUS)
36971.1Skamil	int status;
36981.1Skamil#endif
36991.1Skamil
37001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37021.1Skamil	if (child == 0) {
37031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37051.1Skamil
37061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37081.1Skamil
37091.13Schristos		DPRINTF("Before exiting of the child process\n");
37101.1Skamil		_exit(exitval);
37111.1Skamil	}
37121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37131.1Skamil
37141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37161.1Skamil
37171.1Skamil	validate_status_stopped(status, sigval);
37181.1Skamil
37191.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37201.1Skamil	    child, getpid());
37211.1Skamil	errno = 0;
37221.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37231.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37241.1Skamil
37251.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
37261.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
37271.1Skamil
37281.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
37291.1Skamil	    child, getpid());
37301.1Skamil	errno = 0;
37311.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
37321.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37331.1Skamil
37341.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
37351.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
37361.1Skamil
37371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37381.1Skamil	    "without signal to be sent\n");
37391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37401.1Skamil
37411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37431.1Skamil
37441.1Skamil	validate_status_exited(status, exitval);
37451.1Skamil
37461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37481.1Skamil}
37491.1Skamil
37501.1SkamilATF_TC(read_i3);
37511.1SkamilATF_TC_HEAD(read_i3, tc)
37521.1Skamil{
37531.1Skamil	atf_tc_set_md_var(tc, "descr",
37541.1Skamil	    "Verify PT_READ_I called three times");
37551.1Skamil}
37561.1Skamil
37571.1SkamilATF_TC_BODY(read_i3, tc)
37581.1Skamil{
37591.1Skamil	const int exitval = 5;
37601.1Skamil	const int sigval = SIGSTOP;
37611.1Skamil	pid_t child, wpid;
37621.1Skamil	int lookup_me1 = 0;
37631.1Skamil	int lookup_me2 = 0;
37641.1Skamil	int lookup_me3 = 0;
37651.1Skamil	int magic1;
37661.1Skamil	int magic2;
37671.1Skamil	int magic3;
37681.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
37691.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
37701.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
37711.1Skamil#if defined(TWAIT_HAVE_STATUS)
37721.1Skamil	int status;
37731.1Skamil#endif
37741.1Skamil
37751.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37761.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37771.1Skamil	if (child == 0) {
37781.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37791.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37801.1Skamil
37811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37831.1Skamil
37841.13Schristos		DPRINTF("Before exiting of the child process\n");
37851.1Skamil		_exit(exitval);
37861.1Skamil	}
37871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37881.1Skamil
37891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37911.1Skamil
37921.1Skamil	validate_status_stopped(status, sigval);
37931.1Skamil
37941.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37951.1Skamil	    child, getpid());
37961.1Skamil	errno = 0;
37971.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37981.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37991.1Skamil
38001.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
38011.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
38021.1Skamil
38031.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
38041.1Skamil	    child, getpid());
38051.1Skamil	errno = 0;
38061.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
38071.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38081.1Skamil
38091.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
38101.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
38111.1Skamil
38121.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
38131.1Skamil	    child, getpid());
38141.1Skamil	errno = 0;
38151.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
38161.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38171.1Skamil
38181.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
38191.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
38201.1Skamil
38211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38221.1Skamil	    "without signal to be sent\n");
38231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38241.1Skamil
38251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38271.1Skamil
38281.1Skamil	validate_status_exited(status, exitval);
38291.1Skamil
38301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38321.1Skamil}
38331.1Skamil
38341.1SkamilATF_TC(read_i4);
38351.1SkamilATF_TC_HEAD(read_i4, tc)
38361.1Skamil{
38371.1Skamil	atf_tc_set_md_var(tc, "descr",
38381.1Skamil	    "Verify PT_READ_I called four times");
38391.1Skamil}
38401.1Skamil
38411.1SkamilATF_TC_BODY(read_i4, tc)
38421.1Skamil{
38431.1Skamil	const int exitval = 5;
38441.1Skamil	const int sigval = SIGSTOP;
38451.1Skamil	pid_t child, wpid;
38461.1Skamil	int lookup_me1 = 0;
38471.1Skamil	int lookup_me2 = 0;
38481.1Skamil	int lookup_me3 = 0;
38491.1Skamil	int lookup_me4 = 0;
38501.1Skamil	int magic1;
38511.1Skamil	int magic2;
38521.1Skamil	int magic3;
38531.1Skamil	int magic4;
38541.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
38551.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
38561.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
38571.1Skamil	memcpy(&magic4, dummy_fn4, sizeof(magic4));
38581.1Skamil#if defined(TWAIT_HAVE_STATUS)
38591.1Skamil	int status;
38601.1Skamil#endif
38611.1Skamil
38621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38641.1Skamil	if (child == 0) {
38651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38671.1Skamil
38681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38701.1Skamil
38711.13Schristos		DPRINTF("Before exiting of the child process\n");
38721.1Skamil		_exit(exitval);
38731.1Skamil	}
38741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38751.1Skamil
38761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38781.1Skamil
38791.1Skamil	validate_status_stopped(status, sigval);
38801.1Skamil
38811.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
38821.1Skamil	    child, getpid());
38831.1Skamil	errno = 0;
38841.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
38851.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38861.1Skamil
38871.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
38881.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
38891.1Skamil
38901.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
38911.1Skamil	    child, getpid());
38921.1Skamil	errno = 0;
38931.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
38941.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38951.1Skamil
38961.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
38971.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
38981.1Skamil
38991.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
39001.1Skamil	    child, getpid());
39011.1Skamil	errno = 0;
39021.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
39031.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
39041.1Skamil
39051.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
39061.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
39071.1Skamil
39081.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
39091.1Skamil	    child, getpid());
39101.1Skamil	errno = 0;
39111.1Skamil	lookup_me4 = ptrace(PT_READ_I, child, dummy_fn4, 0);
39121.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
39131.1Skamil
39141.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
39151.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
39161.1Skamil
39171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39181.1Skamil	    "without signal to be sent\n");
39191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39201.1Skamil
39211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39231.1Skamil
39241.1Skamil	validate_status_exited(status, exitval);
39251.1Skamil
39261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39271.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39281.1Skamil}
39291.1Skamil
39301.1Skamil#if defined(HAVE_GPREGS)
39311.1SkamilATF_TC(regs1);
39321.1SkamilATF_TC_HEAD(regs1, tc)
39331.1Skamil{
39341.1Skamil	atf_tc_set_md_var(tc, "descr",
39351.1Skamil	    "Verify plain PT_GETREGS call without further steps");
39361.1Skamil}
39371.1Skamil
39381.1SkamilATF_TC_BODY(regs1, tc)
39391.1Skamil{
39401.1Skamil	const int exitval = 5;
39411.1Skamil	const int sigval = SIGSTOP;
39421.1Skamil	pid_t child, wpid;
39431.1Skamil#if defined(TWAIT_HAVE_STATUS)
39441.1Skamil	int status;
39451.1Skamil#endif
39461.1Skamil	struct reg r;
39471.1Skamil
39481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39501.1Skamil	if (child == 0) {
39511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39531.1Skamil
39541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39561.1Skamil
39571.13Schristos		DPRINTF("Before exiting of the child process\n");
39581.1Skamil		_exit(exitval);
39591.1Skamil	}
39601.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39611.1Skamil
39621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39641.1Skamil
39651.1Skamil	validate_status_stopped(status, sigval);
39661.1Skamil
39671.13Schristos	DPRINTF("Call GETREGS for the child process\n");
39681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
39691.1Skamil
39701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39711.1Skamil	    "without signal to be sent\n");
39721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39731.1Skamil
39741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39761.1Skamil
39771.1Skamil	validate_status_exited(status, exitval);
39781.1Skamil
39791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39811.1Skamil}
39821.1Skamil#endif
39831.1Skamil
39841.1Skamil#if defined(HAVE_GPREGS)
39851.1SkamilATF_TC(regs2);
39861.1SkamilATF_TC_HEAD(regs2, tc)
39871.1Skamil{
39881.1Skamil	atf_tc_set_md_var(tc, "descr",
39891.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
39901.1Skamil}
39911.1Skamil
39921.1SkamilATF_TC_BODY(regs2, tc)
39931.1Skamil{
39941.1Skamil	const int exitval = 5;
39951.1Skamil	const int sigval = SIGSTOP;
39961.1Skamil	pid_t child, wpid;
39971.1Skamil#if defined(TWAIT_HAVE_STATUS)
39981.1Skamil	int status;
39991.1Skamil#endif
40001.1Skamil	struct reg r;
40011.1Skamil
40021.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40031.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40041.1Skamil	if (child == 0) {
40051.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40061.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40071.1Skamil
40081.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40091.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40101.1Skamil
40111.13Schristos		DPRINTF("Before exiting of the child process\n");
40121.1Skamil		_exit(exitval);
40131.1Skamil	}
40141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40151.1Skamil
40161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40181.1Skamil
40191.1Skamil	validate_status_stopped(status, sigval);
40201.1Skamil
40211.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40231.1Skamil
40241.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
40251.1Skamil
40261.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40271.1Skamil	    "without signal to be sent\n");
40281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40291.1Skamil
40301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40321.1Skamil
40331.1Skamil	validate_status_exited(status, exitval);
40341.1Skamil
40351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40371.1Skamil}
40381.1Skamil#endif
40391.1Skamil
40401.1Skamil#if defined(HAVE_GPREGS)
40411.1SkamilATF_TC(regs3);
40421.1SkamilATF_TC_HEAD(regs3, tc)
40431.1Skamil{
40441.1Skamil	atf_tc_set_md_var(tc, "descr",
40451.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
40461.1Skamil}
40471.1Skamil
40481.1SkamilATF_TC_BODY(regs3, tc)
40491.1Skamil{
40501.1Skamil	const int exitval = 5;
40511.1Skamil	const int sigval = SIGSTOP;
40521.1Skamil	pid_t child, wpid;
40531.1Skamil#if defined(TWAIT_HAVE_STATUS)
40541.1Skamil	int status;
40551.1Skamil#endif
40561.1Skamil	struct reg r;
40571.1Skamil
40581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40601.1Skamil	if (child == 0) {
40611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40631.1Skamil
40641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40661.1Skamil
40671.13Schristos		DPRINTF("Before exiting of the child process\n");
40681.1Skamil		_exit(exitval);
40691.1Skamil	}
40701.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40711.1Skamil
40721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40741.1Skamil
40751.1Skamil	validate_status_stopped(status, sigval);
40761.1Skamil
40771.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40791.1Skamil
40801.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
40811.1Skamil
40821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40831.1Skamil	    "without signal to be sent\n");
40841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40851.1Skamil
40861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40881.1Skamil
40891.1Skamil	validate_status_exited(status, exitval);
40901.1Skamil
40911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40931.1Skamil}
40941.1Skamil#endif
40951.1Skamil
40961.1Skamil#if defined(HAVE_GPREGS)
40971.1SkamilATF_TC(regs4);
40981.1SkamilATF_TC_HEAD(regs4, tc)
40991.1Skamil{
41001.1Skamil	atf_tc_set_md_var(tc, "descr",
41011.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
41021.1Skamil}
41031.1Skamil
41041.1SkamilATF_TC_BODY(regs4, tc)
41051.1Skamil{
41061.1Skamil	const int exitval = 5;
41071.1Skamil	const int sigval = SIGSTOP;
41081.1Skamil	pid_t child, wpid;
41091.1Skamil#if defined(TWAIT_HAVE_STATUS)
41101.1Skamil	int status;
41111.1Skamil#endif
41121.1Skamil	struct reg r;
41131.1Skamil
41141.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41151.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41161.1Skamil	if (child == 0) {
41171.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41181.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41191.1Skamil
41201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41221.1Skamil
41231.13Schristos		DPRINTF("Before exiting of the child process\n");
41241.1Skamil		_exit(exitval);
41251.1Skamil	}
41261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41271.1Skamil
41281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41301.1Skamil
41311.1Skamil	validate_status_stopped(status, sigval);
41321.1Skamil
41331.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41351.1Skamil
41361.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
41371.1Skamil
41381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41391.1Skamil	    "without signal to be sent\n");
41401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41411.1Skamil
41421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41441.1Skamil
41451.1Skamil	validate_status_exited(status, exitval);
41461.1Skamil
41471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41491.1Skamil}
41501.1Skamil#endif
41511.1Skamil
41521.1Skamil#if defined(HAVE_GPREGS)
41531.1SkamilATF_TC(regs5);
41541.1SkamilATF_TC_HEAD(regs5, tc)
41551.1Skamil{
41561.1Skamil	atf_tc_set_md_var(tc, "descr",
41571.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
41581.1Skamil}
41591.1Skamil
41601.1SkamilATF_TC_BODY(regs5, tc)
41611.1Skamil{
41621.1Skamil	const int exitval = 5;
41631.1Skamil	const int sigval = SIGSTOP;
41641.1Skamil	pid_t child, wpid;
41651.1Skamil#if defined(TWAIT_HAVE_STATUS)
41661.1Skamil	int status;
41671.1Skamil#endif
41681.1Skamil	struct reg r;
41691.1Skamil
41701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41721.1Skamil	if (child == 0) {
41731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41751.1Skamil
41761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41781.1Skamil
41791.13Schristos		DPRINTF("Before exiting of the child process\n");
41801.1Skamil		_exit(exitval);
41811.1Skamil	}
41821.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41831.1Skamil
41841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41861.1Skamil
41871.1Skamil	validate_status_stopped(status, sigval);
41881.1Skamil
41891.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41911.1Skamil
41921.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
41931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41941.1Skamil
41951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41961.1Skamil	    "without signal to be sent\n");
41971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41981.1Skamil
41991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42011.1Skamil
42021.1Skamil	validate_status_exited(status, exitval);
42031.1Skamil
42041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42051.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42061.1Skamil}
42071.1Skamil#endif
42081.1Skamil
42091.1Skamil#if defined(HAVE_FPREGS)
42101.1SkamilATF_TC(fpregs1);
42111.1SkamilATF_TC_HEAD(fpregs1, tc)
42121.1Skamil{
42131.1Skamil	atf_tc_set_md_var(tc, "descr",
42141.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
42151.1Skamil}
42161.1Skamil
42171.1SkamilATF_TC_BODY(fpregs1, tc)
42181.1Skamil{
42191.1Skamil	const int exitval = 5;
42201.1Skamil	const int sigval = SIGSTOP;
42211.1Skamil	pid_t child, wpid;
42221.1Skamil#if defined(TWAIT_HAVE_STATUS)
42231.1Skamil	int status;
42241.1Skamil#endif
42251.1Skamil	struct fpreg r;
42261.1Skamil
42271.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42281.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42291.1Skamil	if (child == 0) {
42301.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42311.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42321.1Skamil
42331.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42341.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42351.1Skamil
42361.13Schristos		DPRINTF("Before exiting of the child process\n");
42371.1Skamil		_exit(exitval);
42381.1Skamil	}
42391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42401.1Skamil
42411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42431.1Skamil
42441.1Skamil	validate_status_stopped(status, sigval);
42451.1Skamil
42461.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
42471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
42481.1Skamil
42491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42501.1Skamil	    "without signal to be sent\n");
42511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42521.1Skamil
42531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42551.1Skamil
42561.1Skamil	validate_status_exited(status, exitval);
42571.1Skamil
42581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42601.1Skamil}
42611.1Skamil#endif
42621.1Skamil
42631.1Skamil#if defined(HAVE_FPREGS)
42641.1SkamilATF_TC(fpregs2);
42651.1SkamilATF_TC_HEAD(fpregs2, tc)
42661.1Skamil{
42671.1Skamil	atf_tc_set_md_var(tc, "descr",
42681.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
42691.1Skamil	    "regs");
42701.1Skamil}
42711.1Skamil
42721.1SkamilATF_TC_BODY(fpregs2, tc)
42731.1Skamil{
42741.1Skamil	const int exitval = 5;
42751.1Skamil	const int sigval = SIGSTOP;
42761.1Skamil	pid_t child, wpid;
42771.1Skamil#if defined(TWAIT_HAVE_STATUS)
42781.1Skamil	int status;
42791.1Skamil#endif
42801.1Skamil	struct fpreg r;
42811.1Skamil
42821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42841.1Skamil	if (child == 0) {
42851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42871.1Skamil
42881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42901.1Skamil
42911.13Schristos		DPRINTF("Before exiting of the child process\n");
42921.1Skamil		_exit(exitval);
42931.1Skamil	}
42941.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42951.1Skamil
42961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42981.1Skamil
42991.1Skamil	validate_status_stopped(status, sigval);
43001.1Skamil
43011.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
43021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
43031.1Skamil
43041.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
43051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
43061.1Skamil
43071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43081.1Skamil	    "without signal to be sent\n");
43091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43101.1Skamil
43111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43131.1Skamil
43141.1Skamil	validate_status_exited(status, exitval);
43151.1Skamil
43161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43181.1Skamil}
43191.1Skamil#endif
43201.1Skamil
43211.1Skamil#if defined(PT_STEP)
43221.1Skamilstatic void
43231.2Skamilptrace_step(int N, int setstep)
43241.1Skamil{
43251.1Skamil	const int exitval = 5;
43261.1Skamil	const int sigval = SIGSTOP;
43271.1Skamil	pid_t child, wpid;
43281.1Skamil#if defined(TWAIT_HAVE_STATUS)
43291.1Skamil	int status;
43301.1Skamil#endif
43311.1Skamil	int happy;
43321.1Skamil
43331.1Skamil#if defined(__arm__)
43341.1Skamil	/* PT_STEP not supported on arm 32-bit */
43351.1Skamil	atf_tc_expect_fail("PR kern/52119");
43361.1Skamil#endif
43371.1Skamil
43381.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43391.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43401.1Skamil	if (child == 0) {
43411.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43421.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43431.1Skamil
43441.1Skamil		happy = check_happy(999);
43451.1Skamil
43461.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43471.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43481.1Skamil
43491.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
43501.1Skamil
43511.13Schristos		DPRINTF("Before exiting of the child process\n");
43521.1Skamil		_exit(exitval);
43531.1Skamil	}
43541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43551.1Skamil
43561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43581.1Skamil
43591.1Skamil	validate_status_stopped(status, sigval);
43601.1Skamil
43611.1Skamil	while (N --> 0) {
43621.2Skamil		if (setstep) {
43631.13Schristos			DPRINTF("Before resuming the child process where it "
43641.2Skamil			    "left off and without signal to be sent (use "
43651.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
43661.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
43671.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
43681.2Skamil			    != -1);
43691.2Skamil		} else {
43701.13Schristos			DPRINTF("Before resuming the child process where it "
43711.2Skamil			    "left off and without signal to be sent (use "
43721.2Skamil			    "PT_STEP)\n");
43731.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
43741.2Skamil			    != -1);
43751.2Skamil		}
43761.1Skamil
43771.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43781.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
43791.1Skamil		    child);
43801.1Skamil
43811.1Skamil		validate_status_stopped(status, SIGTRAP);
43821.2Skamil
43831.2Skamil		if (setstep) {
43841.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
43851.2Skamil		}
43861.1Skamil	}
43871.1Skamil
43881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43891.1Skamil	    "without signal to be sent\n");
43901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43911.1Skamil
43921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43941.1Skamil
43951.1Skamil	validate_status_exited(status, exitval);
43961.1Skamil
43971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43991.1Skamil}
44001.1Skamil#endif
44011.1Skamil
44021.1Skamil#if defined(PT_STEP)
44031.1SkamilATF_TC(step1);
44041.1SkamilATF_TC_HEAD(step1, tc)
44051.1Skamil{
44061.1Skamil	atf_tc_set_md_var(tc, "descr",
44071.1Skamil	    "Verify single PT_STEP call");
44081.1Skamil}
44091.1Skamil
44101.1SkamilATF_TC_BODY(step1, tc)
44111.1Skamil{
44121.2Skamil	ptrace_step(1, 0);
44131.1Skamil}
44141.1Skamil#endif
44151.1Skamil
44161.1Skamil#if defined(PT_STEP)
44171.1SkamilATF_TC(step2);
44181.1SkamilATF_TC_HEAD(step2, tc)
44191.1Skamil{
44201.1Skamil	atf_tc_set_md_var(tc, "descr",
44211.1Skamil	    "Verify PT_STEP called twice");
44221.1Skamil}
44231.1Skamil
44241.1SkamilATF_TC_BODY(step2, tc)
44251.1Skamil{
44261.2Skamil	ptrace_step(2, 0);
44271.1Skamil}
44281.1Skamil#endif
44291.1Skamil
44301.1Skamil#if defined(PT_STEP)
44311.1SkamilATF_TC(step3);
44321.1SkamilATF_TC_HEAD(step3, tc)
44331.1Skamil{
44341.1Skamil	atf_tc_set_md_var(tc, "descr",
44351.1Skamil	    "Verify PT_STEP called three times");
44361.1Skamil}
44371.1Skamil
44381.1SkamilATF_TC_BODY(step3, tc)
44391.1Skamil{
44401.2Skamil	ptrace_step(3, 0);
44411.1Skamil}
44421.1Skamil#endif
44431.1Skamil
44441.1Skamil#if defined(PT_STEP)
44451.1SkamilATF_TC(step4);
44461.1SkamilATF_TC_HEAD(step4, tc)
44471.1Skamil{
44481.1Skamil	atf_tc_set_md_var(tc, "descr",
44491.1Skamil	    "Verify PT_STEP called four times");
44501.1Skamil}
44511.1Skamil
44521.1SkamilATF_TC_BODY(step4, tc)
44531.1Skamil{
44541.2Skamil	ptrace_step(4, 0);
44551.2Skamil}
44561.2Skamil#endif
44571.2Skamil
44581.2Skamil#if defined(PT_STEP)
44591.2SkamilATF_TC(setstep1);
44601.2SkamilATF_TC_HEAD(setstep1, tc)
44611.2Skamil{
44621.2Skamil	atf_tc_set_md_var(tc, "descr",
44631.2Skamil	    "Verify single PT_SETSTEP call");
44641.2Skamil}
44651.2Skamil
44661.2SkamilATF_TC_BODY(setstep1, tc)
44671.2Skamil{
44681.2Skamil	ptrace_step(1, 1);
44691.2Skamil}
44701.2Skamil#endif
44711.2Skamil
44721.2Skamil#if defined(PT_STEP)
44731.2SkamilATF_TC(setstep2);
44741.2SkamilATF_TC_HEAD(setstep2, tc)
44751.2Skamil{
44761.2Skamil	atf_tc_set_md_var(tc, "descr",
44771.2Skamil	    "Verify PT_SETSTEP called twice");
44781.2Skamil}
44791.2Skamil
44801.2SkamilATF_TC_BODY(setstep2, tc)
44811.2Skamil{
44821.2Skamil	ptrace_step(2, 1);
44831.2Skamil}
44841.2Skamil#endif
44851.2Skamil
44861.2Skamil#if defined(PT_STEP)
44871.2SkamilATF_TC(setstep3);
44881.2SkamilATF_TC_HEAD(setstep3, tc)
44891.2Skamil{
44901.2Skamil	atf_tc_set_md_var(tc, "descr",
44911.2Skamil	    "Verify PT_SETSTEP called three times");
44921.2Skamil}
44931.2Skamil
44941.2SkamilATF_TC_BODY(setstep3, tc)
44951.2Skamil{
44961.2Skamil	ptrace_step(3, 1);
44971.2Skamil}
44981.2Skamil#endif
44991.2Skamil
45001.2Skamil#if defined(PT_STEP)
45011.2SkamilATF_TC(setstep4);
45021.2SkamilATF_TC_HEAD(setstep4, tc)
45031.2Skamil{
45041.2Skamil	atf_tc_set_md_var(tc, "descr",
45051.2Skamil	    "Verify PT_SETSTEP called four times");
45061.2Skamil}
45071.2Skamil
45081.2SkamilATF_TC_BODY(setstep4, tc)
45091.2Skamil{
45101.2Skamil	ptrace_step(4, 1);
45111.1Skamil}
45121.1Skamil#endif
45131.1Skamil
45141.1SkamilATF_TC(kill1);
45151.1SkamilATF_TC_HEAD(kill1, tc)
45161.1Skamil{
45171.1Skamil	atf_tc_set_md_var(tc, "descr",
45181.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
45191.1Skamil}
45201.1Skamil
45211.1SkamilATF_TC_BODY(kill1, tc)
45221.1Skamil{
45231.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
45241.1Skamil	pid_t child, wpid;
45251.1Skamil#if defined(TWAIT_HAVE_STATUS)
45261.1Skamil	int status;
45271.1Skamil#endif
45281.1Skamil
45291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45311.1Skamil	if (child == 0) {
45321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45341.1Skamil
45351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45371.1Skamil
45381.1Skamil		/* NOTREACHED */
45391.1Skamil		FORKEE_ASSERTX(0 &&
45401.1Skamil		    "Child should be terminated by a signal from its parent");
45411.1Skamil	}
45421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45431.1Skamil
45441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45461.1Skamil
45471.1Skamil	validate_status_stopped(status, sigval);
45481.1Skamil
45491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45501.1Skamil	    "without signal to be sent\n");
45511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
45521.1Skamil
45531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45551.1Skamil
45561.1Skamil	validate_status_signaled(status, sigsent, 0);
45571.1Skamil
45581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45601.1Skamil}
45611.1Skamil
45621.1SkamilATF_TC(kill2);
45631.1SkamilATF_TC_HEAD(kill2, tc)
45641.1Skamil{
45651.1Skamil	atf_tc_set_md_var(tc, "descr",
45661.1Skamil	    "Verify that PT_KILL terminates child");
45671.1Skamil}
45681.1Skamil
45691.1SkamilATF_TC_BODY(kill2, tc)
45701.1Skamil{
45711.1Skamil	const int sigval = SIGSTOP;
45721.1Skamil	pid_t child, wpid;
45731.1Skamil#if defined(TWAIT_HAVE_STATUS)
45741.1Skamil	int status;
45751.1Skamil#endif
45761.1Skamil
45771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45791.1Skamil	if (child == 0) {
45801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45821.1Skamil
45831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45851.1Skamil
45861.1Skamil		/* NOTREACHED */
45871.1Skamil		FORKEE_ASSERTX(0 &&
45881.1Skamil		    "Child should be terminated by a signal from its parent");
45891.1Skamil	}
45901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45911.1Skamil
45921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45941.1Skamil
45951.1Skamil	validate_status_stopped(status, sigval);
45961.1Skamil
45971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45981.1Skamil	    "without signal to be sent\n");
45991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
46001.1Skamil
46011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46031.1Skamil
46041.1Skamil	validate_status_signaled(status, SIGKILL, 0);
46051.1Skamil
46061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46081.1Skamil}
46091.1Skamil
46101.1SkamilATF_TC(lwpinfo1);
46111.1SkamilATF_TC_HEAD(lwpinfo1, tc)
46121.1Skamil{
46131.1Skamil	atf_tc_set_md_var(tc, "descr",
46141.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
46151.1Skamil}
46161.1Skamil
46171.1SkamilATF_TC_BODY(lwpinfo1, tc)
46181.1Skamil{
46191.1Skamil	const int exitval = 5;
46201.1Skamil	const int sigval = SIGSTOP;
46211.1Skamil	pid_t child, wpid;
46221.1Skamil#if defined(TWAIT_HAVE_STATUS)
46231.1Skamil	int status;
46241.1Skamil#endif
46251.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46261.1Skamil
46271.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46281.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46291.1Skamil	if (child == 0) {
46301.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46311.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46321.1Skamil
46331.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46341.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46351.1Skamil
46361.13Schristos		DPRINTF("Before exiting of the child process\n");
46371.1Skamil		_exit(exitval);
46381.1Skamil	}
46391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46401.1Skamil
46411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46431.1Skamil
46441.1Skamil	validate_status_stopped(status, sigval);
46451.1Skamil
46461.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
46481.1Skamil
46491.13Schristos	DPRINTF("Assert that there exists a thread\n");
46501.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
46511.1Skamil
46521.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
46531.1Skamil	    info.pl_lwpid);
46541.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
46551.1Skamil	    "Received event %d != expected event %d",
46561.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
46571.1Skamil
46581.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
46601.1Skamil
46611.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
46621.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
46631.1Skamil
46641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46651.1Skamil	    "without signal to be sent\n");
46661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46671.1Skamil
46681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46701.1Skamil
46711.1Skamil	validate_status_exited(status, exitval);
46721.1Skamil
46731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46751.1Skamil}
46761.1Skamil
46771.1Skamil#if defined(TWAIT_HAVE_PID)
46781.1SkamilATF_TC(lwpinfo2);
46791.1SkamilATF_TC_HEAD(lwpinfo2, tc)
46801.1Skamil{
46811.1Skamil	atf_tc_set_md_var(tc, "descr",
46821.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
46831.1Skamil	    "tracer)");
46841.1Skamil}
46851.1Skamil
46861.1SkamilATF_TC_BODY(lwpinfo2, tc)
46871.1Skamil{
46881.1Skamil	struct msg_fds parent_tracee, parent_tracer;
46891.1Skamil	const int exitval_tracee = 5;
46901.1Skamil	const int exitval_tracer = 10;
46911.1Skamil	pid_t tracee, tracer, wpid;
46921.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
46931.1Skamil#if defined(TWAIT_HAVE_STATUS)
46941.1Skamil	int status;
46951.1Skamil#endif
46961.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46971.1Skamil
46981.13Schristos	DPRINTF("Spawn tracee\n");
46991.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
47001.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
47011.1Skamil	tracee = atf_utils_fork();
47021.1Skamil	if (tracee == 0) {
47031.1Skamil
47041.1Skamil		/* Wait for message from the parent */
47051.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
47061.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
47071.1Skamil
47081.1Skamil		_exit(exitval_tracee);
47091.1Skamil	}
47101.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
47111.1Skamil
47121.13Schristos	DPRINTF("Spawn debugger\n");
47131.1Skamil	tracer = atf_utils_fork();
47141.1Skamil	if (tracer == 0) {
47151.1Skamil		/* No IPC to communicate with the child */
47161.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
47171.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
47181.1Skamil
47191.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
47201.1Skamil		FORKEE_REQUIRE_SUCCESS(
47211.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47221.1Skamil
47231.1Skamil		forkee_status_stopped(status, SIGSTOP);
47241.1Skamil
47251.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47261.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
47271.1Skamil		    != -1);
47281.1Skamil
47291.13Schristos		DPRINTF("Assert that there exists a thread\n");
47301.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
47311.1Skamil
47321.13Schristos		DPRINTF("Assert that lwp thread %d received event "
47331.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
47341.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
47351.1Skamil
47361.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47371.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
47381.1Skamil		    != -1);
47391.1Skamil
47401.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
47411.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
47421.1Skamil
47431.1Skamil		/* Resume tracee with PT_CONTINUE */
47441.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
47451.1Skamil
47461.1Skamil		/* Inform parent that tracer has attached to tracee */
47471.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
47481.1Skamil		/* Wait for parent */
47491.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
47501.1Skamil
47511.1Skamil		/* Wait for tracee and assert that it exited */
47521.1Skamil		FORKEE_REQUIRE_SUCCESS(
47531.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47541.1Skamil
47551.1Skamil		forkee_status_exited(status, exitval_tracee);
47561.1Skamil
47571.13Schristos		DPRINTF("Before exiting of the tracer process\n");
47581.1Skamil		_exit(exitval_tracer);
47591.1Skamil	}
47601.1Skamil
47611.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
47621.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
47631.1Skamil
47641.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
47651.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
47661.1Skamil
47671.13Schristos	DPRINTF("Detect that tracee is zombie\n");
47681.1Skamil	await_zombie(tracee);
47691.1Skamil
47701.13Schristos	DPRINTF("Assert that there is no status about tracee - "
47711.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
47721.1Skamil	TWAIT_REQUIRE_SUCCESS(
47731.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
47741.1Skamil
47751.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
47761.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
47771.1Skamil
47781.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
47791.1Skamil	    TWAIT_FNAME);
47801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
47811.1Skamil	    tracer);
47821.1Skamil
47831.1Skamil	validate_status_exited(status, exitval_tracer);
47841.1Skamil
47851.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
47861.1Skamil	    TWAIT_FNAME);
47871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
47881.1Skamil	    tracee);
47891.1Skamil
47901.1Skamil	validate_status_exited(status, exitval_tracee);
47911.1Skamil
47921.1Skamil	msg_close(&parent_tracer);
47931.1Skamil	msg_close(&parent_tracee);
47941.1Skamil}
47951.1Skamil#endif
47961.1Skamil
47971.1SkamilATF_TC(siginfo1);
47981.1SkamilATF_TC_HEAD(siginfo1, tc)
47991.1Skamil{
48001.1Skamil	atf_tc_set_md_var(tc, "descr",
48011.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
48021.1Skamil}
48031.1Skamil
48041.1SkamilATF_TC_BODY(siginfo1, tc)
48051.1Skamil{
48061.1Skamil	const int exitval = 5;
48071.1Skamil	const int sigval = SIGTRAP;
48081.1Skamil	pid_t child, wpid;
48091.1Skamil#if defined(TWAIT_HAVE_STATUS)
48101.1Skamil	int status;
48111.1Skamil#endif
48121.1Skamil	struct ptrace_siginfo info;
48131.1Skamil	memset(&info, 0, sizeof(info));
48141.1Skamil
48151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48171.1Skamil	if (child == 0) {
48181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48201.1Skamil
48211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48231.1Skamil
48241.13Schristos		DPRINTF("Before exiting of the child process\n");
48251.1Skamil		_exit(exitval);
48261.1Skamil	}
48271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48281.1Skamil
48291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48311.1Skamil
48321.1Skamil	validate_status_stopped(status, sigval);
48331.1Skamil
48341.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48361.1Skamil
48371.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48381.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48391.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48401.1Skamil	    info.psi_siginfo.si_errno);
48411.1Skamil
48421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48431.1Skamil	    "without signal to be sent\n");
48441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48451.1Skamil
48461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48481.1Skamil
48491.1Skamil	validate_status_exited(status, exitval);
48501.1Skamil
48511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48531.1Skamil}
48541.1Skamil
48551.1SkamilATF_TC(siginfo2);
48561.1SkamilATF_TC_HEAD(siginfo2, tc)
48571.1Skamil{
48581.1Skamil	atf_tc_set_md_var(tc, "descr",
48591.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
48601.1Skamil	    "modification of SIGINT from tracee");
48611.1Skamil}
48621.1Skamil
48631.1Skamilstatic int siginfo2_caught = 0;
48641.1Skamil
48651.1Skamilstatic void
48661.1Skamilsiginfo2_sighandler(int sig)
48671.1Skamil{
48681.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
48691.1Skamil
48701.1Skamil	++siginfo2_caught;
48711.1Skamil}
48721.1Skamil
48731.1SkamilATF_TC_BODY(siginfo2, tc)
48741.1Skamil{
48751.1Skamil	const int exitval = 5;
48761.1Skamil	const int sigval = SIGINT;
48771.1Skamil	pid_t child, wpid;
48781.1Skamil	struct sigaction sa;
48791.1Skamil#if defined(TWAIT_HAVE_STATUS)
48801.1Skamil	int status;
48811.1Skamil#endif
48821.1Skamil	struct ptrace_siginfo info;
48831.1Skamil	memset(&info, 0, sizeof(info));
48841.1Skamil
48851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48871.1Skamil	if (child == 0) {
48881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48901.1Skamil
48911.1Skamil		sa.sa_handler = siginfo2_sighandler;
48921.1Skamil		sa.sa_flags = SA_SIGINFO;
48931.1Skamil		sigemptyset(&sa.sa_mask);
48941.1Skamil
48951.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
48961.1Skamil
48971.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48981.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48991.1Skamil
49001.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
49011.1Skamil
49021.13Schristos		DPRINTF("Before exiting of the child process\n");
49031.1Skamil		_exit(exitval);
49041.1Skamil	}
49051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49061.1Skamil
49071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49091.1Skamil
49101.1Skamil	validate_status_stopped(status, sigval);
49111.1Skamil
49121.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49141.1Skamil
49151.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49161.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49171.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49181.1Skamil	    info.psi_siginfo.si_errno);
49191.1Skamil
49201.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -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, sigval) != -1);
49261.1Skamil
49271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49291.1Skamil
49301.1Skamil	validate_status_exited(status, exitval);
49311.1Skamil
49321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49341.1Skamil}
49351.1Skamil
49361.1SkamilATF_TC(siginfo3);
49371.1SkamilATF_TC_HEAD(siginfo3, tc)
49381.1Skamil{
49391.1Skamil	atf_tc_set_md_var(tc, "descr",
49401.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
49411.1Skamil	    "setting signal to new value");
49421.1Skamil}
49431.1Skamil
49441.1Skamilstatic int siginfo3_caught = 0;
49451.1Skamil
49461.1Skamilstatic void
49471.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
49481.1Skamil{
49491.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
49501.1Skamil
49511.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
49521.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
49531.1Skamil
49541.1Skamil	++siginfo3_caught;
49551.1Skamil}
49561.1Skamil
49571.1SkamilATF_TC_BODY(siginfo3, tc)
49581.1Skamil{
49591.1Skamil	const int exitval = 5;
49601.1Skamil	const int sigval = SIGINT;
49611.1Skamil	const int sigfaked = SIGTRAP;
49621.1Skamil	const int sicodefaked = TRAP_BRKPT;
49631.1Skamil	pid_t child, wpid;
49641.1Skamil	struct sigaction sa;
49651.1Skamil#if defined(TWAIT_HAVE_STATUS)
49661.1Skamil	int status;
49671.1Skamil#endif
49681.1Skamil	struct ptrace_siginfo info;
49691.1Skamil	memset(&info, 0, sizeof(info));
49701.1Skamil
49711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49731.1Skamil	if (child == 0) {
49741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49761.1Skamil
49771.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
49781.1Skamil		sa.sa_flags = SA_SIGINFO;
49791.1Skamil		sigemptyset(&sa.sa_mask);
49801.1Skamil
49811.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
49821.1Skamil
49831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49851.1Skamil
49861.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
49871.1Skamil
49881.13Schristos		DPRINTF("Before exiting of the child process\n");
49891.1Skamil		_exit(exitval);
49901.1Skamil	}
49911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49921.1Skamil
49931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49951.1Skamil
49961.1Skamil	validate_status_stopped(status, sigval);
49971.1Skamil
49981.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50001.1Skamil
50011.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50021.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
50031.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50041.1Skamil	    info.psi_siginfo.si_errno);
50051.1Skamil
50061.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
50071.1Skamil	    sigfaked, sicodefaked);
50081.1Skamil	info.psi_siginfo.si_signo = sigfaked;
50091.1Skamil	info.psi_siginfo.si_code = sicodefaked;
50101.1Skamil
50111.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
50121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
50131.1Skamil
50141.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50161.1Skamil
50171.13Schristos	DPRINTF("Before checking siginfo_t\n");
50181.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
50191.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
50201.1Skamil
50211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50221.1Skamil	    "without signal to be sent\n");
50231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
50241.1Skamil
50251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50271.1Skamil
50281.1Skamil	validate_status_exited(status, exitval);
50291.1Skamil
50301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50321.1Skamil}
50331.1Skamil
50341.1SkamilATF_TC(siginfo4);
50351.1SkamilATF_TC_HEAD(siginfo4, tc)
50361.1Skamil{
50371.1Skamil	atf_tc_set_md_var(tc, "descr",
50381.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
50391.1Skamil}
50401.1Skamil
50411.1SkamilATF_TC_BODY(siginfo4, tc)
50421.1Skamil{
50431.1Skamil	const int sigval = SIGTRAP;
50441.1Skamil	pid_t child, wpid;
50451.1Skamil#if defined(TWAIT_HAVE_STATUS)
50461.1Skamil	int status;
50471.1Skamil#endif
50481.1Skamil
50491.1Skamil	struct ptrace_siginfo info;
50501.1Skamil	memset(&info, 0, sizeof(info));
50511.1Skamil
50521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50541.1Skamil	if (child == 0) {
50551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50571.1Skamil
50581.13Schristos		DPRINTF("Before calling execve(2) from child\n");
50591.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
50601.1Skamil
50611.1Skamil		FORKEE_ASSERT(0 && "Not reached");
50621.1Skamil	}
50631.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50641.1Skamil
50651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50671.1Skamil
50681.1Skamil	validate_status_stopped(status, sigval);
50691.1Skamil
50701.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50721.1Skamil
50731.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50741.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
50751.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50761.1Skamil	    info.psi_siginfo.si_errno);
50771.1Skamil
50781.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
50791.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
50801.1Skamil
50811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50821.1Skamil	    "without signal to be sent\n");
50831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50841.1Skamil
50851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50871.1Skamil
50881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50891.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50901.1Skamil}
50911.1Skamil
50921.1Skamil#if defined(TWAIT_HAVE_PID)
50931.1SkamilATF_TC(siginfo5);
50941.1SkamilATF_TC_HEAD(siginfo5, tc)
50951.1Skamil{
50961.1Skamil	atf_tc_set_md_var(tc, "descr",
50971.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
50981.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
50991.1Skamil}
51001.1Skamil
51011.1SkamilATF_TC_BODY(siginfo5, tc)
51021.1Skamil{
51031.1Skamil	const int exitval = 5;
51041.1Skamil	const int exitval2 = 15;
51051.1Skamil	const int sigval = SIGSTOP;
51061.1Skamil	pid_t child, child2, wpid;
51071.1Skamil#if defined(TWAIT_HAVE_STATUS)
51081.1Skamil	int status;
51091.1Skamil#endif
51101.1Skamil	ptrace_state_t state;
51111.1Skamil	const int slen = sizeof(state);
51121.1Skamil	ptrace_event_t event;
51131.1Skamil	const int elen = sizeof(event);
51141.1Skamil	struct ptrace_siginfo info;
51151.1Skamil
51161.1Skamil	memset(&info, 0, sizeof(info));
51171.1Skamil
51181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51201.1Skamil	if (child == 0) {
51211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51231.1Skamil
51241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51261.1Skamil
51271.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
51281.1Skamil
51291.1Skamil		if (child2 == 0)
51301.1Skamil			_exit(exitval2);
51311.1Skamil
51321.1Skamil		FORKEE_REQUIRE_SUCCESS
51331.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
51341.1Skamil
51351.1Skamil		forkee_status_exited(status, exitval2);
51361.1Skamil
51371.13Schristos		DPRINTF("Before exiting of the child process\n");
51381.1Skamil		_exit(exitval);
51391.1Skamil	}
51401.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51411.1Skamil
51421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51441.1Skamil
51451.1Skamil	validate_status_stopped(status, sigval);
51461.1Skamil
51471.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51491.1Skamil
51501.13Schristos	DPRINTF("Before checking siginfo_t\n");
51511.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
51521.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
51531.1Skamil
51541.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
51551.1Skamil	event.pe_set_event = PTRACE_FORK;
51561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
51571.1Skamil
51581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51591.1Skamil	    "without signal to be sent\n");
51601.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
51611.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
51621.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
51631.1Skamil                "state.pe_other_pid=child)\n", child);
51641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51651.1Skamil
51661.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
51671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51681.1Skamil
51691.1Skamil	validate_status_stopped(status, SIGTRAP);
51701.1Skamil
51711.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51731.1Skamil
51741.13Schristos	DPRINTF("Before checking siginfo_t\n");
51751.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51761.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
51771.1Skamil
51781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51791.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
51801.1Skamil
51811.1Skamil	child2 = state.pe_other_pid;
51821.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
51831.1Skamil
51841.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
51851.1Skamil	    TWAIT_FNAME, child2, child);
51861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51871.1Skamil	    child2);
51881.1Skamil
51891.1Skamil	validate_status_stopped(status, SIGTRAP);
51901.1Skamil
51911.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51931.1Skamil
51941.13Schristos	DPRINTF("Before checking siginfo_t\n");
51951.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51961.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
51971.1Skamil
51981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
51991.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
52001.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
52011.1Skamil
52021.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
52031.1Skamil	    "without signal to be sent\n");
52041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
52051.1Skamil
52061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52071.1Skamil	    "without signal to be sent\n");
52081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52091.1Skamil
52101.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
52111.1Skamil	    TWAIT_FNAME);
52121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
52131.1Skamil	    child2);
52141.1Skamil
52151.1Skamil	validate_status_exited(status, exitval2);
52161.1Skamil
52171.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
52181.1Skamil	    TWAIT_FNAME);
52191.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
52201.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
52211.1Skamil
52221.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52231.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
52241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52251.1Skamil
52261.1Skamil	validate_status_stopped(status, SIGCHLD);
52271.1Skamil
52281.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52301.1Skamil
52311.13Schristos	DPRINTF("Before checking siginfo_t\n");
52321.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
52331.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
52341.1Skamil
52351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52361.1Skamil	    "without signal to be sent\n");
52371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52381.1Skamil
52391.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52401.1Skamil	    TWAIT_FNAME);
52411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52421.1Skamil
52431.1Skamil	validate_status_exited(status, exitval);
52441.1Skamil
52451.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52461.1Skamil	    TWAIT_FNAME);
52471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52481.1Skamil}
52491.1Skamil#endif
52501.1Skamil
52511.1Skamil#if defined(PT_STEP)
52521.1SkamilATF_TC(siginfo6);
52531.1SkamilATF_TC_HEAD(siginfo6, tc)
52541.1Skamil{
52551.1Skamil	atf_tc_set_md_var(tc, "descr",
52561.1Skamil	    "Verify single PT_STEP call with signal information check");
52571.1Skamil}
52581.1Skamil
52591.1SkamilATF_TC_BODY(siginfo6, tc)
52601.1Skamil{
52611.1Skamil	const int exitval = 5;
52621.1Skamil	const int sigval = SIGSTOP;
52631.1Skamil	pid_t child, wpid;
52641.1Skamil#if defined(TWAIT_HAVE_STATUS)
52651.1Skamil	int status;
52661.1Skamil#endif
52671.1Skamil	int happy;
52681.1Skamil	struct ptrace_siginfo info;
52691.1Skamil
52701.1Skamil#if defined(__arm__)
52711.1Skamil	/* PT_STEP not supported on arm 32-bit */
52721.1Skamil	atf_tc_expect_fail("PR kern/52119");
52731.1Skamil#endif
52741.1Skamil
52751.1Skamil	memset(&info, 0, sizeof(info));
52761.1Skamil
52771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52791.1Skamil	if (child == 0) {
52801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52821.1Skamil
52831.1Skamil		happy = check_happy(100);
52841.1Skamil
52851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52871.1Skamil
52881.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
52891.1Skamil
52901.13Schristos		DPRINTF("Before exiting of the child process\n");
52911.1Skamil		_exit(exitval);
52921.1Skamil	}
52931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52941.1Skamil
52951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52971.1Skamil
52981.1Skamil	validate_status_stopped(status, sigval);
52991.1Skamil
53001.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53021.1Skamil
53031.13Schristos	DPRINTF("Before checking siginfo_t\n");
53041.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
53051.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
53061.1Skamil
53071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53081.1Skamil	    "without signal to be sent (use PT_STEP)\n");
53091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
53101.1Skamil
53111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53131.1Skamil
53141.1Skamil	validate_status_stopped(status, SIGTRAP);
53151.1Skamil
53161.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53181.1Skamil
53191.13Schristos	DPRINTF("Before checking siginfo_t\n");
53201.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
53211.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
53221.1Skamil
53231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53241.1Skamil	    "without signal to be sent\n");
53251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53261.1Skamil
53271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53291.1Skamil
53301.1Skamil	validate_status_exited(status, exitval);
53311.1Skamil
53321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53341.1Skamil}
53351.1Skamil#endif
53361.1Skamil
53371.1Skamilvolatile lwpid_t the_lwp_id = 0;
53381.1Skamil
53391.1Skamilstatic void
53401.1Skamillwp_main_func(void *arg)
53411.1Skamil{
53421.1Skamil	the_lwp_id = _lwp_self();
53431.1Skamil	_lwp_exit();
53441.1Skamil}
53451.1Skamil
53461.1SkamilATF_TC(lwp_create1);
53471.1SkamilATF_TC_HEAD(lwp_create1, tc)
53481.1Skamil{
53491.1Skamil	atf_tc_set_md_var(tc, "descr",
53501.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
53511.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
53521.1Skamil}
53531.1Skamil
53541.1SkamilATF_TC_BODY(lwp_create1, tc)
53551.1Skamil{
53561.1Skamil	const int exitval = 5;
53571.1Skamil	const int sigval = SIGSTOP;
53581.1Skamil	pid_t child, wpid;
53591.1Skamil#if defined(TWAIT_HAVE_STATUS)
53601.1Skamil	int status;
53611.1Skamil#endif
53621.1Skamil	ptrace_state_t state;
53631.1Skamil	const int slen = sizeof(state);
53641.1Skamil	ptrace_event_t event;
53651.1Skamil	const int elen = sizeof(event);
53661.1Skamil	ucontext_t uc;
53671.1Skamil	lwpid_t lid;
53681.1Skamil	static const size_t ssize = 16*1024;
53691.1Skamil	void *stack;
53701.1Skamil
53711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53731.1Skamil	if (child == 0) {
53741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53761.1Skamil
53771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53791.1Skamil
53801.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
53811.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53821.1Skamil
53831.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53841.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
53851.1Skamil
53861.13Schristos		DPRINTF("Before creating new in child\n");
53871.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
53881.1Skamil
53891.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
53901.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
53911.1Skamil
53921.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
53931.1Skamil		    "are the same\n", lid, the_lwp_id);
53941.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
53951.1Skamil
53961.13Schristos		DPRINTF("Before exiting of the child process\n");
53971.1Skamil		_exit(exitval);
53981.1Skamil	}
53991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54001.1Skamil
54011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54031.1Skamil
54041.1Skamil	validate_status_stopped(status, sigval);
54051.1Skamil
54061.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
54071.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
54081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
54091.1Skamil
54101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54111.1Skamil	    "without signal to be sent\n");
54121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54131.1Skamil
54141.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54151.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54171.1Skamil
54181.1Skamil	validate_status_stopped(status, SIGTRAP);
54191.1Skamil
54201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54211.1Skamil
54221.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
54231.1Skamil
54241.1Skamil	lid = state.pe_lwp;
54251.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
54261.1Skamil
54271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54281.1Skamil	    "without signal to be sent\n");
54291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54301.1Skamil
54311.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54321.1Skamil	    TWAIT_FNAME);
54331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54341.1Skamil
54351.1Skamil	validate_status_exited(status, exitval);
54361.1Skamil
54371.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54381.1Skamil	    TWAIT_FNAME);
54391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54401.1Skamil}
54411.1Skamil
54421.1SkamilATF_TC(lwp_exit1);
54431.1SkamilATF_TC_HEAD(lwp_exit1, tc)
54441.1Skamil{
54451.1Skamil	atf_tc_set_md_var(tc, "descr",
54461.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
54471.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
54481.1Skamil}
54491.1Skamil
54501.1SkamilATF_TC_BODY(lwp_exit1, tc)
54511.1Skamil{
54521.1Skamil	const int exitval = 5;
54531.1Skamil	const int sigval = SIGSTOP;
54541.1Skamil	pid_t child, wpid;
54551.1Skamil#if defined(TWAIT_HAVE_STATUS)
54561.1Skamil	int status;
54571.1Skamil#endif
54581.1Skamil	ptrace_state_t state;
54591.1Skamil	const int slen = sizeof(state);
54601.1Skamil	ptrace_event_t event;
54611.1Skamil	const int elen = sizeof(event);
54621.1Skamil	ucontext_t uc;
54631.1Skamil	lwpid_t lid;
54641.1Skamil	static const size_t ssize = 16*1024;
54651.1Skamil	void *stack;
54661.1Skamil
54671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54691.1Skamil	if (child == 0) {
54701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54721.1Skamil
54731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54751.1Skamil
54761.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
54771.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
54781.1Skamil
54791.13Schristos		DPRINTF("Before making context for new lwp in child\n");
54801.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
54811.1Skamil
54821.13Schristos		DPRINTF("Before creating new in child\n");
54831.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54841.1Skamil
54851.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54861.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54871.1Skamil
54881.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54891.1Skamil		    "are the same\n", lid, the_lwp_id);
54901.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54911.1Skamil
54921.13Schristos		DPRINTF("Before exiting of the child process\n");
54931.1Skamil		_exit(exitval);
54941.1Skamil	}
54951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54961.1Skamil
54971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54991.1Skamil
55001.1Skamil	validate_status_stopped(status, sigval);
55011.1Skamil
55021.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
55031.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
55041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
55051.1Skamil
55061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55071.1Skamil	    "without signal to be sent\n");
55081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55091.1Skamil
55101.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
55111.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
55121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55131.1Skamil
55141.1Skamil	validate_status_stopped(status, SIGTRAP);
55151.1Skamil
55161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55171.1Skamil
55181.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
55191.1Skamil
55201.1Skamil	lid = state.pe_lwp;
55211.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
55221.1Skamil
55231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55241.1Skamil	    "without signal to be sent\n");
55251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55261.1Skamil
55271.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55281.1Skamil	    TWAIT_FNAME);
55291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55301.1Skamil
55311.1Skamil	validate_status_exited(status, exitval);
55321.1Skamil
55331.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55341.1Skamil	    TWAIT_FNAME);
55351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55361.1Skamil}
55371.1Skamil
55381.1SkamilATF_TC(signal1);
55391.1SkamilATF_TC_HEAD(signal1, tc)
55401.1Skamil{
55411.1Skamil	atf_tc_set_md_var(tc, "descr",
55421.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
55431.1Skamil	    "from catching other signals");
55441.1Skamil}
55451.1Skamil
55461.1SkamilATF_TC_BODY(signal1, tc)
55471.1Skamil{
55481.1Skamil	const int exitval = 5;
55491.1Skamil	const int sigval = SIGSTOP;
55501.1Skamil	const int sigmasked = SIGTRAP;
55511.1Skamil	const int signotmasked = SIGINT;
55521.1Skamil	pid_t child, wpid;
55531.1Skamil#if defined(TWAIT_HAVE_STATUS)
55541.1Skamil	int status;
55551.1Skamil#endif
55561.1Skamil	sigset_t intmask;
55571.1Skamil
55581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55601.1Skamil	if (child == 0) {
55611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55631.1Skamil
55641.1Skamil		sigemptyset(&intmask);
55651.1Skamil		sigaddset(&intmask, sigmasked);
55661.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
55671.1Skamil
55681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55701.1Skamil
55711.13Schristos		DPRINTF("Before raising %s from child\n",
55721.1Skamil		    strsignal(signotmasked));
55731.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
55741.1Skamil
55751.13Schristos		DPRINTF("Before exiting of the child process\n");
55761.1Skamil		_exit(exitval);
55771.1Skamil	}
55781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55791.1Skamil
55801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55821.1Skamil
55831.1Skamil	validate_status_stopped(status, sigval);
55841.1Skamil
55851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55861.1Skamil	    "without signal to be sent\n");
55871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55881.1Skamil
55891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55911.1Skamil
55921.1Skamil	validate_status_stopped(status, signotmasked);
55931.1Skamil
55941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55951.1Skamil	    "without signal to be sent\n");
55961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55971.1Skamil
55981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56001.1Skamil
56011.1Skamil	validate_status_exited(status, exitval);
56021.1Skamil
56031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56041.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56051.1Skamil}
56061.1Skamil
56071.1SkamilATF_TC(signal2);
56081.1SkamilATF_TC_HEAD(signal2, tc)
56091.1Skamil{
56101.1Skamil	atf_tc_set_md_var(tc, "descr",
56111.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
56121.1Skamil	    "catching this raised signal");
56131.1Skamil}
56141.1Skamil
56151.1SkamilATF_TC_BODY(signal2, tc)
56161.1Skamil{
56171.1Skamil	const int exitval = 5;
56181.1Skamil	const int sigval = SIGSTOP;
56191.1Skamil	const int sigmasked = SIGTRAP;
56201.1Skamil	pid_t child, wpid;
56211.1Skamil#if defined(TWAIT_HAVE_STATUS)
56221.1Skamil	int status;
56231.1Skamil#endif
56241.1Skamil	sigset_t intmask;
56251.1Skamil
56261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56281.1Skamil	if (child == 0) {
56291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56311.1Skamil
56321.1Skamil		sigemptyset(&intmask);
56331.1Skamil		sigaddset(&intmask, sigmasked);
56341.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56351.1Skamil
56361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56381.1Skamil
56391.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
56401.1Skamil		    strsignal(sigmasked));
56411.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
56421.1Skamil
56431.13Schristos		DPRINTF("Before exiting of the child process\n");
56441.1Skamil		_exit(exitval);
56451.1Skamil	}
56461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56471.1Skamil
56481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56501.1Skamil
56511.1Skamil	validate_status_stopped(status, sigval);
56521.1Skamil
56531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56541.1Skamil	    "without signal to be sent\n");
56551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56561.1Skamil
56571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56591.1Skamil
56601.1Skamil	validate_status_exited(status, exitval);
56611.1Skamil
56621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56641.1Skamil}
56651.1Skamil
56661.1SkamilATF_TC(signal3);
56671.1SkamilATF_TC_HEAD(signal3, tc)
56681.1Skamil{
56691.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
56701.1Skamil	atf_tc_set_md_var(tc, "descr",
56711.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
56721.1Skamil	    "catching software breakpoints");
56731.1Skamil}
56741.1Skamil
56751.1SkamilATF_TC_BODY(signal3, tc)
56761.1Skamil{
56771.1Skamil	const int exitval = 5;
56781.1Skamil	const int sigval = SIGSTOP;
56791.1Skamil	const int sigmasked = SIGTRAP;
56801.1Skamil	pid_t child, wpid;
56811.1Skamil#if defined(TWAIT_HAVE_STATUS)
56821.1Skamil	int status;
56831.1Skamil#endif
56841.1Skamil	sigset_t intmask;
56851.1Skamil
56861.20Skamil	atf_tc_expect_fail("PR kern/51918");
56871.20Skamil
56881.20Skamil	// This test breaks now on some ports, temporarily disable it
56891.20Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
56901.20Skamil
56911.10Smartin#if defined(__sparc__)
56921.7Skamil	atf_tc_expect_timeout("PR kern/52167");
56931.7Skamil
56941.7Skamil	// timeout wins, failure still valid
56951.7Skamil	// atf_tc_expect_fail("PR kern/51918");
56961.7Skamil#endif
56971.1Skamil
56981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57001.1Skamil	if (child == 0) {
57011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57031.1Skamil
57041.1Skamil		sigemptyset(&intmask);
57051.1Skamil		sigaddset(&intmask, sigmasked);
57061.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57071.1Skamil
57081.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57091.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57101.1Skamil
57111.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
57121.4Skamil
57131.4Skamil#ifdef PTRACE_BREAKPOINT_ASM
57141.4Skamil		PTRACE_BREAKPOINT_ASM;
57151.1Skamil#else
57161.4Skamil		/* port me */
57171.1Skamil#endif
57181.1Skamil
57191.13Schristos		DPRINTF("Before exiting of the child process\n");
57201.1Skamil		_exit(exitval);
57211.1Skamil	}
57221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57231.1Skamil
57241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57261.1Skamil
57271.1Skamil	validate_status_stopped(status, sigval);
57281.1Skamil
57291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57301.1Skamil	    "without signal to be sent\n");
57311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57321.1Skamil
57331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57351.1Skamil
57361.1Skamil	validate_status_stopped(status, sigmasked);
57371.1Skamil
57381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57391.1Skamil	    "without signal to be sent\n");
57401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57411.1Skamil
57421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57441.1Skamil
57451.1Skamil	validate_status_exited(status, exitval);
57461.1Skamil
57471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57491.1Skamil}
57501.1Skamil
57511.1Skamil#if defined(PT_STEP)
57521.1SkamilATF_TC(signal4);
57531.1SkamilATF_TC_HEAD(signal4, tc)
57541.1Skamil{
57551.1Skamil	atf_tc_set_md_var(tc, "descr",
57561.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57571.1Skamil	    "catching single step trap");
57581.1Skamil}
57591.1Skamil
57601.1SkamilATF_TC_BODY(signal4, tc)
57611.1Skamil{
57621.1Skamil	const int exitval = 5;
57631.1Skamil	const int sigval = SIGSTOP;
57641.1Skamil	const int sigmasked = SIGTRAP;
57651.1Skamil	pid_t child, wpid;
57661.1Skamil#if defined(TWAIT_HAVE_STATUS)
57671.1Skamil	int status;
57681.1Skamil#endif
57691.1Skamil	sigset_t intmask;
57701.1Skamil	int happy;
57711.1Skamil
57721.1Skamil#if defined(__arm__)
57731.5Skamil	/* PT_STEP not supported on arm 32-bit */
57741.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
57751.1Skamil#endif
57761.1Skamil
57771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57791.1Skamil	if (child == 0) {
57801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57821.1Skamil
57831.1Skamil		happy = check_happy(100);
57841.1Skamil
57851.1Skamil		sigemptyset(&intmask);
57861.1Skamil		sigaddset(&intmask, sigmasked);
57871.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57881.1Skamil
57891.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57901.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57911.1Skamil
57921.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
57931.1Skamil
57941.13Schristos		DPRINTF("Before exiting of the child process\n");
57951.1Skamil		_exit(exitval);
57961.1Skamil	}
57971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57981.1Skamil
57991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58011.1Skamil
58021.1Skamil	validate_status_stopped(status, sigval);
58031.1Skamil
58041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58051.1Skamil	    "without signal to be sent\n");
58061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
58071.1Skamil
58081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58101.1Skamil
58111.1Skamil	validate_status_stopped(status, sigmasked);
58121.1Skamil
58131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58141.1Skamil	    "without signal to be sent\n");
58151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58161.1Skamil
58171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58191.1Skamil
58201.1Skamil	validate_status_exited(status, exitval);
58211.1Skamil
58221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58241.1Skamil}
58251.1Skamil#endif
58261.1Skamil
58271.1SkamilATF_TC(signal5);
58281.1SkamilATF_TC_HEAD(signal5, tc)
58291.1Skamil{
58301.1Skamil	atf_tc_set_md_var(tc, "descr",
58311.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58321.1Skamil	    "catching exec() breakpoint");
58331.1Skamil}
58341.1Skamil
58351.1SkamilATF_TC_BODY(signal5, tc)
58361.1Skamil{
58371.1Skamil	const int exitval = 5;
58381.1Skamil	const int sigval = SIGSTOP;
58391.1Skamil	const int sigmasked = SIGTRAP;
58401.1Skamil	pid_t child, wpid;
58411.1Skamil#if defined(TWAIT_HAVE_STATUS)
58421.1Skamil	int status;
58431.1Skamil#endif
58441.1Skamil	sigset_t intmask;
58451.1Skamil
58461.14Schristos	atf_tc_expect_fail("wrong signal");
58471.14Schristos
58481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58501.1Skamil	if (child == 0) {
58511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58531.1Skamil
58541.1Skamil		sigemptyset(&intmask);
58551.1Skamil		sigaddset(&intmask, sigmasked);
58561.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
58571.1Skamil
58581.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58591.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58601.1Skamil
58611.13Schristos		DPRINTF("Before calling execve(2) from child\n");
58621.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
58631.1Skamil
58641.13Schristos		DPRINTF("Before exiting of the child process\n");
58651.1Skamil		_exit(exitval);
58661.1Skamil	}
58671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58681.1Skamil
58691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58711.1Skamil
58721.1Skamil	validate_status_stopped(status, sigval);
58731.1Skamil
58741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58751.1Skamil	    "without signal to be sent\n");
58761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58771.1Skamil
58781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58801.1Skamil
58811.1Skamil	validate_status_stopped(status, sigmasked);
58821.1Skamil
58831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58841.1Skamil	    "without signal to be sent\n");
58851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58861.1Skamil
58871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58891.1Skamil
58901.1Skamil	validate_status_exited(status, exitval);
58911.1Skamil
58921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58941.1Skamil}
58951.1Skamil
58961.1Skamil#if defined(TWAIT_HAVE_PID)
58971.1SkamilATF_TC(signal6);
58981.1SkamilATF_TC_HEAD(signal6, tc)
58991.1Skamil{
59001.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
59011.1Skamil	atf_tc_set_md_var(tc, "descr",
59021.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
59031.1Skamil	    "catching PTRACE_FORK breakpoint");
59041.1Skamil}
59051.1Skamil
59061.1SkamilATF_TC_BODY(signal6, tc)
59071.1Skamil{
59081.1Skamil	const int exitval = 5;
59091.1Skamil	const int exitval2 = 15;
59101.1Skamil	const int sigval = SIGSTOP;
59111.1Skamil	const int sigmasked = SIGTRAP;
59121.1Skamil	pid_t child, child2, wpid;
59131.1Skamil#if defined(TWAIT_HAVE_STATUS)
59141.1Skamil	int status;
59151.1Skamil#endif
59161.1Skamil	sigset_t intmask;
59171.1Skamil	ptrace_state_t state;
59181.1Skamil	const int slen = sizeof(state);
59191.1Skamil	ptrace_event_t event;
59201.1Skamil	const int elen = sizeof(event);
59211.1Skamil
59221.14Schristos	atf_tc_expect_timeout("PR kern/51918");
59231.14Schristos
59241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59261.1Skamil	if (child == 0) {
59271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59291.1Skamil
59301.1Skamil		sigemptyset(&intmask);
59311.1Skamil		sigaddset(&intmask, sigmasked);
59321.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
59331.1Skamil
59341.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59351.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59361.1Skamil
59371.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
59381.1Skamil
59391.1Skamil		if (child2 == 0)
59401.1Skamil			_exit(exitval2);
59411.1Skamil
59421.1Skamil		FORKEE_REQUIRE_SUCCESS
59431.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
59441.1Skamil
59451.1Skamil		forkee_status_exited(status, exitval2);
59461.1Skamil
59471.13Schristos		DPRINTF("Before exiting of the child process\n");
59481.1Skamil		_exit(exitval);
59491.1Skamil	}
59501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59511.1Skamil
59521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59541.1Skamil
59551.1Skamil	validate_status_stopped(status, sigval);
59561.1Skamil
59571.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
59581.1Skamil	event.pe_set_event = PTRACE_FORK;
59591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
59601.1Skamil
59611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59621.1Skamil	    "without signal to be sent\n");
59631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59641.1Skamil
59651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59671.1Skamil
59681.1Skamil	validate_status_stopped(status, sigmasked);
59691.1Skamil
59701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
59711.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
59721.1Skamil
59731.1Skamil	child2 = state.pe_other_pid;
59741.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
59751.1Skamil
59761.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
59771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59781.1Skamil	    child2);
59791.1Skamil
59801.1Skamil	validate_status_stopped(status, SIGTRAP);
59811.1Skamil
59821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
59831.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
59841.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
59851.1Skamil
59861.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
59871.1Skamil	    "without signal to be sent\n");
59881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
59891.1Skamil
59901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59911.1Skamil	    "without signal to be sent\n");
59921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59931.1Skamil
59941.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
59951.1Skamil	    TWAIT_FNAME);
59961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59971.1Skamil	    child2);
59981.1Skamil
59991.1Skamil	validate_status_exited(status, exitval2);
60001.1Skamil
60011.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
60021.1Skamil	    TWAIT_FNAME);
60031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
60041.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
60051.1Skamil
60061.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60071.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
60081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60091.1Skamil
60101.1Skamil	validate_status_stopped(status, SIGCHLD);
60111.1Skamil
60121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60131.1Skamil	    "without signal to be sent\n");
60141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60151.1Skamil
60161.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60171.1Skamil	    TWAIT_FNAME);
60181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60191.1Skamil
60201.1Skamil	validate_status_exited(status, exitval);
60211.1Skamil
60221.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60231.1Skamil	    TWAIT_FNAME);
60241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60251.1Skamil}
60261.1Skamil#endif
60271.1Skamil
60281.1Skamil#if defined(TWAIT_HAVE_PID)
60291.1SkamilATF_TC(signal7);
60301.1SkamilATF_TC_HEAD(signal7, tc)
60311.1Skamil{
60321.1Skamil	atf_tc_set_md_var(tc, "descr",
60331.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
60341.1Skamil	    "catching PTRACE_VFORK breakpoint");
60351.1Skamil}
60361.1Skamil
60371.1SkamilATF_TC_BODY(signal7, tc)
60381.1Skamil{
60391.1Skamil	const int exitval = 5;
60401.1Skamil	const int exitval2 = 15;
60411.1Skamil	const int sigval = SIGSTOP;
60421.1Skamil	const int sigmasked = SIGTRAP;
60431.1Skamil	pid_t child, child2, wpid;
60441.1Skamil#if defined(TWAIT_HAVE_STATUS)
60451.1Skamil	int status;
60461.1Skamil#endif
60471.1Skamil	sigset_t intmask;
60481.1Skamil	ptrace_state_t state;
60491.1Skamil	const int slen = sizeof(state);
60501.1Skamil	ptrace_event_t event;
60511.1Skamil	const int elen = sizeof(event);
60521.1Skamil
60531.14Schristos	atf_tc_expect_fail("PR kern/51918 PR kern/51630");
60541.14Schristos
60551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60571.1Skamil	if (child == 0) {
60581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60601.1Skamil
60611.1Skamil		sigemptyset(&intmask);
60621.1Skamil		sigaddset(&intmask, sigmasked);
60631.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
60641.1Skamil
60651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60671.1Skamil
60681.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
60691.1Skamil
60701.1Skamil		if (child2 == 0)
60711.1Skamil			_exit(exitval2);
60721.1Skamil
60731.1Skamil		FORKEE_REQUIRE_SUCCESS
60741.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
60751.1Skamil
60761.1Skamil		forkee_status_exited(status, exitval2);
60771.1Skamil
60781.13Schristos		DPRINTF("Before exiting of the child process\n");
60791.1Skamil		_exit(exitval);
60801.1Skamil	}
60811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60821.1Skamil
60831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60851.1Skamil
60861.1Skamil	validate_status_stopped(status, sigval);
60871.1Skamil
60881.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
60891.1Skamil	event.pe_set_event = PTRACE_VFORK;
60901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || errno == ENOTSUP);
60911.1Skamil
60921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60931.1Skamil	    "without signal to be sent\n");
60941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60951.1Skamil
60961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60981.1Skamil
60991.1Skamil	validate_status_stopped(status, sigmasked);
61001.1Skamil
61011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
61021.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
61031.1Skamil
61041.1Skamil	child2 = state.pe_other_pid;
61051.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
61061.1Skamil
61071.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
61081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
61091.1Skamil	    child2);
61101.1Skamil
61111.1Skamil	validate_status_stopped(status, SIGTRAP);
61121.1Skamil
61131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
61141.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
61151.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
61161.1Skamil
61171.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
61181.1Skamil	    "without signal to be sent\n");
61191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
61201.1Skamil
61211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61221.1Skamil	    "without signal to be sent\n");
61231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61241.1Skamil
61251.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
61261.1Skamil	    TWAIT_FNAME);
61271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
61281.1Skamil	    child2);
61291.1Skamil
61301.1Skamil	validate_status_exited(status, exitval2);
61311.1Skamil
61321.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
61331.1Skamil	    TWAIT_FNAME);
61341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
61351.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
61361.1Skamil
61371.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61381.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
61391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61401.1Skamil
61411.1Skamil	validate_status_stopped(status, SIGCHLD);
61421.1Skamil
61431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61441.1Skamil	    "without signal to be sent\n");
61451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61461.1Skamil
61471.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61481.1Skamil	    TWAIT_FNAME);
61491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61501.1Skamil
61511.1Skamil	validate_status_exited(status, exitval);
61521.1Skamil
61531.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61541.1Skamil	    TWAIT_FNAME);
61551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61561.1Skamil}
61571.1Skamil#endif
61581.1Skamil
61591.1SkamilATF_TC(signal8);
61601.1SkamilATF_TC_HEAD(signal8, tc)
61611.1Skamil{
61621.1Skamil	atf_tc_set_md_var(tc, "descr",
61631.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61641.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
61651.1Skamil}
61661.1Skamil
61671.1SkamilATF_TC_BODY(signal8, tc)
61681.1Skamil{
61691.1Skamil	const int exitval = 5;
61701.1Skamil	const int exitval2 = 15;
61711.1Skamil	const int sigval = SIGSTOP;
61721.1Skamil	const int sigmasked = SIGTRAP;
61731.1Skamil	pid_t child, child2, wpid;
61741.1Skamil#if defined(TWAIT_HAVE_STATUS)
61751.1Skamil	int status;
61761.1Skamil#endif
61771.1Skamil	sigset_t intmask;
61781.1Skamil	ptrace_state_t state;
61791.1Skamil	const int slen = sizeof(state);
61801.1Skamil	ptrace_event_t event;
61811.1Skamil	const int elen = sizeof(event);
61821.1Skamil
61831.14Schristos	atf_tc_expect_fail("PR kern/51918");
61841.14Schristos
61851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61871.1Skamil	if (child == 0) {
61881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61901.1Skamil
61911.1Skamil		sigemptyset(&intmask);
61921.1Skamil		sigaddset(&intmask, sigmasked);
61931.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61941.1Skamil
61951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61971.1Skamil
61981.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
61991.1Skamil
62001.1Skamil		if (child2 == 0)
62011.1Skamil			_exit(exitval2);
62021.1Skamil
62031.1Skamil		FORKEE_REQUIRE_SUCCESS
62041.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
62051.1Skamil
62061.1Skamil		forkee_status_exited(status, exitval2);
62071.1Skamil
62081.13Schristos		DPRINTF("Before exiting of the child process\n");
62091.1Skamil		_exit(exitval);
62101.1Skamil	}
62111.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62121.1Skamil
62131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62151.1Skamil
62161.1Skamil	validate_status_stopped(status, sigval);
62171.1Skamil
62181.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
62191.1Skamil	    child);
62201.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
62211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62221.1Skamil
62231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62241.1Skamil	    "without signal to be sent\n");
62251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62261.1Skamil
62271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62291.1Skamil
62301.1Skamil	validate_status_stopped(status, sigmasked);
62311.1Skamil
62321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
62331.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
62341.1Skamil
62351.1Skamil	child2 = state.pe_other_pid;
62361.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
62371.1Skamil
62381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62391.1Skamil	    "without signal to be sent\n");
62401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62411.1Skamil
62421.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62431.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
62441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62451.1Skamil
62461.1Skamil	validate_status_stopped(status, SIGCHLD);
62471.1Skamil
62481.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62491.1Skamil	    "without signal to be sent\n");
62501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62511.1Skamil
62521.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62531.1Skamil	    TWAIT_FNAME);
62541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62551.1Skamil
62561.1Skamil	validate_status_exited(status, exitval);
62571.1Skamil
62581.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62591.1Skamil	    TWAIT_FNAME);
62601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62611.1Skamil}
62621.1Skamil
62631.1SkamilATF_TC(signal9);
62641.1SkamilATF_TC_HEAD(signal9, tc)
62651.1Skamil{
62661.1Skamil	atf_tc_set_md_var(tc, "descr",
62671.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
62681.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
62691.1Skamil}
62701.1Skamil
62711.1SkamilATF_TC_BODY(signal9, tc)
62721.1Skamil{
62731.1Skamil	const int exitval = 5;
62741.1Skamil	const int sigval = SIGSTOP;
62751.1Skamil	const int sigmasked = SIGTRAP;
62761.1Skamil	pid_t child, wpid;
62771.1Skamil#if defined(TWAIT_HAVE_STATUS)
62781.1Skamil	int status;
62791.1Skamil#endif
62801.1Skamil	sigset_t intmask;
62811.1Skamil	ptrace_state_t state;
62821.1Skamil	const int slen = sizeof(state);
62831.1Skamil	ptrace_event_t event;
62841.1Skamil	const int elen = sizeof(event);
62851.1Skamil	ucontext_t uc;
62861.1Skamil	lwpid_t lid;
62871.1Skamil	static const size_t ssize = 16*1024;
62881.1Skamil	void *stack;
62891.1Skamil
62901.14Schristos	atf_tc_expect_fail("PR kern/51918");
62911.14Schristos
62921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62941.1Skamil	if (child == 0) {
62951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62971.1Skamil
62981.1Skamil		sigemptyset(&intmask);
62991.1Skamil		sigaddset(&intmask, sigmasked);
63001.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
63011.1Skamil
63021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63041.1Skamil
63051.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63061.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63071.1Skamil
63081.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63091.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
63101.1Skamil
63111.13Schristos		DPRINTF("Before creating new in child\n");
63121.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63131.1Skamil
63141.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
63151.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
63161.1Skamil
63171.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
63181.1Skamil		    "are the same\n", lid, the_lwp_id);
63191.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63201.1Skamil
63211.13Schristos		DPRINTF("Before exiting of the child process\n");
63221.1Skamil		_exit(exitval);
63231.1Skamil	}
63241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63251.1Skamil
63261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63281.1Skamil
63291.1Skamil	validate_status_stopped(status, sigval);
63301.1Skamil
63311.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
63321.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
63331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
63341.1Skamil
63351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63361.1Skamil	    "without signal to be sent\n");
63371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63381.1Skamil
63391.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63401.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63421.1Skamil
63431.1Skamil	validate_status_stopped(status, sigmasked);
63441.1Skamil
63451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
63461.1Skamil
63471.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
63481.1Skamil
63491.1Skamil	lid = state.pe_lwp;
63501.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
63511.1Skamil
63521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63531.1Skamil	    "without signal to be sent\n");
63541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63551.1Skamil
63561.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63571.1Skamil	    TWAIT_FNAME);
63581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63591.1Skamil
63601.1Skamil	validate_status_exited(status, exitval);
63611.1Skamil
63621.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63631.1Skamil	    TWAIT_FNAME);
63641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63651.1Skamil}
63661.1Skamil
63671.1SkamilATF_TC(signal10);
63681.1SkamilATF_TC_HEAD(signal10, tc)
63691.1Skamil{
63701.1Skamil	atf_tc_set_md_var(tc, "descr",
63711.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
63721.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
63731.1Skamil}
63741.1Skamil
63751.1SkamilATF_TC_BODY(signal10, tc)
63761.1Skamil{
63771.1Skamil	const int exitval = 5;
63781.1Skamil	const int sigval = SIGSTOP;
63791.1Skamil	const int sigmasked = SIGTRAP;
63801.1Skamil	pid_t child, wpid;
63811.1Skamil#if defined(TWAIT_HAVE_STATUS)
63821.1Skamil	int status;
63831.1Skamil#endif
63841.1Skamil	sigset_t intmask;
63851.1Skamil	ptrace_state_t state;
63861.1Skamil	const int slen = sizeof(state);
63871.1Skamil	ptrace_event_t event;
63881.1Skamil	const int elen = sizeof(event);
63891.1Skamil	ucontext_t uc;
63901.1Skamil	lwpid_t lid;
63911.1Skamil	static const size_t ssize = 16*1024;
63921.1Skamil	void *stack;
63931.1Skamil
63941.14Schristos	atf_tc_expect_fail("PR kern/51918");
63951.14Schristos
63961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63981.1Skamil	if (child == 0) {
63991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64011.1Skamil
64021.1Skamil		sigemptyset(&intmask);
64031.1Skamil		sigaddset(&intmask, sigmasked);
64041.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
64051.1Skamil
64061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64081.1Skamil
64091.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
64101.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
64111.1Skamil
64121.13Schristos		DPRINTF("Before making context for new lwp in child\n");
64131.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
64141.1Skamil
64151.13Schristos		DPRINTF("Before creating new in child\n");
64161.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
64171.1Skamil
64181.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
64191.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
64201.1Skamil
64211.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
64221.1Skamil		    "are the same\n", lid, the_lwp_id);
64231.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
64241.1Skamil
64251.13Schristos		DPRINTF("Before exiting of the child process\n");
64261.1Skamil		_exit(exitval);
64271.1Skamil	}
64281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64291.1Skamil
64301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64321.1Skamil
64331.1Skamil	validate_status_stopped(status, sigval);
64341.1Skamil
64351.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
64361.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
64371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
64381.1Skamil
64391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64401.1Skamil	    "without signal to be sent\n");
64411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64421.1Skamil
64431.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64441.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
64451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64461.1Skamil
64471.1Skamil	validate_status_stopped(status, sigmasked);
64481.1Skamil
64491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
64501.1Skamil
64511.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
64521.1Skamil
64531.1Skamil	lid = state.pe_lwp;
64541.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
64551.1Skamil
64561.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64571.1Skamil	    "without signal to be sent\n");
64581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64591.1Skamil
64601.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
64611.1Skamil	    TWAIT_FNAME);
64621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64631.1Skamil
64641.1Skamil	validate_status_exited(status, exitval);
64651.1Skamil
64661.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64671.1Skamil	    TWAIT_FNAME);
64681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64691.1Skamil}
64701.1Skamil
64711.1Skamilstatic void
64721.1Skamillwp_main_stop(void *arg)
64731.1Skamil{
64741.1Skamil	the_lwp_id = _lwp_self();
64751.1Skamil
64761.1Skamil	raise(SIGTRAP);
64771.1Skamil
64781.1Skamil	_lwp_exit();
64791.1Skamil}
64801.1Skamil
64811.1SkamilATF_TC(suspend1);
64821.1SkamilATF_TC_HEAD(suspend1, tc)
64831.1Skamil{
64841.1Skamil	atf_tc_set_md_var(tc, "descr",
64851.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
64861.1Skamil	    "resumed by a tracee");
64871.1Skamil}
64881.1Skamil
64891.1SkamilATF_TC_BODY(suspend1, tc)
64901.1Skamil{
64911.1Skamil	const int exitval = 5;
64921.1Skamil	const int sigval = SIGSTOP;
64931.1Skamil	pid_t child, wpid;
64941.1Skamil#if defined(TWAIT_HAVE_STATUS)
64951.1Skamil	int status;
64961.1Skamil#endif
64971.1Skamil	ucontext_t uc;
64981.1Skamil	lwpid_t lid;
64991.1Skamil	static const size_t ssize = 16*1024;
65001.1Skamil	void *stack;
65011.1Skamil	struct ptrace_lwpinfo pl;
65021.1Skamil	struct ptrace_siginfo psi;
65031.1Skamil	volatile int go = 0;
65041.1Skamil
65051.17Skamil	// Feature pending for refactoring
65061.17Skamil	atf_tc_expect_fail("PR kern/51995");
65071.17Skamil
65081.16Skamil	// Hangs with qemu
65091.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
65101.16Skamil
65111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
65121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
65131.1Skamil	if (child == 0) {
65141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65161.1Skamil
65171.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65181.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65191.1Skamil
65201.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
65211.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
65221.1Skamil
65231.13Schristos		DPRINTF("Before making context for new lwp in child\n");
65241.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
65251.1Skamil
65261.13Schristos		DPRINTF("Before creating new in child\n");
65271.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
65281.1Skamil
65291.1Skamil		while (go == 0)
65301.1Skamil			continue;
65311.1Skamil
65321.1Skamil		raise(SIGINT);
65331.1Skamil
65341.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
65351.1Skamil
65361.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
65371.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
65381.1Skamil
65391.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
65401.1Skamil		    "are the same\n", lid, the_lwp_id);
65411.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
65421.1Skamil
65431.13Schristos		DPRINTF("Before exiting of the child process\n");
65441.1Skamil		_exit(exitval);
65451.1Skamil	}
65461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65471.1Skamil
65481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65501.1Skamil
65511.1Skamil	validate_status_stopped(status, sigval);
65521.1Skamil
65531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65541.1Skamil	    "without signal to be sent\n");
65551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65561.1Skamil
65571.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65581.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
65591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65601.1Skamil
65611.1Skamil	validate_status_stopped(status, SIGTRAP);
65621.1Skamil
65631.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
65641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
65651.1Skamil
65661.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
65671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65681.1Skamil
65691.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
65701.1Skamil	    child, getpid());
65711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
65721.1Skamil
65731.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65741.1Skamil	    "without signal to be sent\n");
65751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65761.1Skamil
65771.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65781.1Skamil	    "SIGINT\n", TWAIT_FNAME);
65791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65801.1Skamil
65811.1Skamil	validate_status_stopped(status, SIGINT);
65821.1Skamil
65831.1Skamil	pl.pl_lwpid = 0;
65841.1Skamil
65851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65861.1Skamil	while (pl.pl_lwpid != 0) {
65871.1Skamil
65881.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65891.1Skamil		switch (pl.pl_lwpid) {
65901.1Skamil		case 1:
65911.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
65921.1Skamil			break;
65931.1Skamil		case 2:
65941.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
65951.1Skamil			break;
65961.1Skamil		}
65971.1Skamil	}
65981.1Skamil
65991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66001.1Skamil	    "without signal to be sent\n");
66011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66021.1Skamil
66031.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
66041.1Skamil	    TWAIT_FNAME);
66051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66061.1Skamil
66071.1Skamil	validate_status_exited(status, exitval);
66081.1Skamil
66091.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66101.1Skamil	    TWAIT_FNAME);
66111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66121.1Skamil}
66131.1Skamil
66141.1SkamilATF_TC(suspend2);
66151.1SkamilATF_TC_HEAD(suspend2, tc)
66161.1Skamil{
66171.1Skamil	atf_tc_set_md_var(tc, "descr",
66181.1Skamil	    "Verify that the while the only thread within a process is "
66191.1Skamil	    "suspended, the whole process cannot be unstopped");
66201.1Skamil}
66211.1Skamil
66221.1SkamilATF_TC_BODY(suspend2, tc)
66231.1Skamil{
66241.1Skamil	const int exitval = 5;
66251.1Skamil	const int sigval = SIGSTOP;
66261.1Skamil	pid_t child, wpid;
66271.1Skamil#if defined(TWAIT_HAVE_STATUS)
66281.1Skamil	int status;
66291.1Skamil#endif
66301.1Skamil	struct ptrace_siginfo psi;
66311.1Skamil
66321.17Skamil	// Feature pending for refactoring
66331.17Skamil	atf_tc_expect_fail("PR kern/51995");
66341.17Skamil
66351.16Skamil	// Hangs with qemu
66361.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
66371.16Skamil
66381.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66391.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66401.1Skamil	if (child == 0) {
66411.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66421.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66431.1Skamil
66441.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66451.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66461.1Skamil
66471.13Schristos		DPRINTF("Before exiting of the child process\n");
66481.1Skamil		_exit(exitval);
66491.1Skamil	}
66501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66511.1Skamil
66521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66541.1Skamil
66551.1Skamil	validate_status_stopped(status, sigval);
66561.1Skamil
66571.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
66581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
66591.1Skamil
66601.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
66611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
66621.1Skamil
66631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66641.1Skamil	    "without signal to be sent\n");
66651.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
66661.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
66671.1Skamil
66681.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
66691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
66701.1Skamil
66711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66721.1Skamil	    "without signal to be sent\n");
66731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66741.1Skamil
66751.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
66761.1Skamil	    TWAIT_FNAME);
66771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66781.1Skamil
66791.1Skamil	validate_status_exited(status, exitval);
66801.1Skamil
66811.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66821.1Skamil	    TWAIT_FNAME);
66831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66841.1Skamil}
66851.1Skamil
66861.1SkamilATF_TC(resume1);
66871.1SkamilATF_TC_HEAD(resume1, tc)
66881.1Skamil{
66891.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
66901.1Skamil	atf_tc_set_md_var(tc, "descr",
66911.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
66921.1Skamil	    "resumed by the debugger");
66931.1Skamil}
66941.1Skamil
66951.1SkamilATF_TC_BODY(resume1, tc)
66961.1Skamil{
66971.1Skamil	struct msg_fds fds;
66981.1Skamil	const int exitval = 5;
66991.1Skamil	const int sigval = SIGSTOP;
67001.1Skamil	pid_t child, wpid;
67011.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
67021.1Skamil#if defined(TWAIT_HAVE_STATUS)
67031.1Skamil	int status;
67041.1Skamil#endif
67051.1Skamil	ucontext_t uc;
67061.1Skamil	lwpid_t lid;
67071.1Skamil	static const size_t ssize = 16*1024;
67081.1Skamil	void *stack;
67091.1Skamil	struct ptrace_lwpinfo pl;
67101.1Skamil	struct ptrace_siginfo psi;
67111.1Skamil
67121.17Skamil	// Feature pending for refactoring
67131.17Skamil	atf_tc_expect_fail("PR kern/51995");
67141.17Skamil
67151.15Schristos	// Hangs with qemu
67161.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
67171.1Skamil
67181.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
67191.1Skamil
67201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67221.1Skamil	if (child == 0) {
67231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67251.1Skamil
67261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67281.1Skamil
67291.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
67301.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
67311.1Skamil
67321.13Schristos		DPRINTF("Before making context for new lwp in child\n");
67331.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
67341.1Skamil
67351.13Schristos		DPRINTF("Before creating new in child\n");
67361.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
67371.1Skamil
67381.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
67391.1Skamil
67401.1Skamil		raise(SIGINT);
67411.1Skamil
67421.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
67431.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
67441.1Skamil
67451.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
67461.1Skamil		    "are the same\n", lid, the_lwp_id);
67471.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
67481.1Skamil
67491.13Schristos		DPRINTF("Before exiting of the child process\n");
67501.1Skamil		_exit(exitval);
67511.1Skamil	}
67521.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67531.1Skamil
67541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67561.1Skamil
67571.1Skamil	validate_status_stopped(status, sigval);
67581.1Skamil
67591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67601.1Skamil	    "without signal to be sent\n");
67611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67621.1Skamil
67631.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67641.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
67651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67661.1Skamil
67671.1Skamil	validate_status_stopped(status, SIGTRAP);
67681.1Skamil
67691.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
67701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
67711.1Skamil
67721.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
67731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
67741.1Skamil
67751.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
67761.1Skamil
67771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67781.1Skamil	    "without signal to be sent\n");
67791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67801.1Skamil
67811.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67821.1Skamil	    "SIGINT\n", TWAIT_FNAME);
67831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67841.1Skamil
67851.1Skamil	validate_status_stopped(status, SIGINT);
67861.1Skamil
67871.1Skamil	pl.pl_lwpid = 0;
67881.1Skamil
67891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67901.1Skamil	while (pl.pl_lwpid != 0) {
67911.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67921.1Skamil		switch (pl.pl_lwpid) {
67931.1Skamil		case 1:
67941.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
67951.1Skamil			break;
67961.1Skamil		case 2:
67971.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
67981.1Skamil			break;
67991.1Skamil		}
68001.1Skamil	}
68011.1Skamil
68021.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
68031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
68041.1Skamil
68051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68061.1Skamil	    "without signal to be sent\n");
68071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68081.1Skamil
68091.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
68101.1Skamil	    TWAIT_FNAME);
68111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68121.1Skamil
68131.1Skamil	validate_status_exited(status, exitval);
68141.1Skamil
68151.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
68161.1Skamil	    TWAIT_FNAME);
68171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68181.1Skamil
68191.1Skamil	msg_close(&fds);
68201.1Skamil
68211.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
68221.1Skamil	sleep(10);
68231.1Skamil}
68241.1Skamil
68251.1SkamilATF_TC(syscall1);
68261.1SkamilATF_TC_HEAD(syscall1, tc)
68271.1Skamil{
68281.1Skamil	atf_tc_set_md_var(tc, "descr",
68291.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
68301.1Skamil}
68311.1Skamil
68321.1SkamilATF_TC_BODY(syscall1, tc)
68331.1Skamil{
68341.1Skamil	const int exitval = 5;
68351.1Skamil	const int sigval = SIGSTOP;
68361.1Skamil	pid_t child, wpid;
68371.1Skamil#if defined(TWAIT_HAVE_STATUS)
68381.1Skamil	int status;
68391.1Skamil#endif
68401.1Skamil	struct ptrace_siginfo info;
68411.1Skamil	memset(&info, 0, sizeof(info));
68421.1Skamil
68431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
68441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
68451.1Skamil	if (child == 0) {
68461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68481.1Skamil
68491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68511.1Skamil
68521.1Skamil		syscall(SYS_getpid);
68531.1Skamil
68541.13Schristos		DPRINTF("Before exiting of the child process\n");
68551.1Skamil		_exit(exitval);
68561.1Skamil	}
68571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
68581.1Skamil
68591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68611.1Skamil
68621.1Skamil	validate_status_stopped(status, sigval);
68631.1Skamil
68641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68651.1Skamil	    "without signal to be sent\n");
68661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68671.1Skamil
68681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68701.1Skamil
68711.1Skamil	validate_status_stopped(status, SIGTRAP);
68721.1Skamil
68731.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
68741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
68751.1Skamil
68761.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
68771.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
68781.1Skamil
68791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68801.1Skamil	    "without signal to be sent\n");
68811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68821.1Skamil
68831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68851.1Skamil
68861.1Skamil	validate_status_stopped(status, SIGTRAP);
68871.1Skamil
68881.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
68891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
68901.1Skamil
68911.13Schristos	DPRINTF("Before checking siginfo_t\n");
68921.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
68931.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
68941.1Skamil
68951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68961.1Skamil	    "without signal to be sent\n");
68971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68981.1Skamil
68991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69011.1Skamil
69021.1Skamil	validate_status_exited(status, exitval);
69031.1Skamil
69041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69051.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69061.1Skamil}
69071.1Skamil
69081.1SkamilATF_TC(syscallemu1);
69091.1SkamilATF_TC_HEAD(syscallemu1, tc)
69101.1Skamil{
69111.1Skamil	atf_tc_set_md_var(tc, "descr",
69121.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
69131.1Skamil}
69141.1Skamil
69151.1SkamilATF_TC_BODY(syscallemu1, tc)
69161.1Skamil{
69171.1Skamil	const int exitval = 5;
69181.1Skamil	const int sigval = SIGSTOP;
69191.1Skamil	pid_t child, wpid;
69201.1Skamil#if defined(TWAIT_HAVE_STATUS)
69211.1Skamil	int status;
69221.1Skamil#endif
69231.1Skamil
69241.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
69251.6Skamil	/* syscallemu does not work on sparc (32-bit) */
69261.6Skamil	atf_tc_expect_fail("PR kern/52166");
69271.6Skamil#endif
69281.6Skamil
69291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
69301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
69311.1Skamil	if (child == 0) {
69321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
69331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
69341.1Skamil
69351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
69361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
69371.1Skamil
69381.1Skamil		syscall(SYS_exit, 100);
69391.1Skamil
69401.13Schristos		DPRINTF("Before exiting of the child process\n");
69411.1Skamil		_exit(exitval);
69421.1Skamil	}
69431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
69441.1Skamil
69451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69471.1Skamil
69481.1Skamil	validate_status_stopped(status, sigval);
69491.1Skamil
69501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69511.1Skamil	    "without signal to be sent\n");
69521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69531.1Skamil
69541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69561.1Skamil
69571.1Skamil	validate_status_stopped(status, SIGTRAP);
69581.1Skamil
69591.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
69601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
69611.1Skamil
69621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69631.1Skamil	    "without signal to be sent\n");
69641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69651.1Skamil
69661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69681.1Skamil
69691.1Skamil	validate_status_stopped(status, SIGTRAP);
69701.1Skamil
69711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69721.1Skamil	    "without signal to be sent\n");
69731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69741.1Skamil
69751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69771.1Skamil
69781.1Skamil	validate_status_exited(status, exitval);
69791.1Skamil
69801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69821.1Skamil}
69831.1Skamil
69841.26Skamil#if defined(TWAIT_HAVE_PID)
69851.26SkamilATF_TC(race1);
69861.26SkamilATF_TC_HEAD(race1, tc)
69871.26Skamil{
69881.26Skamil	atf_tc_set_md_var(tc, "descr",
69891.26Skamil	    "Assert that await_zombie() in attach1 always finds a single "
69901.26Skamil	    "process and no other error is reported");
69911.26Skamil}
69921.26Skamil
69931.26SkamilATF_TC_BODY(race1, tc)
69941.26Skamil{
69951.26Skamil	time_t start, end;
69961.26Skamil	double diff;
69971.26Skamil	unsigned long N = 0;
69981.26Skamil
69991.26Skamil	/* Reuse this test with attach1 */
70001.26Skamil
70011.26Skamil	start = time(NULL);
70021.26Skamil	while (true) {
70031.26Skamil		DPRINTF("Step: %lu\n", N);
70041.26Skamil		attach1_raw(true);
70051.26Skamil		end = time(NULL);
70061.26Skamil		diff = difftime(end, start);
70071.26Skamil		if (diff >= 5.0)
70081.26Skamil			break;
70091.26Skamil		++N;
70101.26Skamil	}
70111.26Skamil	DPRINTF("Iterations: %lu\n", N);
70121.26Skamil}
70131.26Skamil#endif
70141.26Skamil
70151.1Skamil#include "t_ptrace_amd64_wait.h"
70161.1Skamil#include "t_ptrace_i386_wait.h"
70171.1Skamil#include "t_ptrace_x86_wait.h"
70181.1Skamil
70191.1SkamilATF_TP_ADD_TCS(tp)
70201.1Skamil{
70211.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
70221.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
70231.1Skamil	ATF_TP_ADD_TC(tp, traceme1);
70241.1Skamil	ATF_TP_ADD_TC(tp, traceme2);
70251.1Skamil	ATF_TP_ADD_TC(tp, traceme3);
70261.1Skamil	ATF_TP_ADD_TC(tp, traceme4);
70271.1Skamil
70281.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach1);
70291.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach2);
70301.1Skamil	ATF_TP_ADD_TC(tp, attach3);
70311.1Skamil	ATF_TP_ADD_TC(tp, attach4);
70321.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach5);
70331.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach6);
70341.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach7);
70351.1Skamil
70361.1Skamil	ATF_TP_ADD_TC(tp, eventmask1);
70371.1Skamil	ATF_TP_ADD_TC(tp, eventmask2);
70381.1Skamil	ATF_TP_ADD_TC(tp, eventmask3);
70391.1Skamil	ATF_TP_ADD_TC(tp, eventmask4);
70401.1Skamil	ATF_TP_ADD_TC(tp, eventmask5);
70411.1Skamil	ATF_TP_ADD_TC(tp, eventmask6);
70421.1Skamil
70431.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork1);
70441.1Skamil	ATF_TP_ADD_TC(tp, fork2);
70451.1Skamil
70461.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork1);
70471.1Skamil	ATF_TP_ADD_TC(tp, vfork2);
70481.1Skamil
70491.1Skamil	ATF_TP_ADD_TC(tp, vforkdone1);
70501.1Skamil	ATF_TP_ADD_TC(tp, vforkdone2);
70511.1Skamil
70521.1Skamil	ATF_TP_ADD_TC(tp, io_read_d1);
70531.1Skamil	ATF_TP_ADD_TC(tp, io_read_d2);
70541.1Skamil	ATF_TP_ADD_TC(tp, io_read_d3);
70551.1Skamil	ATF_TP_ADD_TC(tp, io_read_d4);
70561.1Skamil
70571.1Skamil	ATF_TP_ADD_TC(tp, io_write_d1);
70581.1Skamil	ATF_TP_ADD_TC(tp, io_write_d2);
70591.1Skamil	ATF_TP_ADD_TC(tp, io_write_d3);
70601.1Skamil	ATF_TP_ADD_TC(tp, io_write_d4);
70611.1Skamil
70621.1Skamil	ATF_TP_ADD_TC(tp, read_d1);
70631.1Skamil	ATF_TP_ADD_TC(tp, read_d2);
70641.1Skamil	ATF_TP_ADD_TC(tp, read_d3);
70651.1Skamil	ATF_TP_ADD_TC(tp, read_d4);
70661.1Skamil
70671.1Skamil	ATF_TP_ADD_TC(tp, write_d1);
70681.1Skamil	ATF_TP_ADD_TC(tp, write_d2);
70691.1Skamil	ATF_TP_ADD_TC(tp, write_d3);
70701.1Skamil	ATF_TP_ADD_TC(tp, write_d4);
70711.1Skamil
70721.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake1);
70731.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake2);
70741.1Skamil
70751.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake1);
70761.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake2);
70771.1Skamil
70781.1Skamil	ATF_TP_ADD_TC(tp, io_read_i1);
70791.1Skamil	ATF_TP_ADD_TC(tp, io_read_i2);
70801.1Skamil	ATF_TP_ADD_TC(tp, io_read_i3);
70811.1Skamil	ATF_TP_ADD_TC(tp, io_read_i4);
70821.1Skamil
70831.1Skamil	ATF_TP_ADD_TC(tp, read_i1);
70841.1Skamil	ATF_TP_ADD_TC(tp, read_i2);
70851.1Skamil	ATF_TP_ADD_TC(tp, read_i3);
70861.1Skamil	ATF_TP_ADD_TC(tp, read_i4);
70871.1Skamil
70881.1Skamil	ATF_TP_ADD_TC(tp, io_read_auxv1);
70891.1Skamil
70901.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
70911.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
70921.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
70931.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
70941.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
70951.1Skamil
70961.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
70971.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
70981.1Skamil
70991.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
71001.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
71011.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
71021.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
71031.1Skamil
71041.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
71051.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
71061.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
71071.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
71081.2Skamil
71091.1Skamil	ATF_TP_ADD_TC(tp, kill1);
71101.1Skamil	ATF_TP_ADD_TC(tp, kill2);
71111.1Skamil
71121.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
71131.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
71141.1Skamil
71151.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
71161.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
71171.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
71181.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
71191.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
71201.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
71211.1Skamil
71221.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
71231.1Skamil
71241.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
71251.1Skamil
71261.1Skamil	ATF_TP_ADD_TC(tp, signal1);
71271.1Skamil	ATF_TP_ADD_TC(tp, signal2);
71281.1Skamil	ATF_TP_ADD_TC(tp, signal3);
71291.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
71301.1Skamil	ATF_TP_ADD_TC(tp, signal5);
71311.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
71321.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
71331.1Skamil	ATF_TP_ADD_TC(tp, signal8);
71341.1Skamil	ATF_TP_ADD_TC(tp, signal9);
71351.1Skamil	ATF_TP_ADD_TC(tp, signal10);
71361.1Skamil
71371.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
71381.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
71391.1Skamil
71401.1Skamil	ATF_TP_ADD_TC(tp, resume1);
71411.1Skamil
71421.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
71431.1Skamil
71441.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
71451.1Skamil
71461.26Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, race1);
71471.26Skamil
71481.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
71491.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
71501.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
71511.1Skamil
71521.1Skamil	return atf_no_error();
71531.1Skamil}
7154