t_ptrace_wait.c revision 1.165
11.165Skamil/* $NetBSD: t_ptrace_wait.c,v 1.165 2020/02/22 19:44:07 kamil Exp $ */ 21.1Skamil 31.1Skamil/*- 41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. 51.1Skamil * All rights reserved. 61.1Skamil * 71.1Skamil * Redistribution and use in source and binary forms, with or without 81.1Skamil * modification, are permitted provided that the following conditions 91.1Skamil * are met: 101.1Skamil * 1. Redistributions of source code must retain the above copyright 111.1Skamil * notice, this list of conditions and the following disclaimer. 121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright 131.1Skamil * notice, this list of conditions and the following disclaimer in the 141.1Skamil * documentation and/or other materials provided with the distribution. 151.1Skamil * 161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Skamil * POSSIBILITY OF SUCH DAMAGE. 271.1Skamil */ 281.1Skamil 291.1Skamil#include <sys/cdefs.h> 301.165Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.165 2020/02/22 19:44:07 kamil Exp $"); 311.143Skamil 321.143Skamil#define __LEGACY_PT_LWPINFO 331.1Skamil 341.1Skamil#include <sys/param.h> 351.1Skamil#include <sys/types.h> 361.130Smgorny#include <sys/exec_elf.h> 371.39Skamil#include <sys/mman.h> 381.1Skamil#include <sys/ptrace.h> 391.1Skamil#include <sys/resource.h> 401.1Skamil#include <sys/stat.h> 411.1Skamil#include <sys/syscall.h> 421.1Skamil#include <sys/sysctl.h> 431.129Smgorny#include <sys/uio.h> 441.1Skamil#include <sys/wait.h> 451.1Skamil#include <machine/reg.h> 461.132Skamil#include <assert.h> 471.1Skamil#include <elf.h> 481.1Skamil#include <err.h> 491.1Skamil#include <errno.h> 501.130Smgorny#include <fcntl.h> 511.1Skamil#include <lwp.h> 521.77Skamil#include <pthread.h> 531.1Skamil#include <sched.h> 541.1Skamil#include <signal.h> 551.124Skamil#include <spawn.h> 561.1Skamil#include <stdint.h> 571.1Skamil#include <stdio.h> 581.1Skamil#include <stdlib.h> 591.1Skamil#include <strings.h> 601.26Skamil#include <time.h> 611.1Skamil#include <unistd.h> 621.1Skamil 631.114Skamil#include <fenv.h> 641.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 651.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 661.114Skamil#endif 671.114Skamil 681.121Smgorny#if defined(__i386__) || defined(__x86_64__) 691.121Smgorny#include <cpuid.h> 701.121Smgorny#include <x86/cpu_extended_state.h> 711.129Smgorny#include <x86/specialreg.h> 721.121Smgorny#endif 731.121Smgorny 741.130Smgorny#include <libelf.h> 751.130Smgorny#include <gelf.h> 761.130Smgorny 771.1Skamil#include <atf-c.h> 781.1Skamil 791.165Skamil#ifdef ENABLE_TESTS 801.165Skamil 811.132Skamil/* Assumptions in the kernel code that must be kept. */ 821.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_report_event) == 831.132Skamil sizeof(((siginfo_t *)0)->si_pe_report_event), 841.132Skamil "pe_report_event and si_pe_report_event must be of the same size"); 851.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 861.132Skamil sizeof(((siginfo_t *)0)->si_pe_other_pid), 871.132Skamil "pe_other_pid and si_pe_other_pid must be of the same size"); 881.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_lwp) == 891.132Skamil sizeof(((siginfo_t *)0)->si_pe_lwp), 901.132Skamil "pe_lwp and si_pe_lwp must be of the same size"); 911.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 921.132Skamil sizeof(((struct ptrace_state *)0)->pe_lwp), 931.132Skamil "pe_other_pid and pe_lwp must be of the same size"); 941.132Skamil 951.1Skamil#include "h_macros.h" 961.1Skamil 971.1Skamil#include "t_ptrace_wait.h" 981.1Skamil#include "msg.h" 991.1Skamil 1001.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 1011.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 1021.61Skre sizeof(msg)) == 0) 1031.1Skamil 1041.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 1051.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 1061.61Skre sizeof(msg)) == 0) 1071.1Skamil 1081.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 1091.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 1101.61Skre sizeof(msg)) == 0) 1111.1Skamil 1121.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 1131.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 1141.61Skre sizeof(msg)) == 0) 1151.13Schristos 1161.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 1171.13Schristos strerror(errno)) 1181.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 1191.18Schristos "%d(%s) != %d", res, strerror(res), exp) 1201.13Schristos 1211.152Skamilstatic int debug = 0; 1221.13Schristos 1231.13Schristos#define DPRINTF(a, ...) do \ 1241.123Skamil if (debug) \ 1251.142Skamil printf("%s() %d.%d %s:%d " a, \ 1261.142Skamil __func__, getpid(), _lwp_self(), __FILE__, __LINE__, ##__VA_ARGS__); \ 1271.13Schristos while (/*CONSTCOND*/0) 1281.1Skamil 1291.34Skamil/// ---------------------------------------------------------------------------- 1301.34Skamil 1311.33Skamilstatic void 1321.33Skamiltraceme_raise(int sigval) 1331.1Skamil{ 1341.1Skamil const int exitval = 5; 1351.1Skamil pid_t child, wpid; 1361.1Skamil#if defined(TWAIT_HAVE_STATUS) 1371.1Skamil int status; 1381.1Skamil#endif 1391.1Skamil 1401.133Skamil ptrace_state_t state, zero_state; 1411.133Skamil const int slen = sizeof(state); 1421.45Skamil struct ptrace_siginfo info; 1431.133Skamil memset(&zero_state, 0, sizeof(zero_state)); 1441.45Skamil memset(&info, 0, sizeof(info)); 1451.45Skamil 1461.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1471.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1481.1Skamil if (child == 0) { 1491.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1501.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1511.1Skamil 1521.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1531.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1541.1Skamil 1551.36Skamil switch (sigval) { 1561.36Skamil case SIGKILL: 1571.36Skamil /* NOTREACHED */ 1581.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1591.70Smrg __unreachable(); 1601.36Skamil default: 1611.36Skamil DPRINTF("Before exiting of the child process\n"); 1621.36Skamil _exit(exitval); 1631.36Skamil } 1641.1Skamil } 1651.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1661.1Skamil 1671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1691.1Skamil 1701.36Skamil switch (sigval) { 1711.36Skamil case SIGKILL: 1721.36Skamil validate_status_signaled(status, sigval, 0); 1731.133Skamil SYSCALL_REQUIRE( 1741.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) == -1); 1751.133Skamil 1761.36Skamil break; 1771.36Skamil default: 1781.36Skamil validate_status_stopped(status, sigval); 1791.1Skamil 1801.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1811.61Skre "child\n"); 1821.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1831.61Skre sizeof(info)) != -1); 1841.45Skamil 1851.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1861.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1871.61Skre "si_errno=%#x\n", 1881.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1891.61Skre info.psi_siginfo.si_errno); 1901.45Skamil 1911.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1921.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1931.45Skamil 1941.133Skamil DPRINTF("Assert that PT_GET_PROCESS_STATE returns non-error"); 1951.133Skamil SYSCALL_REQUIRE( 1961.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 1971.133Skamil ATF_REQUIRE(memcmp(&state, &zero_state, slen) == 0); 1981.133Skamil 1991.36Skamil DPRINTF("Before resuming the child process where it left off " 2001.36Skamil "and without signal to be sent\n"); 2011.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2021.1Skamil 2031.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2041.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 2051.61Skre child); 2061.36Skamil break; 2071.36Skamil } 2081.1Skamil 2091.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2101.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2111.1Skamil} 2121.1Skamil 2131.61Skre#define TRACEME_RAISE(test, sig) \ 2141.61SkreATF_TC(test); \ 2151.61SkreATF_TC_HEAD(test, tc) \ 2161.61Skre{ \ 2171.61Skre atf_tc_set_md_var(tc, "descr", \ 2181.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 2191.61Skre} \ 2201.61Skre \ 2211.61SkreATF_TC_BODY(test, tc) \ 2221.61Skre{ \ 2231.61Skre \ 2241.61Skre traceme_raise(sig); \ 2251.33Skamil} 2261.33Skamil 2271.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2281.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2291.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2301.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2311.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2321.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2331.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2341.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2351.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2361.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2371.33Skamil 2381.34Skamil/// ---------------------------------------------------------------------------- 2391.1Skamil 2401.1Skamilstatic void 2411.87Skamiltraceme_raisesignal_ignored(int sigignored) 2421.87Skamil{ 2431.87Skamil const int exitval = 5; 2441.87Skamil const int sigval = SIGSTOP; 2451.87Skamil pid_t child, wpid; 2461.87Skamil struct sigaction sa; 2471.87Skamil#if defined(TWAIT_HAVE_STATUS) 2481.87Skamil int status; 2491.87Skamil#endif 2501.87Skamil struct ptrace_siginfo info; 2511.87Skamil 2521.87Skamil memset(&info, 0, sizeof(info)); 2531.87Skamil 2541.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2551.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2561.87Skamil if (child == 0) { 2571.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2581.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2591.87Skamil 2601.87Skamil memset(&sa, 0, sizeof(sa)); 2611.87Skamil sa.sa_handler = SIG_IGN; 2621.87Skamil sigemptyset(&sa.sa_mask); 2631.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2641.87Skamil 2651.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2661.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2671.87Skamil 2681.87Skamil DPRINTF("Before raising %s from child\n", 2691.87Skamil strsignal(sigignored)); 2701.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2711.87Skamil 2721.87Skamil DPRINTF("Before exiting of the child process\n"); 2731.87Skamil _exit(exitval); 2741.87Skamil } 2751.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2761.87Skamil 2771.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2781.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2791.87Skamil 2801.87Skamil validate_status_stopped(status, sigval); 2811.87Skamil 2821.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2831.87Skamil SYSCALL_REQUIRE( 2841.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2851.87Skamil 2861.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2871.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2881.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2891.87Skamil info.psi_siginfo.si_errno); 2901.87Skamil 2911.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2921.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2931.87Skamil 2941.87Skamil DPRINTF("Before resuming the child process where it left off and " 2951.87Skamil "without signal to be sent\n"); 2961.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2971.87Skamil 2981.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2991.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3001.87Skamil 3011.87Skamil validate_status_stopped(status, sigignored); 3021.87Skamil 3031.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3041.87Skamil SYSCALL_REQUIRE( 3051.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3061.87Skamil 3071.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3081.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3091.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3101.87Skamil info.psi_siginfo.si_errno); 3111.87Skamil 3121.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 3131.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3141.87Skamil 3151.87Skamil DPRINTF("Before resuming the child process where it left off and " 3161.87Skamil "without signal to be sent\n"); 3171.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3181.87Skamil 3191.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3201.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3211.87Skamil 3221.87Skamil validate_status_exited(status, exitval); 3231.87Skamil 3241.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3251.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3261.87Skamil} 3271.87Skamil 3281.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3291.87SkamilATF_TC(test); \ 3301.87SkamilATF_TC_HEAD(test, tc) \ 3311.87Skamil{ \ 3321.87Skamil atf_tc_set_md_var(tc, "descr", \ 3331.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3341.87Skamil "does not stop tracer from catching this raised signal"); \ 3351.87Skamil} \ 3361.87Skamil \ 3371.87SkamilATF_TC_BODY(test, tc) \ 3381.87Skamil{ \ 3391.87Skamil \ 3401.87Skamil traceme_raisesignal_ignored(sig); \ 3411.87Skamil} 3421.87Skamil 3431.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3441.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3451.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3461.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3471.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3481.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3491.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3501.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3511.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3521.87Skamil 3531.87Skamil/// ---------------------------------------------------------------------------- 3541.87Skamil 3551.87Skamilstatic void 3561.86Skamiltraceme_raisesignal_masked(int sigmasked) 3571.86Skamil{ 3581.86Skamil const int exitval = 5; 3591.86Skamil const int sigval = SIGSTOP; 3601.86Skamil pid_t child, wpid; 3611.86Skamil#if defined(TWAIT_HAVE_STATUS) 3621.86Skamil int status; 3631.86Skamil#endif 3641.86Skamil sigset_t intmask; 3651.86Skamil struct ptrace_siginfo info; 3661.86Skamil 3671.86Skamil memset(&info, 0, sizeof(info)); 3681.86Skamil 3691.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3701.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3711.86Skamil if (child == 0) { 3721.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3731.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3741.86Skamil 3751.86Skamil sigemptyset(&intmask); 3761.86Skamil sigaddset(&intmask, sigmasked); 3771.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3781.86Skamil 3791.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3801.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3811.86Skamil 3821.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3831.86Skamil strsignal(sigmasked)); 3841.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3851.86Skamil 3861.86Skamil DPRINTF("Before exiting of the child process\n"); 3871.86Skamil _exit(exitval); 3881.86Skamil } 3891.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3901.86Skamil 3911.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3921.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3931.86Skamil 3941.86Skamil validate_status_stopped(status, sigval); 3951.86Skamil 3961.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3971.86Skamil SYSCALL_REQUIRE( 3981.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3991.86Skamil 4001.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4011.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4021.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4031.86Skamil info.psi_siginfo.si_errno); 4041.86Skamil 4051.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 4061.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 4071.86Skamil 4081.86Skamil DPRINTF("Before resuming the child process where it left off and " 4091.86Skamil "without signal to be sent\n"); 4101.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 4111.86Skamil 4121.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4131.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4141.86Skamil 4151.86Skamil validate_status_exited(status, exitval); 4161.86Skamil 4171.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4181.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 4191.86Skamil} 4201.86Skamil 4211.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 4221.86SkamilATF_TC(test); \ 4231.86SkamilATF_TC_HEAD(test, tc) \ 4241.86Skamil{ \ 4251.86Skamil atf_tc_set_md_var(tc, "descr", \ 4261.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4271.86Skamil "stops tracer from catching this raised signal"); \ 4281.86Skamil} \ 4291.86Skamil \ 4301.86SkamilATF_TC_BODY(test, tc) \ 4311.86Skamil{ \ 4321.86Skamil \ 4331.86Skamil traceme_raisesignal_masked(sig); \ 4341.86Skamil} 4351.86Skamil 4361.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4371.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4381.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4391.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4401.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4411.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4421.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4431.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4441.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4451.86Skamil 4461.86Skamil/// ---------------------------------------------------------------------------- 4471.86Skamil 4481.86Skamilstatic void 4491.59Skamiltraceme_crash(int sig) 4501.59Skamil{ 4511.59Skamil pid_t child, wpid; 4521.59Skamil#if defined(TWAIT_HAVE_STATUS) 4531.59Skamil int status; 4541.59Skamil#endif 4551.59Skamil struct ptrace_siginfo info; 4561.61Skre 4571.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4581.71Skamil if (sig == SIGILL) 4591.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4601.71Skamil#endif 4611.71Skamil 4621.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4631.114Skamil atf_tc_skip("FP exceptions are not supported"); 4641.114Skamil 4651.59Skamil memset(&info, 0, sizeof(info)); 4661.59Skamil 4671.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4681.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4691.59Skamil if (child == 0) { 4701.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4711.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4721.59Skamil 4731.59Skamil DPRINTF("Before executing a trap\n"); 4741.59Skamil switch (sig) { 4751.59Skamil case SIGTRAP: 4761.59Skamil trigger_trap(); 4771.59Skamil break; 4781.59Skamil case SIGSEGV: 4791.59Skamil trigger_segv(); 4801.59Skamil break; 4811.59Skamil case SIGILL: 4821.59Skamil trigger_ill(); 4831.59Skamil break; 4841.59Skamil case SIGFPE: 4851.59Skamil trigger_fpe(); 4861.59Skamil break; 4871.59Skamil case SIGBUS: 4881.59Skamil trigger_bus(); 4891.59Skamil break; 4901.59Skamil default: 4911.59Skamil /* NOTREACHED */ 4921.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4931.59Skamil } 4941.59Skamil 4951.59Skamil /* NOTREACHED */ 4961.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4971.59Skamil } 4981.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4991.59Skamil 5001.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5011.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5021.59Skamil 5031.59Skamil validate_status_stopped(status, sig); 5041.59Skamil 5051.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 5061.61Skre SYSCALL_REQUIRE( 5071.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 5081.59Skamil 5091.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 5101.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 5111.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 5121.61Skre info.psi_siginfo.si_errno); 5131.59Skamil 5141.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 5151.59Skamil switch (sig) { 5161.59Skamil case SIGTRAP: 5171.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 5181.59Skamil break; 5191.59Skamil case SIGSEGV: 5201.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 5211.59Skamil break; 5221.71Skamil case SIGILL: 5231.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 5241.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5251.71Skamil break; 5261.59Skamil case SIGFPE: 5271.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5281.59Skamil break; 5291.59Skamil case SIGBUS: 5301.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5311.59Skamil break; 5321.59Skamil } 5331.59Skamil 5341.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5351.59Skamil 5361.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5371.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5381.59Skamil 5391.59Skamil validate_status_signaled(status, SIGKILL, 0); 5401.59Skamil 5411.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5421.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5431.59Skamil} 5441.59Skamil 5451.61Skre#define TRACEME_CRASH(test, sig) \ 5461.61SkreATF_TC(test); \ 5471.61SkreATF_TC_HEAD(test, tc) \ 5481.61Skre{ \ 5491.61Skre atf_tc_set_md_var(tc, "descr", \ 5501.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5511.61Skre} \ 5521.61Skre \ 5531.61SkreATF_TC_BODY(test, tc) \ 5541.61Skre{ \ 5551.61Skre \ 5561.61Skre traceme_crash(sig); \ 5571.59Skamil} 5581.59Skamil 5591.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5601.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5611.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5621.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5631.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5641.59Skamil 5651.59Skamil/// ---------------------------------------------------------------------------- 5661.59Skamil 5671.59Skamilstatic void 5681.88Skamiltraceme_signalmasked_crash(int sig) 5691.88Skamil{ 5701.89Skamil const int sigval = SIGSTOP; 5711.88Skamil pid_t child, wpid; 5721.88Skamil#if defined(TWAIT_HAVE_STATUS) 5731.88Skamil int status; 5741.88Skamil#endif 5751.88Skamil struct ptrace_siginfo info; 5761.88Skamil sigset_t intmask; 5771.89Skamil struct kinfo_proc2 kp; 5781.89Skamil size_t len = sizeof(kp); 5791.89Skamil 5801.89Skamil int name[6]; 5811.89Skamil const size_t namelen = __arraycount(name); 5821.89Skamil ki_sigset_t kp_sigmask; 5831.88Skamil 5841.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5851.88Skamil if (sig == SIGILL) 5861.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5871.88Skamil#endif 5881.88Skamil 5891.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5901.114Skamil atf_tc_skip("FP exceptions are not supported"); 5911.114Skamil 5921.88Skamil memset(&info, 0, sizeof(info)); 5931.88Skamil 5941.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5951.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5961.88Skamil if (child == 0) { 5971.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5981.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5991.88Skamil 6001.88Skamil sigemptyset(&intmask); 6011.88Skamil sigaddset(&intmask, sig); 6021.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 6031.88Skamil 6041.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 6051.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 6061.89Skamil 6071.88Skamil DPRINTF("Before executing a trap\n"); 6081.88Skamil switch (sig) { 6091.88Skamil case SIGTRAP: 6101.88Skamil trigger_trap(); 6111.88Skamil break; 6121.88Skamil case SIGSEGV: 6131.88Skamil trigger_segv(); 6141.88Skamil break; 6151.88Skamil case SIGILL: 6161.88Skamil trigger_ill(); 6171.88Skamil break; 6181.88Skamil case SIGFPE: 6191.88Skamil trigger_fpe(); 6201.88Skamil break; 6211.88Skamil case SIGBUS: 6221.88Skamil trigger_bus(); 6231.88Skamil break; 6241.88Skamil default: 6251.88Skamil /* NOTREACHED */ 6261.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6271.88Skamil } 6281.88Skamil 6291.88Skamil /* NOTREACHED */ 6301.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6311.88Skamil } 6321.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6331.88Skamil 6341.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6351.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6361.88Skamil 6371.89Skamil validate_status_stopped(status, sigval); 6381.89Skamil 6391.89Skamil name[0] = CTL_KERN, 6401.89Skamil name[1] = KERN_PROC2, 6411.89Skamil name[2] = KERN_PROC_PID; 6421.89Skamil name[3] = child; 6431.89Skamil name[4] = sizeof(kp); 6441.89Skamil name[5] = 1; 6451.89Skamil 6461.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6471.89Skamil 6481.89Skamil kp_sigmask = kp.p_sigmask; 6491.89Skamil 6501.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6511.89Skamil SYSCALL_REQUIRE( 6521.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6531.89Skamil 6541.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6551.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6561.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6571.89Skamil info.psi_siginfo.si_errno); 6581.89Skamil 6591.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6601.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6611.89Skamil 6621.89Skamil DPRINTF("Before resuming the child process where it left off and " 6631.89Skamil "without signal to be sent\n"); 6641.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6651.89Skamil 6661.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6671.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6681.89Skamil 6691.88Skamil validate_status_stopped(status, sig); 6701.88Skamil 6711.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6721.88Skamil SYSCALL_REQUIRE( 6731.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6741.88Skamil 6751.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6761.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6771.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6781.88Skamil info.psi_siginfo.si_errno); 6791.88Skamil 6801.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6811.89Skamil 6821.89Skamil DPRINTF("kp_sigmask=" 6831.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6841.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6851.89Skamil kp_sigmask.__bits[3]); 6861.89Skamil 6871.89Skamil DPRINTF("kp.p_sigmask=" 6881.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6891.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6901.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6911.89Skamil 6921.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6931.89Skamil 6941.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6951.88Skamil switch (sig) { 6961.88Skamil case SIGTRAP: 6971.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6981.88Skamil break; 6991.88Skamil case SIGSEGV: 7001.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 7011.88Skamil break; 7021.88Skamil case SIGILL: 7031.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 7041.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 7051.88Skamil break; 7061.88Skamil case SIGFPE: 7071.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 7081.88Skamil break; 7091.88Skamil case SIGBUS: 7101.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 7111.88Skamil break; 7121.88Skamil } 7131.88Skamil 7141.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 7151.88Skamil 7161.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7171.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7181.88Skamil 7191.88Skamil validate_status_signaled(status, SIGKILL, 0); 7201.88Skamil 7211.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7221.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 7231.88Skamil} 7241.88Skamil 7251.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7261.88SkamilATF_TC(test); \ 7271.88SkamilATF_TC_HEAD(test, tc) \ 7281.88Skamil{ \ 7291.88Skamil atf_tc_set_md_var(tc, "descr", \ 7301.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7311.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7321.88Skamil} \ 7331.88Skamil \ 7341.88SkamilATF_TC_BODY(test, tc) \ 7351.88Skamil{ \ 7361.88Skamil \ 7371.88Skamil traceme_signalmasked_crash(sig); \ 7381.88Skamil} 7391.88Skamil 7401.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7411.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7421.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7431.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7441.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7451.88Skamil 7461.88Skamil/// ---------------------------------------------------------------------------- 7471.88Skamil 7481.88Skamilstatic void 7491.88Skamiltraceme_signalignored_crash(int sig) 7501.88Skamil{ 7511.90Skamil const int sigval = SIGSTOP; 7521.88Skamil pid_t child, wpid; 7531.88Skamil#if defined(TWAIT_HAVE_STATUS) 7541.88Skamil int status; 7551.88Skamil#endif 7561.88Skamil struct sigaction sa; 7571.88Skamil struct ptrace_siginfo info; 7581.90Skamil struct kinfo_proc2 kp; 7591.90Skamil size_t len = sizeof(kp); 7601.90Skamil 7611.90Skamil int name[6]; 7621.90Skamil const size_t namelen = __arraycount(name); 7631.90Skamil ki_sigset_t kp_sigignore; 7641.88Skamil 7651.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7661.88Skamil if (sig == SIGILL) 7671.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7681.88Skamil#endif 7691.88Skamil 7701.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7711.114Skamil atf_tc_skip("FP exceptions are not supported"); 7721.114Skamil 7731.88Skamil memset(&info, 0, sizeof(info)); 7741.88Skamil 7751.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7761.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7771.88Skamil if (child == 0) { 7781.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7791.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7801.88Skamil 7811.88Skamil memset(&sa, 0, sizeof(sa)); 7821.88Skamil sa.sa_handler = SIG_IGN; 7831.88Skamil sigemptyset(&sa.sa_mask); 7841.88Skamil 7851.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7861.88Skamil 7871.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7881.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7891.90Skamil 7901.88Skamil DPRINTF("Before executing a trap\n"); 7911.88Skamil switch (sig) { 7921.88Skamil case SIGTRAP: 7931.88Skamil trigger_trap(); 7941.88Skamil break; 7951.88Skamil case SIGSEGV: 7961.88Skamil trigger_segv(); 7971.88Skamil break; 7981.88Skamil case SIGILL: 7991.88Skamil trigger_ill(); 8001.88Skamil break; 8011.88Skamil case SIGFPE: 8021.88Skamil trigger_fpe(); 8031.88Skamil break; 8041.88Skamil case SIGBUS: 8051.88Skamil trigger_bus(); 8061.88Skamil break; 8071.88Skamil default: 8081.88Skamil /* NOTREACHED */ 8091.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8101.88Skamil } 8111.88Skamil 8121.88Skamil /* NOTREACHED */ 8131.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8141.88Skamil } 8151.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 8161.88Skamil 8171.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8181.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8191.88Skamil 8201.90Skamil validate_status_stopped(status, sigval); 8211.90Skamil 8221.90Skamil name[0] = CTL_KERN, 8231.90Skamil name[1] = KERN_PROC2, 8241.90Skamil name[2] = KERN_PROC_PID; 8251.90Skamil name[3] = child; 8261.90Skamil name[4] = sizeof(kp); 8271.90Skamil name[5] = 1; 8281.90Skamil 8291.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8301.90Skamil 8311.90Skamil kp_sigignore = kp.p_sigignore; 8321.90Skamil 8331.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8341.90Skamil SYSCALL_REQUIRE( 8351.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8361.90Skamil 8371.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8381.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8391.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8401.90Skamil info.psi_siginfo.si_errno); 8411.90Skamil 8421.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8431.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8441.90Skamil 8451.90Skamil DPRINTF("Before resuming the child process where it left off and " 8461.90Skamil "without signal to be sent\n"); 8471.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8481.90Skamil 8491.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8501.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8511.90Skamil 8521.88Skamil validate_status_stopped(status, sig); 8531.88Skamil 8541.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8551.88Skamil SYSCALL_REQUIRE( 8561.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8571.88Skamil 8581.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8591.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8601.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8611.88Skamil info.psi_siginfo.si_errno); 8621.88Skamil 8631.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8641.90Skamil 8651.90Skamil DPRINTF("kp_sigignore=" 8661.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8671.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8681.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8691.90Skamil 8701.90Skamil DPRINTF("kp.p_sigignore=" 8711.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8721.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8731.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8741.90Skamil 8751.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8761.90Skamil 8771.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8781.88Skamil switch (sig) { 8791.88Skamil case SIGTRAP: 8801.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8811.88Skamil break; 8821.88Skamil case SIGSEGV: 8831.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8841.88Skamil break; 8851.88Skamil case SIGILL: 8861.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8871.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8881.88Skamil break; 8891.88Skamil case SIGFPE: 8901.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8911.88Skamil break; 8921.88Skamil case SIGBUS: 8931.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8941.88Skamil break; 8951.88Skamil } 8961.88Skamil 8971.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8981.88Skamil 8991.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9001.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9011.88Skamil 9021.88Skamil validate_status_signaled(status, SIGKILL, 0); 9031.88Skamil 9041.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9051.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9061.88Skamil} 9071.88Skamil 9081.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 9091.88SkamilATF_TC(test); \ 9101.88SkamilATF_TC_HEAD(test, tc) \ 9111.88Skamil{ \ 9121.88Skamil atf_tc_set_md_var(tc, "descr", \ 9131.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 9141.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 9151.88Skamil} \ 9161.88Skamil \ 9171.88SkamilATF_TC_BODY(test, tc) \ 9181.88Skamil{ \ 9191.88Skamil \ 9201.88Skamil traceme_signalignored_crash(sig); \ 9211.88Skamil} 9221.88Skamil 9231.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 9241.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9251.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9261.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9271.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9281.88Skamil 9291.88Skamil/// ---------------------------------------------------------------------------- 9301.88Skamil 9311.88Skamilstatic void 9321.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9331.1Skamil{ 9341.1Skamil const int exitval = 5; 9351.34Skamil const int sigval = SIGSTOP; 9361.1Skamil pid_t child, wpid; 9371.1Skamil struct sigaction sa; 9381.1Skamil#if defined(TWAIT_HAVE_STATUS) 9391.1Skamil int status; 9401.1Skamil#endif 9411.61Skre struct ptrace_siginfo info; 9421.1Skamil 9431.45Skamil memset(&info, 0, sizeof(info)); 9441.45Skamil 9451.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9461.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9471.1Skamil if (child == 0) { 9481.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9491.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9501.1Skamil 9511.34Skamil sa.sa_handler = sah; 9521.1Skamil sa.sa_flags = SA_SIGINFO; 9531.1Skamil sigemptyset(&sa.sa_mask); 9541.1Skamil 9551.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9561.1Skamil 9571.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9581.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9591.1Skamil 9601.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9611.1Skamil 9621.13Schristos DPRINTF("Before exiting of the child process\n"); 9631.1Skamil _exit(exitval); 9641.1Skamil } 9651.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9661.1Skamil 9671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9691.1Skamil 9701.1Skamil validate_status_stopped(status, sigval); 9711.1Skamil 9721.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9731.61Skre SYSCALL_REQUIRE( 9741.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9751.45Skamil 9761.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9771.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9781.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9791.45Skamil info.psi_siginfo.si_errno); 9801.45Skamil 9811.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9821.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9831.45Skamil 9841.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9851.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9861.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9871.1Skamil 9881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9901.1Skamil 9911.1Skamil validate_status_exited(status, exitval); 9921.1Skamil 9931.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9941.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9951.1Skamil} 9961.1Skamil 9971.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9981.61SkreATF_TC(test); \ 9991.61SkreATF_TC_HEAD(test, tc) \ 10001.61Skre{ \ 10011.61Skre atf_tc_set_md_var(tc, "descr", \ 10021.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10031.61Skre "handled correctly and caught by a signal handler"); \ 10041.61Skre} \ 10051.61Skre \ 10061.61Skrestatic int test##_caught = 0; \ 10071.61Skre \ 10081.61Skrestatic void \ 10091.61Skretest##_sighandler(int arg) \ 10101.61Skre{ \ 10111.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 10121.61Skre \ 10131.61Skre ++ test##_caught; \ 10141.61Skre} \ 10151.61Skre \ 10161.61SkreATF_TC_BODY(test, tc) \ 10171.61Skre{ \ 10181.61Skre \ 10191.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 10201.34Skamil} 10211.34Skamil 10221.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 10231.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 10241.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10251.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10261.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10271.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10281.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10291.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10301.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10311.34Skamil 10321.34Skamil/// ---------------------------------------------------------------------------- 10331.34Skamil 10341.35Skamilstatic void 10351.50Skamiltraceme_sendsignal_masked(int sigsent) 10361.50Skamil{ 10371.50Skamil const int exitval = 5; 10381.50Skamil const int sigval = SIGSTOP; 10391.50Skamil pid_t child, wpid; 10401.50Skamil sigset_t set; 10411.50Skamil#if defined(TWAIT_HAVE_STATUS) 10421.50Skamil int status; 10431.50Skamil#endif 10441.61Skre struct ptrace_siginfo info; 10451.50Skamil 10461.50Skamil memset(&info, 0, sizeof(info)); 10471.50Skamil 10481.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10491.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10501.50Skamil if (child == 0) { 10511.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10521.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10531.50Skamil 10541.50Skamil sigemptyset(&set); 10551.50Skamil sigaddset(&set, sigsent); 10561.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10571.50Skamil 10581.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10591.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10601.50Skamil 10611.50Skamil _exit(exitval); 10621.50Skamil } 10631.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10641.50Skamil 10651.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10661.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10671.50Skamil 10681.50Skamil validate_status_stopped(status, sigval); 10691.50Skamil 10701.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10711.61Skre SYSCALL_REQUIRE( 10721.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10731.50Skamil 10741.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10751.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10761.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10771.50Skamil info.psi_siginfo.si_errno); 10781.50Skamil 10791.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10801.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10811.50Skamil 10821.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10831.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10841.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10851.50Skamil 10861.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10871.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10881.50Skamil 10891.50Skamil validate_status_exited(status, exitval); 10901.50Skamil 10911.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10921.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10931.50Skamil} 10941.50Skamil 10951.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10961.61SkreATF_TC(test); \ 10971.61SkreATF_TC_HEAD(test, tc) \ 10981.61Skre{ \ 10991.61Skre atf_tc_set_md_var(tc, "descr", \ 11001.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11011.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 11021.61Skre} \ 11031.61Skre \ 11041.61SkreATF_TC_BODY(test, tc) \ 11051.61Skre{ \ 11061.61Skre \ 11071.61Skre traceme_sendsignal_masked(sig); \ 11081.50Skamil} 11091.50Skamil 11101.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 11111.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 11121.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 11131.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 11141.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 11151.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 11161.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 11171.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 11181.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 11191.50Skamil 11201.50Skamil/// ---------------------------------------------------------------------------- 11211.50Skamil 11221.50Skamilstatic void 11231.50Skamiltraceme_sendsignal_ignored(int sigsent) 11241.50Skamil{ 11251.50Skamil const int exitval = 5; 11261.50Skamil const int sigval = SIGSTOP; 11271.50Skamil pid_t child, wpid; 11281.50Skamil struct sigaction sa; 11291.50Skamil#if defined(TWAIT_HAVE_STATUS) 11301.50Skamil int status; 11311.50Skamil#endif 11321.61Skre struct ptrace_siginfo info; 11331.50Skamil 11341.50Skamil memset(&info, 0, sizeof(info)); 11351.50Skamil 11361.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11371.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11381.50Skamil if (child == 0) { 11391.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11401.61Skre 11411.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11421.50Skamil 11431.50Skamil memset(&sa, 0, sizeof(sa)); 11441.50Skamil sa.sa_handler = SIG_IGN; 11451.50Skamil sigemptyset(&sa.sa_mask); 11461.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11471.50Skamil 11481.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11491.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11501.50Skamil 11511.50Skamil _exit(exitval); 11521.50Skamil } 11531.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11541.50Skamil 11551.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11561.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11571.50Skamil 11581.50Skamil validate_status_stopped(status, sigval); 11591.50Skamil 11601.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11611.61Skre SYSCALL_REQUIRE( 11621.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11631.50Skamil 11641.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11651.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11661.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11671.50Skamil info.psi_siginfo.si_errno); 11681.50Skamil 11691.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11701.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11711.50Skamil 11721.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11731.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11741.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11751.50Skamil 11761.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11771.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11781.50Skamil 11791.50Skamil validate_status_exited(status, exitval); 11801.50Skamil 11811.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11821.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11831.50Skamil} 11841.50Skamil 11851.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11861.61SkreATF_TC(test); \ 11871.61SkreATF_TC_HEAD(test, tc) \ 11881.61Skre{ \ 11891.61Skre atf_tc_set_md_var(tc, "descr", \ 11901.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11911.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11921.61Skre} \ 11931.61Skre \ 11941.61SkreATF_TC_BODY(test, tc) \ 11951.61Skre{ \ 11961.61Skre \ 11971.61Skre traceme_sendsignal_ignored(sig); \ 11981.50Skamil} 11991.50Skamil 12001.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 12011.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 12021.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 12031.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 12041.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 12051.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 12061.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 12071.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 12081.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 12091.50Skamil 12101.50Skamil/// ---------------------------------------------------------------------------- 12111.50Skamil 12121.50Skamilstatic void 12131.50Skamiltraceme_sendsignal_simple(int sigsent) 12141.1Skamil{ 12151.35Skamil const int sigval = SIGSTOP; 12161.35Skamil int exitval = 0; 12171.1Skamil pid_t child, wpid; 12181.1Skamil#if defined(TWAIT_HAVE_STATUS) 12191.1Skamil int status; 12201.85Skamil int expect_core; 12211.85Skamil 12221.85Skamil switch (sigsent) { 12231.85Skamil case SIGABRT: 12241.85Skamil case SIGTRAP: 12251.85Skamil case SIGBUS: 12261.85Skamil case SIGILL: 12271.85Skamil case SIGFPE: 12281.85Skamil case SIGSEGV: 12291.85Skamil expect_core = 1; 12301.85Skamil break; 12311.85Skamil default: 12321.85Skamil expect_core = 0; 12331.85Skamil break; 12341.85Skamil } 12351.1Skamil#endif 12361.61Skre struct ptrace_siginfo info; 12371.1Skamil 12381.45Skamil memset(&info, 0, sizeof(info)); 12391.45Skamil 12401.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12411.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12421.1Skamil if (child == 0) { 12431.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12441.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12451.1Skamil 12461.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12471.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12481.1Skamil 12491.35Skamil switch (sigsent) { 12501.35Skamil case SIGCONT: 12511.48Skamil case SIGSTOP: 12521.35Skamil _exit(exitval); 12531.35Skamil default: 12541.35Skamil /* NOTREACHED */ 12551.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12561.35Skamil } 12571.1Skamil } 12581.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 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_stopped(status, sigval); 12641.1Skamil 12651.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12661.61Skre SYSCALL_REQUIRE( 12671.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12681.45Skamil 12691.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12701.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12711.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12721.45Skamil info.psi_siginfo.si_errno); 12731.45Skamil 12741.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12751.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12761.45Skamil 12771.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12781.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12791.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12801.1Skamil 12811.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12821.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12831.1Skamil 12841.35Skamil switch (sigsent) { 12851.48Skamil case SIGSTOP: 12861.48Skamil validate_status_stopped(status, sigsent); 12871.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12881.61Skre "child\n"); 12891.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12901.61Skre sizeof(info)) != -1); 12911.48Skamil 12921.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12931.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12941.61Skre "si_errno=%#x\n", 12951.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12961.61Skre info.psi_siginfo.si_errno); 12971.48Skamil 12981.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12991.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 13001.48Skamil 13011.48Skamil DPRINTF("Before resuming the child process where it left off " 13021.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 13031.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 13041.48Skamil 13051.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13061.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 13071.61Skre child); 13081.48Skamil /* FALLTHROUGH */ 13091.35Skamil case SIGCONT: 13101.35Skamil validate_status_exited(status, exitval); 13111.35Skamil break; 13121.35Skamil default: 13131.35Skamil validate_status_signaled(status, sigsent, expect_core); 13141.35Skamil break; 13151.35Skamil } 13161.1Skamil 13171.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 13181.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 13191.1Skamil} 13201.1Skamil 13211.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 13221.61SkreATF_TC(test); \ 13231.61SkreATF_TC_HEAD(test, tc) \ 13241.61Skre{ \ 13251.61Skre atf_tc_set_md_var(tc, "descr", \ 13261.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13271.61Skre "handled correctly in a child without a signal handler"); \ 13281.61Skre} \ 13291.61Skre \ 13301.61SkreATF_TC_BODY(test, tc) \ 13311.61Skre{ \ 13321.61Skre \ 13331.61Skre traceme_sendsignal_simple(sig); \ 13341.35Skamil} 13351.35Skamil 13361.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13371.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13381.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13391.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13401.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13411.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13421.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13431.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13441.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13451.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13461.35Skamil 13471.35Skamil/// ---------------------------------------------------------------------------- 13481.35Skamil 13491.37SkamilATF_TC(traceme_pid1_parent); 13501.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13511.37Skamil{ 13521.37Skamil atf_tc_set_md_var(tc, "descr", 13531.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13541.37Skamil} 13551.37Skamil 13561.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13571.37Skamil{ 13581.37Skamil struct msg_fds parent_child; 13591.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13601.37Skamil pid_t child1, child2, wpid; 13611.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13621.37Skamil#if defined(TWAIT_HAVE_STATUS) 13631.37Skamil int status; 13641.37Skamil#endif 13651.37Skamil 13661.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13671.37Skamil 13681.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13691.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13701.37Skamil if (child1 == 0) { 13711.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13721.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13731.37Skamil if (child2 != 0) { 13741.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13751.61Skre getpid(), child2); 13761.37Skamil _exit(exitval_child1); 13771.37Skamil } 13781.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13791.37Skamil 13801.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13811.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13821.37Skamil 13831.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13841.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13851.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13861.37Skamil 13871.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13881.37Skamil 13891.37Skamil _exit(exitval_child2); 13901.37Skamil } 13911.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13921.37Skamil 13931.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13941.61Skre TWAIT_REQUIRE_SUCCESS( 13951.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13961.37Skamil 13971.37Skamil validate_status_exited(status, exitval_child1); 13981.37Skamil 13991.37Skamil DPRINTF("Notify that child1 is dead\n"); 14001.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 14011.37Skamil 14021.37Skamil DPRINTF("Wait for exiting of child2\n"); 14031.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 14041.37Skamil} 14051.37Skamil 14061.37Skamil/// ---------------------------------------------------------------------------- 14071.37Skamil 14081.40Skamilstatic void 14091.40Skamiltraceme_vfork_raise(int sigval) 14101.40Skamil{ 14111.46Skamil const int exitval = 5, exitval_watcher = 10; 14121.46Skamil pid_t child, parent, watcher, wpid; 14131.46Skamil int rv; 14141.40Skamil#if defined(TWAIT_HAVE_STATUS) 14151.40Skamil int status; 14161.85Skamil 14171.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 14181.85Skamil volatile int expect_core; 14191.85Skamil 14201.85Skamil switch (sigval) { 14211.85Skamil case SIGABRT: 14221.85Skamil case SIGTRAP: 14231.85Skamil case SIGBUS: 14241.85Skamil case SIGILL: 14251.85Skamil case SIGFPE: 14261.85Skamil case SIGSEGV: 14271.85Skamil expect_core = 1; 14281.85Skamil break; 14291.85Skamil default: 14301.85Skamil expect_core = 0; 14311.85Skamil break; 14321.85Skamil } 14331.40Skamil#endif 14341.40Skamil 14351.46Skamil /* 14361.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14371.46Skamil * the SIGKILL signal to it. 14381.46Skamil * 14391.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14401.46Skamil * simpler to reparent this process to initproc and forget about it. 14411.46Skamil */ 14421.46Skamil if (sigval == SIGSTOP) { 14431.46Skamil parent = getpid(); 14441.46Skamil 14451.46Skamil watcher = fork(); 14461.46Skamil ATF_REQUIRE(watcher != 1); 14471.46Skamil if (watcher == 0) { 14481.46Skamil /* Double fork(2) trick to reparent to initproc */ 14491.46Skamil watcher = fork(); 14501.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14511.46Skamil if (watcher != 0) 14521.46Skamil _exit(exitval_watcher); 14531.46Skamil 14541.46Skamil child = await_stopped_child(parent); 14551.46Skamil 14561.46Skamil errno = 0; 14571.46Skamil rv = kill(child, SIGKILL); 14581.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14591.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14601.46Skamil 14611.46Skamil /* This exit value will be collected by initproc */ 14621.46Skamil _exit(0); 14631.46Skamil } 14641.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14651.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14661.61Skre watcher); 14671.46Skamil 14681.46Skamil validate_status_exited(status, exitval_watcher); 14691.46Skamil 14701.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14711.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14721.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14731.46Skamil } 14741.46Skamil 14751.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14761.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14771.40Skamil if (child == 0) { 14781.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14791.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14801.40Skamil 14811.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14821.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14831.40Skamil 14841.40Skamil switch (sigval) { 14851.46Skamil case SIGSTOP: 14861.40Skamil case SIGKILL: 14871.40Skamil case SIGABRT: 14881.40Skamil case SIGHUP: 14891.85Skamil case SIGTRAP: 14901.85Skamil case SIGBUS: 14911.85Skamil case SIGILL: 14921.85Skamil case SIGFPE: 14931.85Skamil case SIGSEGV: 14941.40Skamil /* NOTREACHED */ 14951.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14961.70Smrg __unreachable(); 14971.40Skamil default: 14981.40Skamil DPRINTF("Before exiting of the child process\n"); 14991.40Skamil _exit(exitval); 15001.40Skamil } 15011.40Skamil } 15021.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15031.40Skamil 15041.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15051.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15061.40Skamil 15071.40Skamil switch (sigval) { 15081.40Skamil case SIGKILL: 15091.40Skamil case SIGABRT: 15101.40Skamil case SIGHUP: 15111.85Skamil case SIGTRAP: 15121.85Skamil case SIGBUS: 15131.85Skamil case SIGILL: 15141.85Skamil case SIGFPE: 15151.85Skamil case SIGSEGV: 15161.40Skamil validate_status_signaled(status, sigval, expect_core); 15171.40Skamil break; 15181.40Skamil case SIGSTOP: 15191.46Skamil validate_status_signaled(status, SIGKILL, 0); 15201.46Skamil break; 15211.40Skamil case SIGCONT: 15221.47Skamil case SIGTSTP: 15231.47Skamil case SIGTTIN: 15241.47Skamil case SIGTTOU: 15251.40Skamil validate_status_exited(status, exitval); 15261.40Skamil break; 15271.40Skamil default: 15281.40Skamil /* NOTREACHED */ 15291.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15301.40Skamil break; 15311.40Skamil } 15321.40Skamil 15331.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15341.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15351.40Skamil} 15361.40Skamil 15371.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15381.61SkreATF_TC(test); \ 15391.61SkreATF_TC_HEAD(test, tc) \ 15401.61Skre{ \ 15411.61Skre atf_tc_set_md_var(tc, "descr", \ 15421.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15431.61Skre "vfork(2)ed child"); \ 15441.61Skre} \ 15451.61Skre \ 15461.61SkreATF_TC_BODY(test, tc) \ 15471.61Skre{ \ 15481.61Skre \ 15491.61Skre traceme_vfork_raise(sig); \ 15501.40Skamil} 15511.40Skamil 15521.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15531.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15541.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15551.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15561.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15571.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15581.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15591.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15601.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15611.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15621.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15631.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15641.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15651.40Skamil 15661.40Skamil/// ---------------------------------------------------------------------------- 15671.40Skamil 15681.52Skamilstatic void 15691.52Skamiltraceme_vfork_crash(int sig) 15701.41Skamil{ 15711.41Skamil pid_t child, wpid; 15721.41Skamil#if defined(TWAIT_HAVE_STATUS) 15731.41Skamil int status; 15741.41Skamil#endif 15751.41Skamil 15761.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15771.71Skamil if (sig == SIGILL) 15781.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15791.71Skamil#endif 15801.71Skamil 15811.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15821.114Skamil atf_tc_skip("FP exceptions are not supported"); 15831.114Skamil 15841.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15851.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15861.41Skamil if (child == 0) { 15871.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15881.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15891.41Skamil 15901.52Skamil DPRINTF("Before executing a trap\n"); 15911.52Skamil switch (sig) { 15921.52Skamil case SIGTRAP: 15931.52Skamil trigger_trap(); 15941.52Skamil break; 15951.52Skamil case SIGSEGV: 15961.52Skamil trigger_segv(); 15971.52Skamil break; 15981.52Skamil case SIGILL: 15991.52Skamil trigger_ill(); 16001.52Skamil break; 16011.52Skamil case SIGFPE: 16021.52Skamil trigger_fpe(); 16031.52Skamil break; 16041.52Skamil case SIGBUS: 16051.52Skamil trigger_bus(); 16061.52Skamil break; 16071.52Skamil default: 16081.52Skamil /* NOTREACHED */ 16091.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16101.52Skamil } 16111.41Skamil 16121.41Skamil /* NOTREACHED */ 16131.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16141.41Skamil } 16151.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16161.41Skamil 16171.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16181.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16191.41Skamil 16201.52Skamil validate_status_signaled(status, sig, 1); 16211.41Skamil 16221.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16231.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16241.41Skamil} 16251.41Skamil 16261.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16271.61SkreATF_TC(test); \ 16281.61SkreATF_TC_HEAD(test, tc) \ 16291.61Skre{ \ 16301.61Skre atf_tc_set_md_var(tc, "descr", \ 16311.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16321.61Skre "vfork(2)ed child"); \ 16331.61Skre} \ 16341.61Skre \ 16351.61SkreATF_TC_BODY(test, tc) \ 16361.61Skre{ \ 16371.61Skre \ 16381.61Skre traceme_vfork_crash(sig); \ 16391.52Skamil} 16401.52Skamil 16411.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16421.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16431.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16441.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16451.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16461.52Skamil 16471.41Skamil/// ---------------------------------------------------------------------------- 16481.41Skamil 16491.92Skamilstatic void 16501.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16511.92Skamil{ 16521.92Skamil pid_t child, wpid; 16531.92Skamil#if defined(TWAIT_HAVE_STATUS) 16541.92Skamil int status; 16551.92Skamil#endif 16561.92Skamil sigset_t intmask; 16571.92Skamil 16581.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16591.92Skamil if (sig == SIGILL) 16601.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16611.92Skamil#endif 16621.92Skamil 16631.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16641.114Skamil atf_tc_skip("FP exceptions are not supported"); 16651.114Skamil 16661.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16671.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16681.92Skamil if (child == 0) { 16691.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16701.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16711.92Skamil 16721.92Skamil sigemptyset(&intmask); 16731.92Skamil sigaddset(&intmask, sig); 16741.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16751.92Skamil 16761.92Skamil DPRINTF("Before executing a trap\n"); 16771.92Skamil switch (sig) { 16781.92Skamil case SIGTRAP: 16791.92Skamil trigger_trap(); 16801.92Skamil break; 16811.92Skamil case SIGSEGV: 16821.92Skamil trigger_segv(); 16831.92Skamil break; 16841.92Skamil case SIGILL: 16851.92Skamil trigger_ill(); 16861.92Skamil break; 16871.92Skamil case SIGFPE: 16881.92Skamil trigger_fpe(); 16891.92Skamil break; 16901.92Skamil case SIGBUS: 16911.92Skamil trigger_bus(); 16921.92Skamil break; 16931.92Skamil default: 16941.92Skamil /* NOTREACHED */ 16951.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16961.92Skamil } 16971.92Skamil 16981.92Skamil /* NOTREACHED */ 16991.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17001.92Skamil } 17011.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17021.92Skamil 17031.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17041.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17051.92Skamil 17061.92Skamil validate_status_signaled(status, sig, 1); 17071.92Skamil 17081.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17091.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17101.92Skamil} 17111.92Skamil 17121.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 17131.92SkamilATF_TC(test); \ 17141.92SkamilATF_TC_HEAD(test, tc) \ 17151.92Skamil{ \ 17161.92Skamil atf_tc_set_md_var(tc, "descr", \ 17171.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17181.92Skamil "vfork(2)ed child with a masked signal"); \ 17191.92Skamil} \ 17201.92Skamil \ 17211.92SkamilATF_TC_BODY(test, tc) \ 17221.92Skamil{ \ 17231.92Skamil \ 17241.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17251.92Skamil} 17261.92Skamil 17271.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17281.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17291.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17301.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17311.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17321.92Skamil 17331.92Skamil/// ---------------------------------------------------------------------------- 17341.92Skamil 17351.92Skamilstatic void 17361.92Skamiltraceme_vfork_signalignored_crash(int sig) 17371.92Skamil{ 17381.92Skamil pid_t child, wpid; 17391.92Skamil#if defined(TWAIT_HAVE_STATUS) 17401.92Skamil int status; 17411.92Skamil#endif 17421.92Skamil struct sigaction sa; 17431.92Skamil 17441.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17451.92Skamil if (sig == SIGILL) 17461.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17471.92Skamil#endif 17481.92Skamil 17491.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17501.114Skamil atf_tc_skip("FP exceptions are not supported"); 17511.114Skamil 17521.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17531.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17541.92Skamil if (child == 0) { 17551.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17561.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17571.92Skamil 17581.92Skamil memset(&sa, 0, sizeof(sa)); 17591.92Skamil sa.sa_handler = SIG_IGN; 17601.92Skamil sigemptyset(&sa.sa_mask); 17611.92Skamil 17621.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17631.92Skamil 17641.92Skamil DPRINTF("Before executing a trap\n"); 17651.92Skamil switch (sig) { 17661.92Skamil case SIGTRAP: 17671.92Skamil trigger_trap(); 17681.92Skamil break; 17691.92Skamil case SIGSEGV: 17701.92Skamil trigger_segv(); 17711.92Skamil break; 17721.92Skamil case SIGILL: 17731.92Skamil trigger_ill(); 17741.92Skamil break; 17751.92Skamil case SIGFPE: 17761.92Skamil trigger_fpe(); 17771.92Skamil break; 17781.92Skamil case SIGBUS: 17791.92Skamil trigger_bus(); 17801.92Skamil break; 17811.92Skamil default: 17821.92Skamil /* NOTREACHED */ 17831.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17841.92Skamil } 17851.92Skamil 17861.92Skamil /* NOTREACHED */ 17871.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17881.92Skamil } 17891.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17901.92Skamil 17911.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17921.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17931.92Skamil 17941.92Skamil validate_status_signaled(status, sig, 1); 17951.92Skamil 17961.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17971.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17981.92Skamil} 17991.92Skamil 18001.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 18011.92SkamilATF_TC(test); \ 18021.92SkamilATF_TC_HEAD(test, tc) \ 18031.92Skamil{ \ 18041.92Skamil atf_tc_set_md_var(tc, "descr", \ 18051.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 18061.92Skamil "vfork(2)ed child with ignored signal"); \ 18071.92Skamil} \ 18081.92Skamil \ 18091.92SkamilATF_TC_BODY(test, tc) \ 18101.92Skamil{ \ 18111.92Skamil \ 18121.92Skamil traceme_vfork_signalignored_crash(sig); \ 18131.92Skamil} 18141.92Skamil 18151.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 18161.92Skamil SIGTRAP) 18171.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 18181.92Skamil SIGSEGV) 18191.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 18201.92Skamil SIGILL) 18211.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 18221.92Skamil SIGFPE) 18231.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 18241.92Skamil SIGBUS) 18251.92Skamil 18261.92Skamil/// ---------------------------------------------------------------------------- 18271.92Skamil 18281.96Skamilstatic void 18291.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18301.43Skamil{ 18311.43Skamil const int sigval = SIGTRAP; 18321.43Skamil pid_t child, wpid; 18331.43Skamil#if defined(TWAIT_HAVE_STATUS) 18341.43Skamil int status; 18351.43Skamil#endif 18361.96Skamil struct sigaction sa; 18371.61Skre struct ptrace_siginfo info; 18381.96Skamil sigset_t intmask; 18391.96Skamil struct kinfo_proc2 kp; 18401.96Skamil size_t len = sizeof(kp); 18411.96Skamil 18421.96Skamil int name[6]; 18431.96Skamil const size_t namelen = __arraycount(name); 18441.96Skamil ki_sigset_t kp_sigmask; 18451.96Skamil ki_sigset_t kp_sigignore; 18461.43Skamil 18471.43Skamil memset(&info, 0, sizeof(info)); 18481.43Skamil 18491.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18501.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18511.43Skamil if (child == 0) { 18521.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18531.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18541.43Skamil 18551.96Skamil if (masked) { 18561.96Skamil sigemptyset(&intmask); 18571.96Skamil sigaddset(&intmask, sigval); 18581.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18591.96Skamil } 18601.96Skamil 18611.96Skamil if (ignored) { 18621.96Skamil memset(&sa, 0, sizeof(sa)); 18631.96Skamil sa.sa_handler = SIG_IGN; 18641.96Skamil sigemptyset(&sa.sa_mask); 18651.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18661.96Skamil } 18671.96Skamil 18681.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18691.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18701.43Skamil 18711.43Skamil /* NOTREACHED */ 18721.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18731.43Skamil } 18741.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18751.43Skamil 18761.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18771.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18781.43Skamil 18791.43Skamil validate_status_stopped(status, sigval); 18801.43Skamil 18811.96Skamil name[0] = CTL_KERN, 18821.96Skamil name[1] = KERN_PROC2, 18831.96Skamil name[2] = KERN_PROC_PID; 18841.96Skamil name[3] = getpid(); 18851.96Skamil name[4] = sizeof(kp); 18861.96Skamil name[5] = 1; 18871.96Skamil 18881.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18891.96Skamil 18901.96Skamil if (masked) 18911.96Skamil kp_sigmask = kp.p_sigmask; 18921.96Skamil 18931.96Skamil if (ignored) 18941.96Skamil kp_sigignore = kp.p_sigignore; 18951.96Skamil 18961.96Skamil name[3] = getpid(); 18971.96Skamil 18981.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18991.96Skamil 19001.96Skamil if (masked) { 19011.96Skamil DPRINTF("kp_sigmask=" 19021.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19031.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 19041.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 19051.96Skamil 19061.96Skamil DPRINTF("kp.p_sigmask=" 19071.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19081.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 19091.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 19101.96Skamil 19111.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 19121.96Skamil sizeof(kp_sigmask))); 19131.96Skamil } 19141.96Skamil 19151.96Skamil if (ignored) { 19161.96Skamil DPRINTF("kp_sigignore=" 19171.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19181.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 19191.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 19201.96Skamil 19211.96Skamil DPRINTF("kp.p_sigignore=" 19221.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19231.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 19241.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19251.96Skamil 19261.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19271.96Skamil sizeof(kp_sigignore))); 19281.96Skamil } 19291.96Skamil 19301.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19311.61Skre SYSCALL_REQUIRE( 19321.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19331.43Skamil 19341.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19351.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19361.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19371.43Skamil info.psi_siginfo.si_errno); 19381.43Skamil 19391.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19401.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19411.43Skamil 19421.43Skamil DPRINTF("Before resuming the child process where it left off and " 19431.43Skamil "without signal to be sent\n"); 19441.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19451.43Skamil 19461.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19471.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19481.43Skamil 19491.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19501.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19511.43Skamil} 19521.43Skamil 19531.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19541.96SkamilATF_TC(test); \ 19551.96SkamilATF_TC_HEAD(test, tc) \ 19561.96Skamil{ \ 19571.96Skamil atf_tc_set_md_var(tc, "descr", \ 19581.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19591.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19601.96Skamil masked ? " with ignored signal" : ""); \ 19611.96Skamil} \ 19621.96Skamil \ 19631.96SkamilATF_TC_BODY(test, tc) \ 19641.96Skamil{ \ 19651.96Skamil \ 19661.96Skamil traceme_vfork_exec(masked, ignored); \ 19671.96Skamil} 19681.96Skamil 19691.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19701.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19711.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19721.96Skamil 19731.43Skamil/// ---------------------------------------------------------------------------- 19741.43Skamil 19751.1Skamil#if defined(TWAIT_HAVE_PID) 19761.51Skamilstatic void 19771.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19781.59Skamil{ 19791.94Skamil const int sigval = SIGSTOP; 19801.59Skamil struct msg_fds parent_tracee, parent_tracer; 19811.59Skamil const int exitval = 10; 19821.59Skamil pid_t tracee, tracer, wpid; 19831.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19841.59Skamil#if defined(TWAIT_HAVE_STATUS) 19851.59Skamil int status; 19861.59Skamil#endif 19871.94Skamil struct sigaction sa; 19881.59Skamil struct ptrace_siginfo info; 19891.94Skamil sigset_t intmask; 19901.94Skamil struct kinfo_proc2 kp; 19911.94Skamil size_t len = sizeof(kp); 19921.94Skamil 19931.94Skamil int name[6]; 19941.94Skamil const size_t namelen = __arraycount(name); 19951.94Skamil ki_sigset_t kp_sigmask; 19961.94Skamil ki_sigset_t kp_sigignore; 19971.61Skre 19981.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19991.71Skamil if (sig == SIGILL) 20001.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 20011.71Skamil#endif 20021.71Skamil 20031.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 20041.114Skamil atf_tc_skip("FP exceptions are not supported"); 20051.114Skamil 20061.59Skamil memset(&info, 0, sizeof(info)); 20071.59Skamil 20081.59Skamil DPRINTF("Spawn tracee\n"); 20091.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 20101.59Skamil tracee = atf_utils_fork(); 20111.59Skamil if (tracee == 0) { 20121.59Skamil // Wait for parent to let us crash 20131.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 20141.61Skre 20151.94Skamil if (masked) { 20161.94Skamil sigemptyset(&intmask); 20171.94Skamil sigaddset(&intmask, sig); 20181.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 20191.94Skamil } 20201.94Skamil 20211.94Skamil if (ignored) { 20221.94Skamil memset(&sa, 0, sizeof(sa)); 20231.94Skamil sa.sa_handler = SIG_IGN; 20241.94Skamil sigemptyset(&sa.sa_mask); 20251.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20261.94Skamil } 20271.94Skamil 20281.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20291.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20301.94Skamil 20311.59Skamil DPRINTF("Before executing a trap\n"); 20321.59Skamil switch (sig) { 20331.59Skamil case SIGTRAP: 20341.59Skamil trigger_trap(); 20351.59Skamil break; 20361.59Skamil case SIGSEGV: 20371.59Skamil trigger_segv(); 20381.59Skamil break; 20391.59Skamil case SIGILL: 20401.59Skamil trigger_ill(); 20411.59Skamil break; 20421.59Skamil case SIGFPE: 20431.59Skamil trigger_fpe(); 20441.59Skamil break; 20451.59Skamil case SIGBUS: 20461.59Skamil trigger_bus(); 20471.59Skamil break; 20481.59Skamil default: 20491.59Skamil /* NOTREACHED */ 20501.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20511.59Skamil } 20521.59Skamil 20531.59Skamil /* NOTREACHED */ 20541.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20551.59Skamil } 20561.59Skamil 20571.59Skamil DPRINTF("Spawn debugger\n"); 20581.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20591.59Skamil tracer = atf_utils_fork(); 20601.59Skamil if (tracer == 0) { 20611.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20621.59Skamil tracer = atf_utils_fork(); 20631.59Skamil if (tracer != 0) 20641.61Skre _exit(exitval); 20651.59Skamil 20661.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20671.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20681.59Skamil 20691.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20701.59Skamil FORKEE_REQUIRE_SUCCESS( 20711.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20721.59Skamil 20731.59Skamil forkee_status_stopped(status, SIGSTOP); 20741.59Skamil 20751.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20761.94Skamil "traced process\n"); 20771.94Skamil SYSCALL_REQUIRE( 20781.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20791.94Skamil 20801.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20811.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20821.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20831.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20841.94Skamil 20851.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20861.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20871.94Skamil 20881.59Skamil /* Resume tracee with PT_CONTINUE */ 20891.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20901.59Skamil 20911.59Skamil /* Inform parent that tracer has attached to tracee */ 20921.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20931.59Skamil 20941.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20951.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20961.59Skamil 20971.59Skamil /* Wait for tracee and assert that it exited */ 20981.59Skamil FORKEE_REQUIRE_SUCCESS( 20991.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21001.59Skamil 21011.94Skamil forkee_status_stopped(status, sigval); 21021.94Skamil 21031.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21041.94Skamil "traced process\n"); 21051.94Skamil SYSCALL_REQUIRE( 21061.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21071.94Skamil 21081.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21091.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21101.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 21111.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21121.94Skamil 21131.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 21141.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 21151.94Skamil 21161.94Skamil name[0] = CTL_KERN, 21171.94Skamil name[1] = KERN_PROC2, 21181.94Skamil name[2] = KERN_PROC_PID; 21191.94Skamil name[3] = tracee; 21201.94Skamil name[4] = sizeof(kp); 21211.94Skamil name[5] = 1; 21221.94Skamil 21231.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21241.94Skamil 21251.94Skamil if (masked) 21261.94Skamil kp_sigmask = kp.p_sigmask; 21271.94Skamil 21281.94Skamil if (ignored) 21291.94Skamil kp_sigignore = kp.p_sigignore; 21301.94Skamil 21311.94Skamil /* Resume tracee with PT_CONTINUE */ 21321.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21331.94Skamil 21341.94Skamil /* Wait for tracee and assert that it exited */ 21351.94Skamil FORKEE_REQUIRE_SUCCESS( 21361.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21371.94Skamil 21381.93Skamil forkee_status_stopped(status, sig); 21391.59Skamil 21401.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21411.61Skre "traced process\n"); 21421.61Skre SYSCALL_REQUIRE( 21431.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21441.59Skamil 21451.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21461.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21471.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21481.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21491.59Skamil 21501.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21511.94Skamil 21521.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21531.94Skamil 21541.94Skamil if (masked) { 21551.94Skamil DPRINTF("kp_sigmask=" 21561.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21571.94Skamil PRIx32 "\n", 21581.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21591.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21601.94Skamil 21611.94Skamil DPRINTF("kp.p_sigmask=" 21621.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21631.94Skamil PRIx32 "\n", 21641.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21651.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21661.94Skamil 21671.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21681.94Skamil sizeof(kp_sigmask))); 21691.94Skamil } 21701.94Skamil 21711.94Skamil if (ignored) { 21721.94Skamil DPRINTF("kp_sigignore=" 21731.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21741.94Skamil PRIx32 "\n", 21751.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21761.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21771.94Skamil 21781.94Skamil DPRINTF("kp.p_sigignore=" 21791.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21801.94Skamil PRIx32 "\n", 21811.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21821.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21831.94Skamil 21841.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21851.94Skamil sizeof(kp_sigignore))); 21861.94Skamil } 21871.94Skamil 21881.59Skamil switch (sig) { 21891.59Skamil case SIGTRAP: 21901.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21911.59Skamil break; 21921.59Skamil case SIGSEGV: 21931.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21941.59Skamil break; 21951.71Skamil case SIGILL: 21961.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21971.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21981.71Skamil break; 21991.59Skamil case SIGFPE: 22001.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 22011.59Skamil break; 22021.59Skamil case SIGBUS: 22031.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 22041.59Skamil break; 22051.59Skamil } 22061.59Skamil 22071.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 22081.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 22091.93Skamil FORKEE_REQUIRE_SUCCESS( 22101.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22111.59Skamil 22121.93Skamil forkee_status_signaled(status, SIGKILL, 0); 22131.59Skamil 22141.71Skamil /* Inform parent that tracer is exiting normally */ 22151.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 22161.71Skamil 22171.59Skamil DPRINTF("Before exiting of the tracer process\n"); 22181.59Skamil _exit(0 /* collect by initproc */); 22191.59Skamil } 22201.59Skamil 22211.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 22221.59Skamil "calling %s()\n", TWAIT_FNAME); 22231.59Skamil TWAIT_REQUIRE_SUCCESS( 22241.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22251.59Skamil 22261.59Skamil validate_status_exited(status, exitval); 22271.59Skamil 22281.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22291.59Skamil TWAIT_FNAME); 22301.59Skamil TWAIT_REQUIRE_SUCCESS( 22311.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22321.59Skamil 22331.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22341.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22351.59Skamil 22361.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22371.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22381.59Skamil 22391.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22401.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22411.59Skamil 22421.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22431.59Skamil TWAIT_FNAME); 22441.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22451.59Skamil 22461.59Skamil validate_status_signaled(status, SIGKILL, 0); 22471.59Skamil 22481.71Skamil DPRINTF("Await normal exit of tracer\n"); 22491.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22501.71Skamil 22511.59Skamil msg_close(&parent_tracer); 22521.59Skamil msg_close(&parent_tracee); 22531.59Skamil} 22541.59Skamil 22551.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22561.61SkreATF_TC(test); \ 22571.61SkreATF_TC_HEAD(test, tc) \ 22581.61Skre{ \ 22591.61Skre atf_tc_set_md_var(tc, "descr", \ 22601.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22611.94Skamil "the debuggee"); \ 22621.61Skre} \ 22631.61Skre \ 22641.61SkreATF_TC_BODY(test, tc) \ 22651.61Skre{ \ 22661.61Skre \ 22671.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22681.59Skamil} 22691.59Skamil 22701.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22711.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22721.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22731.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22741.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22751.94Skamil 22761.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22771.94SkamilATF_TC(test); \ 22781.94SkamilATF_TC_HEAD(test, tc) \ 22791.94Skamil{ \ 22801.94Skamil atf_tc_set_md_var(tc, "descr", \ 22811.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22821.94Skamil "the debuggee with masked signal"); \ 22831.94Skamil} \ 22841.94Skamil \ 22851.94SkamilATF_TC_BODY(test, tc) \ 22861.94Skamil{ \ 22871.94Skamil \ 22881.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22891.94Skamil} 22901.94Skamil 22911.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22921.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22931.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22941.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22951.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22961.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22971.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22981.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22991.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 23001.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 23011.94Skamil 23021.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 23031.94SkamilATF_TC(test); \ 23041.94SkamilATF_TC_HEAD(test, tc) \ 23051.94Skamil{ \ 23061.94Skamil atf_tc_set_md_var(tc, "descr", \ 23071.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 23081.94Skamil "the debuggee with signal ignored"); \ 23091.94Skamil} \ 23101.94Skamil \ 23111.94SkamilATF_TC_BODY(test, tc) \ 23121.94Skamil{ \ 23131.94Skamil \ 23141.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 23151.94Skamil} 23161.94Skamil 23171.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23181.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 23191.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23201.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 23211.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23221.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 23231.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23241.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23251.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23261.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23271.59Skamil#endif 23281.59Skamil 23291.59Skamil/// ---------------------------------------------------------------------------- 23301.59Skamil 23311.59Skamil#if defined(TWAIT_HAVE_PID) 23321.59Skamilstatic void 23331.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23341.67Skamil bool stopped) 23351.1Skamil{ 23361.51Skamil /* 23371.51Skamil * notimeout - disable timeout in await zombie function 23381.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23391.67Skamil * stopped - attach to a stopped process 23401.51Skamil */ 23411.1Skamil 23421.1Skamil struct msg_fds parent_tracee, parent_tracer; 23431.1Skamil const int exitval_tracee = 5; 23441.1Skamil const int exitval_tracer = 10; 23451.1Skamil pid_t tracee, tracer, wpid; 23461.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23471.1Skamil#if defined(TWAIT_HAVE_STATUS) 23481.1Skamil int status; 23491.1Skamil#endif 23501.1Skamil 23511.67Skamil /* 23521.67Skamil * Only a subset of options are supported. 23531.67Skamil */ 23541.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23551.67Skamil (!notimeout && unrelated && !stopped) || 23561.67Skamil (notimeout && !unrelated && !stopped) || 23571.67Skamil (!notimeout && unrelated && stopped)); 23581.67Skamil 23591.13Schristos DPRINTF("Spawn tracee\n"); 23601.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23611.1Skamil tracee = atf_utils_fork(); 23621.1Skamil if (tracee == 0) { 23631.67Skamil if (stopped) { 23641.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23651.67Skamil raise(SIGSTOP); 23661.67Skamil } 23671.67Skamil 23681.1Skamil // Wait for parent to let us exit 23691.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23701.1Skamil _exit(exitval_tracee); 23711.1Skamil } 23721.1Skamil 23731.13Schristos DPRINTF("Spawn debugger\n"); 23741.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23751.1Skamil tracer = atf_utils_fork(); 23761.1Skamil if (tracer == 0) { 23771.51Skamil if(unrelated) { 23781.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23791.51Skamil tracer = atf_utils_fork(); 23801.51Skamil if (tracer != 0) 23811.51Skamil _exit(exitval_tracer); 23821.51Skamil } 23831.51Skamil 23841.67Skamil if (stopped) { 23851.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23861.67Skamil await_stopped(tracee); 23871.67Skamil } 23881.67Skamil 23891.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23901.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23911.1Skamil 23921.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23931.1Skamil FORKEE_REQUIRE_SUCCESS( 23941.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23951.1Skamil 23961.1Skamil forkee_status_stopped(status, SIGSTOP); 23971.1Skamil 23981.1Skamil /* Resume tracee with PT_CONTINUE */ 23991.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 24001.1Skamil 24011.1Skamil /* Inform parent that tracer has attached to tracee */ 24021.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 24031.1Skamil 24041.1Skamil /* Wait for parent to tell use that tracee should have exited */ 24051.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 24061.1Skamil 24071.1Skamil /* Wait for tracee and assert that it exited */ 24081.1Skamil FORKEE_REQUIRE_SUCCESS( 24091.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24101.1Skamil 24111.1Skamil forkee_status_exited(status, exitval_tracee); 24121.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 24131.1Skamil 24141.13Schristos DPRINTF("Before exiting of the tracer process\n"); 24151.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 24161.51Skamil } 24171.51Skamil 24181.51Skamil if (unrelated) { 24191.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 24201.51Skamil "calling %s()\n", TWAIT_FNAME); 24211.51Skamil TWAIT_REQUIRE_SUCCESS( 24221.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 24231.51Skamil 24241.51Skamil validate_status_exited(status, exitval_tracer); 24251.51Skamil 24261.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24271.51Skamil TWAIT_FNAME); 24281.51Skamil TWAIT_REQUIRE_SUCCESS( 24291.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24301.1Skamil } 24311.1Skamil 24321.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24331.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24341.1Skamil 24351.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24361.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24371.1Skamil 24381.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24391.51Skamil if (notimeout) 24401.26Skamil await_zombie_raw(tracee, 0); 24411.26Skamil else 24421.26Skamil await_zombie(tracee); 24431.1Skamil 24441.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24451.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24461.1Skamil TWAIT_FNAME); 24471.1Skamil TWAIT_REQUIRE_SUCCESS( 24481.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24491.1Skamil 24501.51Skamil if (unrelated) { 24511.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24521.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24531.51Skamil } else { 24541.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24551.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24561.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24571.59Skamil "%s()\n", TWAIT_FNAME); 24581.51Skamil 24591.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24601.59Skamil "tracee\n"); 24611.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24621.51Skamil tracer); 24631.1Skamil 24641.51Skamil validate_status_exited(status, exitval_tracer); 24651.51Skamil } 24661.1Skamil 24671.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24681.1Skamil TWAIT_FNAME); 24691.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24701.1Skamil 24711.1Skamil validate_status_exited(status, exitval_tracee); 24721.1Skamil 24731.1Skamil msg_close(&parent_tracer); 24741.1Skamil msg_close(&parent_tracee); 24751.1Skamil} 24761.26Skamil 24771.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24781.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24791.51Skamil{ 24801.51Skamil atf_tc_set_md_var(tc, "descr", 24811.51Skamil "Assert that tracer sees process termination before the parent"); 24821.51Skamil} 24831.51Skamil 24841.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24851.26Skamil{ 24861.26Skamil 24871.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24881.26Skamil} 24891.26Skamil 24901.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24911.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24921.1Skamil{ 24931.164Skamil atf_tc_set_md_var(tc, "timeout", "15"); 24941.1Skamil atf_tc_set_md_var(tc, "descr", 24951.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24961.51Skamil "process and no other error is reported"); 24971.1Skamil} 24981.1Skamil 24991.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 25001.1Skamil{ 25011.51Skamil time_t start, end; 25021.51Skamil double diff; 25031.51Skamil unsigned long N = 0; 25041.1Skamil 25051.51Skamil /* 25061.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 25071.51Skamil * This test body isn't specific to this race, however it's just good 25081.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 25091.51Skamil */ 25101.1Skamil 25111.51Skamil start = time(NULL); 25121.51Skamil while (true) { 25131.51Skamil DPRINTF("Step: %lu\n", N); 25141.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 25151.67Skamil false); 25161.51Skamil end = time(NULL); 25171.51Skamil diff = difftime(end, start); 25181.51Skamil if (diff >= 5.0) 25191.51Skamil break; 25201.51Skamil ++N; 25211.1Skamil } 25221.51Skamil DPRINTF("Iterations: %lu\n", N); 25231.51Skamil} 25241.1Skamil 25251.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25261.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25271.51Skamil{ 25281.51Skamil atf_tc_set_md_var(tc, "descr", 25291.51Skamil "Assert that tracer sees process termination before the parent"); 25301.51Skamil} 25311.1Skamil 25321.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25331.51Skamil{ 25341.1Skamil 25351.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25361.67Skamil} 25371.67Skamil 25381.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25391.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25401.67Skamil{ 25411.67Skamil atf_tc_set_md_var(tc, "descr", 25421.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25431.67Skamil} 25441.67Skamil 25451.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25461.67Skamil{ 25471.67Skamil 25481.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25491.1Skamil} 25501.1Skamil#endif 25511.1Skamil 25521.51Skamil/// ---------------------------------------------------------------------------- 25531.51Skamil 25541.66Skamilstatic void 25551.66Skamilparent_attach_to_its_child(bool stopped) 25561.1Skamil{ 25571.1Skamil struct msg_fds parent_tracee; 25581.1Skamil const int exitval_tracee = 5; 25591.1Skamil pid_t tracee, wpid; 25601.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25611.1Skamil#if defined(TWAIT_HAVE_STATUS) 25621.1Skamil int status; 25631.1Skamil#endif 25641.1Skamil 25651.13Schristos DPRINTF("Spawn tracee\n"); 25661.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25671.1Skamil tracee = atf_utils_fork(); 25681.1Skamil if (tracee == 0) { 25691.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25701.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25711.1Skamil 25721.66Skamil if (stopped) { 25731.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25741.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25751.66Skamil } 25761.66Skamil 25771.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25781.1Skamil /* Wait for message from the parent */ 25791.1Skamil _exit(exitval_tracee); 25801.1Skamil } 25811.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25821.57Skamil 25831.66Skamil if (stopped) { 25841.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25851.66Skamil await_stopped(tracee); 25861.66Skamil } 25871.66Skamil 25881.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25891.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25901.1Skamil 25911.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25921.1Skamil TWAIT_FNAME); 25931.1Skamil TWAIT_REQUIRE_SUCCESS( 25941.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25951.1Skamil 25961.1Skamil validate_status_stopped(status, SIGSTOP); 25971.1Skamil 25981.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25991.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 26001.1Skamil 26011.13Schristos DPRINTF("Let the tracee exit now\n"); 26021.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 26031.1Skamil 26041.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 26051.1Skamil TWAIT_REQUIRE_SUCCESS( 26061.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 26071.1Skamil 26081.1Skamil validate_status_exited(status, exitval_tracee); 26091.1Skamil 26101.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 26111.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26121.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 26131.1Skamil 26141.1Skamil msg_close(&parent_tracee); 26151.1Skamil} 26161.1Skamil 26171.66SkamilATF_TC(parent_attach_to_its_child); 26181.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 26191.66Skamil{ 26201.66Skamil atf_tc_set_md_var(tc, "descr", 26211.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 26221.66Skamil} 26231.66Skamil 26241.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26251.66Skamil{ 26261.66Skamil 26271.66Skamil parent_attach_to_its_child(false); 26281.66Skamil} 26291.66Skamil 26301.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26311.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26321.66Skamil{ 26331.66Skamil atf_tc_set_md_var(tc, "descr", 26341.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26351.66Skamil} 26361.66Skamil 26371.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26381.66Skamil{ 26391.66Skamil 26401.66Skamil parent_attach_to_its_child(true); 26411.66Skamil} 26421.66Skamil 26431.51Skamil/// ---------------------------------------------------------------------------- 26441.51Skamil 26451.65Skamilstatic void 26461.65Skamilchild_attach_to_its_parent(bool stopped) 26471.1Skamil{ 26481.1Skamil struct msg_fds parent_tracee; 26491.1Skamil const int exitval_tracer = 5; 26501.1Skamil pid_t tracer, wpid; 26511.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26521.1Skamil#if defined(TWAIT_HAVE_STATUS) 26531.1Skamil int status; 26541.1Skamil#endif 26551.1Skamil 26561.13Schristos DPRINTF("Spawn tracer\n"); 26571.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26581.1Skamil tracer = atf_utils_fork(); 26591.1Skamil if (tracer == 0) { 26601.1Skamil /* Wait for message from the parent */ 26611.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26621.1Skamil 26631.65Skamil if (stopped) { 26641.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26651.65Skamil getppid()); 26661.65Skamil await_stopped(getppid()); 26671.65Skamil } 26681.65Skamil 26691.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26701.1Skamil getppid()); 26711.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26721.1Skamil 26731.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26741.1Skamil TWAIT_FNAME); 26751.1Skamil FORKEE_REQUIRE_SUCCESS( 26761.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26771.1Skamil 26781.1Skamil forkee_status_stopped(status, SIGSTOP); 26791.1Skamil 26801.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26811.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26821.1Skamil != -1); 26831.1Skamil 26841.1Skamil /* Tell parent we are ready */ 26851.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26861.1Skamil 26871.1Skamil _exit(exitval_tracer); 26881.1Skamil } 26891.1Skamil 26901.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26911.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26921.65Skamil 26931.65Skamil if (stopped) { 26941.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26951.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26961.65Skamil } 26971.65Skamil 26981.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26991.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 27001.1Skamil 27011.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 27021.1Skamil TWAIT_REQUIRE_SUCCESS( 27031.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 27041.1Skamil 27051.1Skamil validate_status_exited(status, exitval_tracer); 27061.1Skamil 27071.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 27081.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 27091.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 27101.1Skamil 27111.1Skamil msg_close(&parent_tracee); 27121.1Skamil} 27131.1Skamil 27141.65SkamilATF_TC(child_attach_to_its_parent); 27151.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 27161.65Skamil{ 27171.65Skamil atf_tc_set_md_var(tc, "descr", 27181.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 27191.65Skamil} 27201.65Skamil 27211.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 27221.65Skamil{ 27231.65Skamil 27241.65Skamil child_attach_to_its_parent(false); 27251.65Skamil} 27261.65Skamil 27271.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27281.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27291.65Skamil{ 27301.65Skamil atf_tc_set_md_var(tc, "descr", 27311.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27321.65Skamil} 27331.65Skamil 27341.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27351.65Skamil{ 27361.65Skamil /* 27371.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27381.65Skamil * this causes a pipe (established from atf-run) to be broken. 27391.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27401.65Skamil * 27411.65Skamil * As a workaround spawn this test as a subprocess. 27421.65Skamil */ 27431.65Skamil 27441.65Skamil const int exitval = 15; 27451.65Skamil pid_t child, wpid; 27461.65Skamil#if defined(TWAIT_HAVE_STATUS) 27471.65Skamil int status; 27481.65Skamil#endif 27491.65Skamil 27501.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27511.65Skamil if (child == 0) { 27521.65Skamil child_attach_to_its_parent(true); 27531.65Skamil _exit(exitval); 27541.65Skamil } else { 27551.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27561.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27571.65Skamil 27581.65Skamil validate_status_exited(status, exitval); 27591.65Skamil 27601.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27611.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27621.65Skamil } 27631.65Skamil} 27641.65Skamil 27651.51Skamil/// ---------------------------------------------------------------------------- 27661.51Skamil 27671.1Skamil#if defined(TWAIT_HAVE_PID) 27681.1Skamil 27691.51Skamilenum tracee_sees_its_original_parent_type { 27701.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27711.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27721.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27731.51Skamil}; 27741.51Skamil 27751.51Skamilstatic void 27761.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27771.1Skamil{ 27781.1Skamil struct msg_fds parent_tracer, parent_tracee; 27791.1Skamil const int exitval_tracee = 5; 27801.1Skamil const int exitval_tracer = 10; 27811.1Skamil pid_t parent, tracee, tracer, wpid; 27821.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27831.1Skamil#if defined(TWAIT_HAVE_STATUS) 27841.1Skamil int status; 27851.1Skamil#endif 27861.51Skamil /* sysctl(3) - kinfo_proc2 */ 27871.51Skamil int name[CTL_MAXNAME]; 27881.51Skamil struct kinfo_proc2 kp; 27891.51Skamil size_t len = sizeof(kp); 27901.51Skamil unsigned int namelen; 27911.51Skamil 27921.51Skamil /* procfs - status */ 27931.51Skamil FILE *fp; 27941.51Skamil struct stat st; 27951.51Skamil const char *fname = "/proc/curproc/status"; 27961.51Skamil char s_executable[MAXPATHLEN]; 27971.51Skamil int s_pid, s_ppid; 27981.51Skamil int rv; 27991.51Skamil 28001.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 28011.61Skre SYSCALL_REQUIRE( 28021.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 28031.61Skre if (rv != 0) 28041.51Skamil atf_tc_skip("/proc/curproc/status not found"); 28051.51Skamil } 28061.1Skamil 28071.13Schristos DPRINTF("Spawn tracee\n"); 28081.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 28091.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 28101.1Skamil tracee = atf_utils_fork(); 28111.1Skamil if (tracee == 0) { 28121.1Skamil parent = getppid(); 28131.1Skamil 28141.1Skamil /* Emit message to the parent */ 28151.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 28161.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 28171.1Skamil 28181.51Skamil switch (type) { 28191.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 28201.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 28211.51Skamil break; 28221.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 28231.51Skamil namelen = 0; 28241.51Skamil name[namelen++] = CTL_KERN; 28251.51Skamil name[namelen++] = KERN_PROC2; 28261.51Skamil name[namelen++] = KERN_PROC_PID; 28271.51Skamil name[namelen++] = getpid(); 28281.51Skamil name[namelen++] = len; 28291.51Skamil name[namelen++] = 1; 28301.51Skamil 28311.61Skre FORKEE_ASSERT_EQ( 28321.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28331.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28341.51Skamil break; 28351.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28361.51Skamil /* 28371.51Skamil * Format: 28381.51Skamil * EXECUTABLE PID PPID ... 28391.51Skamil */ 28401.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28411.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28421.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28431.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28441.51Skamil break; 28451.51Skamil } 28461.1Skamil 28471.1Skamil _exit(exitval_tracee); 28481.1Skamil } 28491.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28501.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28511.1Skamil 28521.13Schristos DPRINTF("Spawn debugger\n"); 28531.1Skamil tracer = atf_utils_fork(); 28541.1Skamil if (tracer == 0) { 28551.1Skamil /* No IPC to communicate with the child */ 28561.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28571.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28581.1Skamil 28591.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28601.1Skamil FORKEE_REQUIRE_SUCCESS( 28611.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28621.1Skamil 28631.1Skamil forkee_status_stopped(status, SIGSTOP); 28641.1Skamil 28651.1Skamil /* Resume tracee with PT_CONTINUE */ 28661.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28671.1Skamil 28681.1Skamil /* Inform parent that tracer has attached to tracee */ 28691.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28701.1Skamil 28711.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28721.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28731.1Skamil 28741.1Skamil /* Wait for tracee and assert that it exited */ 28751.1Skamil FORKEE_REQUIRE_SUCCESS( 28761.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28771.1Skamil 28781.1Skamil forkee_status_exited(status, exitval_tracee); 28791.1Skamil 28801.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28811.1Skamil _exit(exitval_tracer); 28821.1Skamil } 28831.1Skamil 28841.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28851.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28861.1Skamil 28871.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28881.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28891.1Skamil 28901.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28911.1Skamil await_zombie(tracee); 28921.1Skamil 28931.13Schristos DPRINTF("Assert that there is no status about tracee - " 28941.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28951.1Skamil TWAIT_REQUIRE_SUCCESS( 28961.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28971.1Skamil 28981.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28991.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 29001.1Skamil 29011.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 29021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 29031.1Skamil tracer); 29041.1Skamil 29051.1Skamil validate_status_exited(status, exitval_tracer); 29061.1Skamil 29071.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 29081.1Skamil TWAIT_FNAME); 29091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 29101.1Skamil tracee); 29111.1Skamil 29121.1Skamil validate_status_exited(status, exitval_tracee); 29131.1Skamil 29141.1Skamil msg_close(&parent_tracer); 29151.1Skamil msg_close(&parent_tracee); 29161.1Skamil} 29171.1Skamil 29181.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 29191.61SkreATF_TC(test); \ 29201.61SkreATF_TC_HEAD(test, tc) \ 29211.61Skre{ \ 29221.61Skre atf_tc_set_md_var(tc, "descr", \ 29231.61Skre "Assert that tracee sees its original parent when being traced " \ 29241.61Skre "(check " descr ")"); \ 29251.61Skre} \ 29261.61Skre \ 29271.61SkreATF_TC_BODY(test, tc) \ 29281.61Skre{ \ 29291.61Skre \ 29301.61Skre tracee_sees_its_original_parent(type); \ 29311.1Skamil} 29321.1Skamil 29331.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29341.51Skamil tracee_sees_its_original_parent_getppid, 29351.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29361.51Skamil "getppid(2)"); 29371.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29381.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29391.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29401.51Skamil "sysctl(3) and kinfo_proc2"); 29411.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29421.51Skamil tracee_sees_its_original_parent_procfs_status, 29431.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29441.51Skamil "the status file in procfs"); 29451.1Skamil#endif 29461.1Skamil 29471.51Skamil/// ---------------------------------------------------------------------------- 29481.1Skamil 29491.53Skamilstatic void 29501.53Skamileventmask_preserved(int event) 29511.1Skamil{ 29521.1Skamil const int exitval = 5; 29531.1Skamil const int sigval = SIGSTOP; 29541.1Skamil pid_t child, wpid; 29551.1Skamil#if defined(TWAIT_HAVE_STATUS) 29561.1Skamil int status; 29571.1Skamil#endif 29581.1Skamil ptrace_event_t set_event, get_event; 29591.1Skamil const int len = sizeof(ptrace_event_t); 29601.1Skamil 29611.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29621.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29631.1Skamil if (child == 0) { 29641.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29651.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29661.1Skamil 29671.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29681.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29691.1Skamil 29701.13Schristos DPRINTF("Before exiting of the child process\n"); 29711.1Skamil _exit(exitval); 29721.1Skamil } 29731.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29741.1Skamil 29751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29771.1Skamil 29781.1Skamil validate_status_stopped(status, sigval); 29791.1Skamil 29801.53Skamil set_event.pe_set_event = event; 29811.61Skre SYSCALL_REQUIRE( 29821.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29831.61Skre SYSCALL_REQUIRE( 29841.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29851.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29861.125Skamil get_event.pe_set_event); 29871.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29881.1Skamil 29891.13Schristos DPRINTF("Before resuming the child process where it left off and " 29901.1Skamil "without signal to be sent\n"); 29911.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29921.1Skamil 29931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29951.1Skamil 29961.1Skamil validate_status_exited(status, exitval); 29971.1Skamil 29981.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29991.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 30001.1Skamil} 30011.1Skamil 30021.61Skre#define EVENTMASK_PRESERVED(test, event) \ 30031.61SkreATF_TC(test); \ 30041.61SkreATF_TC_HEAD(test, tc) \ 30051.61Skre{ \ 30061.61Skre atf_tc_set_md_var(tc, "descr", \ 30071.61Skre "Verify that eventmask " #event " is preserved"); \ 30081.61Skre} \ 30091.61Skre \ 30101.61SkreATF_TC_BODY(test, tc) \ 30111.61Skre{ \ 30121.61Skre \ 30131.61Skre eventmask_preserved(event); \ 30141.1Skamil} 30151.1Skamil 30161.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 30171.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 30181.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 30191.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 30201.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 30211.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 30221.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 30231.1Skamil 30241.53Skamil/// ---------------------------------------------------------------------------- 30251.1Skamil 30261.28Skamilstatic void 30271.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 30281.105Skamil bool trackvforkdone) 30291.1Skamil{ 30301.1Skamil const int exitval = 5; 30311.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30321.1Skamil const int sigval = SIGSTOP; 30331.31Skamil pid_t child, child2 = 0, wpid; 30341.1Skamil#if defined(TWAIT_HAVE_STATUS) 30351.1Skamil int status; 30361.1Skamil#endif 30371.1Skamil ptrace_state_t state; 30381.1Skamil const int slen = sizeof(state); 30391.1Skamil ptrace_event_t event; 30401.1Skamil const int elen = sizeof(event); 30411.1Skamil 30421.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30431.124Skamil 30441.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30451.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30461.1Skamil if (child == 0) { 30471.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30481.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30491.1Skamil 30501.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30511.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30521.1Skamil 30531.125Skamil if (strcmp(fn, "spawn") == 0) { 30541.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30551.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30561.125Skamil } else { 30571.125Skamil if (strcmp(fn, "fork") == 0) { 30581.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30591.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30601.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30611.125Skamil } 30621.1Skamil 30631.124Skamil if (child2 == 0) 30641.124Skamil _exit(exitval2); 30651.124Skamil } 30661.1Skamil FORKEE_REQUIRE_SUCCESS 30671.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30681.1Skamil 30691.1Skamil forkee_status_exited(status, exitval2); 30701.1Skamil 30711.13Schristos DPRINTF("Before exiting of the child process\n"); 30721.1Skamil _exit(exitval); 30731.1Skamil } 30741.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30751.1Skamil 30761.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30781.1Skamil 30791.1Skamil validate_status_stopped(status, sigval); 30801.1Skamil 30811.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30821.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30831.61Skre trackfork ? "|PTRACE_FORK" : "", 30841.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30851.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30861.30Skamil event.pe_set_event = 0; 30871.125Skamil if (trackspawn) 30881.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30891.30Skamil if (trackfork) 30901.30Skamil event.pe_set_event |= PTRACE_FORK; 30911.30Skamil if (trackvfork) 30921.30Skamil event.pe_set_event |= PTRACE_VFORK; 30931.30Skamil if (trackvforkdone) 30941.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30951.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30961.1Skamil 30971.13Schristos DPRINTF("Before resuming the child process where it left off and " 30981.1Skamil "without signal to be sent\n"); 30991.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31001.1Skamil 31011.29Skamil#if defined(TWAIT_HAVE_PID) 31021.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31031.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31041.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31051.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31061.61Skre child); 31071.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 31081.61Skre child); 31091.1Skamil 31101.29Skamil validate_status_stopped(status, SIGTRAP); 31111.1Skamil 31121.61Skre SYSCALL_REQUIRE( 31131.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31141.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31151.125Skamil ATF_REQUIRE_EQ( 31161.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31171.125Skamil PTRACE_POSIX_SPAWN); 31181.125Skamil } 31191.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31201.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31211.30Skamil PTRACE_FORK); 31221.30Skamil } 31231.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31241.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31251.30Skamil PTRACE_VFORK); 31261.30Skamil } 31271.29Skamil 31281.29Skamil child2 = state.pe_other_pid; 31291.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31301.29Skamil 31311.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31321.61Skre "%d\n", TWAIT_FNAME, child2, child); 31331.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31341.29Skamil child2); 31351.1Skamil 31361.29Skamil validate_status_stopped(status, SIGTRAP); 31371.1Skamil 31381.61Skre SYSCALL_REQUIRE( 31391.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31401.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31411.125Skamil ATF_REQUIRE_EQ( 31421.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31431.125Skamil PTRACE_POSIX_SPAWN); 31441.125Skamil } 31451.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31461.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31471.30Skamil PTRACE_FORK); 31481.30Skamil } 31491.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31501.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31511.30Skamil PTRACE_VFORK); 31521.30Skamil } 31531.30Skamil 31541.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31551.29Skamil 31561.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31571.29Skamil "and without signal to be sent\n"); 31581.61Skre SYSCALL_REQUIRE( 31591.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31601.29Skamil 31611.29Skamil DPRINTF("Before resuming the child process where it left off " 31621.61Skre "and without signal to be sent\n"); 31631.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31641.30Skamil } 31651.30Skamil#endif 31661.30Skamil 31671.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31681.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31691.61Skre child); 31701.61Skre TWAIT_REQUIRE_SUCCESS( 31711.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31721.30Skamil 31731.30Skamil validate_status_stopped(status, SIGTRAP); 31741.30Skamil 31751.61Skre SYSCALL_REQUIRE( 31761.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31771.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31781.30Skamil 31791.30Skamil child2 = state.pe_other_pid; 31801.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31811.61Skre child2); 31821.30Skamil 31831.30Skamil DPRINTF("Before resuming the child process where it left off " 31841.61Skre "and without signal to be sent\n"); 31851.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31861.30Skamil } 31871.29Skamil 31881.30Skamil#if defined(TWAIT_HAVE_PID) 31891.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31901.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31911.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31921.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31931.61Skre "\n", TWAIT_FNAME); 31941.61Skre TWAIT_REQUIRE_SUCCESS( 31951.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31961.29Skamil 31971.29Skamil validate_status_exited(status, exitval2); 31981.29Skamil 31991.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 32001.61Skre "process\n", TWAIT_FNAME); 32011.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 32021.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 32031.29Skamil } 32041.29Skamil#endif 32051.1Skamil 32061.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 32071.1Skamil "SIGCHLD\n", TWAIT_FNAME); 32081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32091.1Skamil 32101.1Skamil validate_status_stopped(status, SIGCHLD); 32111.1Skamil 32121.13Schristos DPRINTF("Before resuming the child process where it left off and " 32131.1Skamil "without signal to be sent\n"); 32141.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 32151.1Skamil 32161.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 32171.1Skamil TWAIT_FNAME); 32181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32191.1Skamil 32201.1Skamil validate_status_exited(status, exitval); 32211.1Skamil 32221.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 32231.1Skamil TWAIT_FNAME); 32241.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32251.1Skamil} 32261.28Skamil 32271.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 32281.61SkreATF_TC(name); \ 32291.61SkreATF_TC_HEAD(name, tc) \ 32301.61Skre{ \ 32311.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32321.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32331.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32341.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32351.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32361.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32371.61Skre} \ 32381.61Skre \ 32391.61SkreATF_TC_BODY(name, tc) \ 32401.61Skre{ \ 32411.61Skre \ 32421.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32431.32Skamil} 32441.32Skamil 32451.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32461.31Skamil#if defined(TWAIT_HAVE_PID) 32471.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32481.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32491.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32501.31Skamil#endif 32511.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32521.31Skamil#if defined(TWAIT_HAVE_PID) 32531.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32541.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32551.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32561.125Skamil#endif 32571.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32581.125Skamil#if defined(TWAIT_HAVE_PID) 32591.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32601.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32611.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32621.125Skamil#endif 32631.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32641.125Skamil#if defined(TWAIT_HAVE_PID) 32651.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32661.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32671.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32681.31Skamil#endif 32691.1Skamil 32701.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32711.31Skamil#if defined(TWAIT_HAVE_PID) 32721.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32731.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32741.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32751.31Skamil#endif 32761.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32771.31Skamil#if defined(TWAIT_HAVE_PID) 32781.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32791.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32801.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32811.31Skamil#endif 32821.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32831.125Skamil#if defined(TWAIT_HAVE_PID) 32841.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32851.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32861.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32871.110Skamil#endif 32881.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32891.124Skamil#if defined(TWAIT_HAVE_PID) 32901.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32911.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32921.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32931.124Skamil#endif 32941.125Skamil 32951.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32961.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32971.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32981.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32991.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 33001.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 33011.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 33021.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 33031.124Skamil#if defined(TWAIT_HAVE_PID) 33041.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 33051.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 33061.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 33071.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 33081.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 33091.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 33101.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 33111.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 33121.124Skamil#endif 33131.124Skamil 33141.54Skamil/// ---------------------------------------------------------------------------- 33151.31Skamil 33161.116Skamil#if defined(TWAIT_HAVE_PID) 33171.116Skamilstatic void 33181.149Skamilunrelated_tracer_fork_body(const char *fn, bool trackspawn, bool trackfork, 33191.149Skamil bool trackvfork, bool trackvforkdone) 33201.149Skamil{ 33211.149Skamil const int sigval = SIGSTOP; 33221.149Skamil struct msg_fds parent_tracee, parent_tracer; 33231.149Skamil const int exitval = 10; 33241.149Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 33251.149Skamil pid_t tracee, tracer, wpid; 33261.149Skamil pid_t tracee2 = 0; 33271.149Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 33281.149Skamil#if defined(TWAIT_HAVE_STATUS) 33291.149Skamil int status; 33301.149Skamil#endif 33311.149Skamil 33321.149Skamil struct ptrace_siginfo info; 33331.149Skamil ptrace_state_t state; 33341.149Skamil const int slen = sizeof(state); 33351.149Skamil ptrace_event_t event; 33361.149Skamil const int elen = sizeof(event); 33371.149Skamil 33381.149Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33391.149Skamil 33401.149Skamil DPRINTF("Spawn tracee\n"); 33411.149Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 33421.149Skamil tracee = atf_utils_fork(); 33431.149Skamil if (tracee == 0) { 33441.149Skamil // Wait for parent to let us crash 33451.149Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 33461.149Skamil 33471.149Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33481.149Skamil FORKEE_ASSERT(raise(sigval) == 0); 33491.149Skamil 33501.149Skamil if (strcmp(fn, "spawn") == 0) { 33511.149Skamil FORKEE_ASSERT_EQ(posix_spawn(&tracee2, 33521.149Skamil arg[0], NULL, NULL, arg, NULL), 0); 33531.149Skamil } else { 33541.149Skamil if (strcmp(fn, "fork") == 0) { 33551.149Skamil FORKEE_ASSERT((tracee2 = fork()) != -1); 33561.149Skamil } else if (strcmp(fn, "vfork") == 0) { 33571.149Skamil FORKEE_ASSERT((tracee2 = vfork()) != -1); 33581.149Skamil } 33591.149Skamil 33601.149Skamil if (tracee2 == 0) 33611.149Skamil _exit(exitval2); 33621.149Skamil } 33631.149Skamil FORKEE_REQUIRE_SUCCESS 33641.149Skamil (wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 33651.149Skamil 33661.149Skamil forkee_status_exited(status, exitval2); 33671.149Skamil 33681.149Skamil DPRINTF("Before exiting of the child process\n"); 33691.149Skamil _exit(exitval); 33701.149Skamil } 33711.149Skamil 33721.149Skamil DPRINTF("Spawn debugger\n"); 33731.149Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 33741.149Skamil tracer = atf_utils_fork(); 33751.149Skamil if (tracer == 0) { 33761.149Skamil /* Fork again and drop parent to reattach to PID 1 */ 33771.149Skamil tracer = atf_utils_fork(); 33781.149Skamil if (tracer != 0) 33791.149Skamil _exit(exitval); 33801.149Skamil 33811.149Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 33821.149Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 33831.149Skamil 33841.149Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 33851.149Skamil FORKEE_REQUIRE_SUCCESS( 33861.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 33871.149Skamil 33881.149Skamil forkee_status_stopped(status, SIGSTOP); 33891.149Skamil 33901.149Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 33911.149Skamil "traced process\n"); 33921.149Skamil SYSCALL_REQUIRE( 33931.149Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 33941.149Skamil 33951.149Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 33961.149Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 33971.149Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 33981.149Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 33991.149Skamil 34001.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 34011.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 34021.149Skamil 34031.149Skamil /* Resume tracee with PT_CONTINUE */ 34041.149Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 34051.149Skamil 34061.149Skamil /* Inform parent that tracer has attached to tracee */ 34071.149Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 34081.149Skamil 34091.149Skamil /* Wait for parent to tell use that tracee should have exited */ 34101.149Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 34111.149Skamil 34121.149Skamil /* Wait for tracee and assert that it exited */ 34131.149Skamil FORKEE_REQUIRE_SUCCESS( 34141.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 34151.149Skamil 34161.149Skamil forkee_status_stopped(status, sigval); 34171.149Skamil 34181.149Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 34191.149Skamil "traced process\n"); 34201.149Skamil SYSCALL_REQUIRE( 34211.149Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 34221.149Skamil 34231.149Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 34241.149Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 34251.149Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 34261.149Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 34271.149Skamil 34281.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 34291.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 34301.149Skamil 34311.149Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 34321.149Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 34331.149Skamil trackfork ? "|PTRACE_FORK" : "", 34341.149Skamil trackvfork ? "|PTRACE_VFORK" : "", 34351.149Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", tracee); 34361.149Skamil event.pe_set_event = 0; 34371.149Skamil if (trackspawn) 34381.149Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 34391.149Skamil if (trackfork) 34401.149Skamil event.pe_set_event |= PTRACE_FORK; 34411.149Skamil if (trackvfork) 34421.149Skamil event.pe_set_event |= PTRACE_VFORK; 34431.149Skamil if (trackvforkdone) 34441.149Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 34451.149Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, tracee, &event, elen) 34461.149Skamil != -1); 34471.149Skamil 34481.149Skamil DPRINTF("Before resuming the child process where it left off " 34491.149Skamil "and without signal to be sent\n"); 34501.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 34511.149Skamil 34521.149Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 34531.149Skamil (trackfork && strcmp(fn, "fork") == 0) || 34541.149Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 34551.149Skamil DPRINTF("Before calling %s() for the tracee %d\n", TWAIT_FNAME, 34561.149Skamil tracee); 34571.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), 34581.149Skamil tracee); 34591.149Skamil 34601.149Skamil validate_status_stopped(status, SIGTRAP); 34611.149Skamil 34621.149Skamil SYSCALL_REQUIRE( 34631.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 34641.149Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 34651.149Skamil ATF_REQUIRE_EQ( 34661.149Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 34671.149Skamil PTRACE_POSIX_SPAWN); 34681.149Skamil } 34691.149Skamil if (trackfork && strcmp(fn, "fork") == 0) { 34701.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 34711.149Skamil PTRACE_FORK); 34721.149Skamil } 34731.149Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 34741.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 34751.149Skamil PTRACE_VFORK); 34761.149Skamil } 34771.149Skamil 34781.149Skamil tracee2 = state.pe_other_pid; 34791.149Skamil DPRINTF("Reported ptrace event with forkee %d\n", tracee2); 34801.149Skamil 34811.149Skamil DPRINTF("Before calling %s() for the forkee %d of the tracee " 34821.149Skamil "%d\n", TWAIT_FNAME, tracee2, tracee); 34831.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), 34841.149Skamil tracee2); 34851.149Skamil 34861.149Skamil validate_status_stopped(status, SIGTRAP); 34871.149Skamil 34881.149Skamil SYSCALL_REQUIRE( 34891.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee2, &state, slen) != -1); 34901.149Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 34911.149Skamil ATF_REQUIRE_EQ( 34921.149Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 34931.149Skamil PTRACE_POSIX_SPAWN); 34941.149Skamil } 34951.149Skamil if (trackfork && strcmp(fn, "fork") == 0) { 34961.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 34971.149Skamil PTRACE_FORK); 34981.149Skamil } 34991.149Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 35001.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 35011.149Skamil PTRACE_VFORK); 35021.149Skamil } 35031.149Skamil 35041.149Skamil ATF_REQUIRE_EQ(state.pe_other_pid, tracee); 35051.149Skamil 35061.149Skamil DPRINTF("Before resuming the forkee process where it left off " 35071.149Skamil "and without signal to be sent\n"); 35081.149Skamil SYSCALL_REQUIRE( 35091.149Skamil ptrace(PT_CONTINUE, tracee2, (void *)1, 0) != -1); 35101.149Skamil 35111.149Skamil DPRINTF("Before resuming the tracee process where it left off " 35121.149Skamil "and without signal to be sent\n"); 35131.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 35141.149Skamil } 35151.149Skamil 35161.149Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 35171.149Skamil DPRINTF("Before calling %s() for the tracee %d\n", TWAIT_FNAME, 35181.149Skamil tracee); 35191.149Skamil TWAIT_REQUIRE_SUCCESS( 35201.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35211.149Skamil 35221.149Skamil validate_status_stopped(status, SIGTRAP); 35231.149Skamil 35241.149Skamil SYSCALL_REQUIRE( 35251.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 35261.149Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 35271.149Skamil 35281.149Skamil tracee2 = state.pe_other_pid; 35291.149Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 35301.149Skamil tracee2); 35311.149Skamil 35321.149Skamil DPRINTF("Before resuming the tracee process where it left off " 35331.149Skamil "and without signal to be sent\n"); 35341.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 35351.149Skamil } 35361.149Skamil 35371.149Skamil 35381.149Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 35391.149Skamil (trackfork && strcmp(fn, "fork") == 0) || 35401.149Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 35411.149Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 35421.149Skamil "\n", TWAIT_FNAME); 35431.149Skamil TWAIT_REQUIRE_SUCCESS( 35441.149Skamil wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 35451.149Skamil 35461.149Skamil validate_status_exited(status, exitval2); 35471.149Skamil 35481.149Skamil DPRINTF("Before calling %s() for the forkee - expected no " 35491.149Skamil "process\n", TWAIT_FNAME); 35501.149Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 35511.149Skamil wpid = TWAIT_GENERIC(tracee2, &status, 0)); 35521.149Skamil } 35531.149Skamil 35541.149Skamil DPRINTF("Before calling %s() for the tracee - expected stopped " 35551.149Skamil "SIGCHLD\n", TWAIT_FNAME); 35561.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35571.149Skamil 35581.149Skamil validate_status_stopped(status, SIGCHLD); 35591.149Skamil 35601.149Skamil DPRINTF("Before resuming the tracee process where it left off and " 35611.149Skamil "without signal to be sent\n"); 35621.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 35631.149Skamil 35641.149Skamil DPRINTF("Before calling %s() for the tracee - expected exited\n", 35651.149Skamil TWAIT_FNAME); 35661.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35671.149Skamil 35681.149Skamil validate_status_exited(status, exitval); 35691.149Skamil 35701.149Skamil /* Inform parent that tracer is exiting normally */ 35711.149Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 35721.149Skamil 35731.149Skamil DPRINTF("Before exiting of the tracer process\n"); 35741.149Skamil _exit(0 /* collect by initproc */); 35751.149Skamil } 35761.149Skamil 35771.149Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 35781.149Skamil "calling %s()\n", TWAIT_FNAME); 35791.149Skamil TWAIT_REQUIRE_SUCCESS( 35801.149Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 35811.149Skamil 35821.149Skamil validate_status_exited(status, exitval); 35831.149Skamil 35841.149Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 35851.149Skamil TWAIT_FNAME); 35861.149Skamil TWAIT_REQUIRE_SUCCESS( 35871.149Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 35881.149Skamil 35891.149Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 35901.149Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 35911.149Skamil 35921.149Skamil DPRINTF("Resume the tracee and let it crash\n"); 35931.149Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 35941.149Skamil 35951.149Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 35961.149Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 35971.149Skamil 35981.149Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 35991.149Skamil TWAIT_FNAME); 36001.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 36011.149Skamil 36021.149Skamil validate_status_exited(status, exitval); 36031.149Skamil 36041.149Skamil DPRINTF("Await normal exit of tracer\n"); 36051.149Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 36061.149Skamil 36071.149Skamil msg_close(&parent_tracer); 36081.149Skamil msg_close(&parent_tracee); 36091.149Skamil} 36101.149Skamil 36111.149Skamil#define UNRELATED_TRACER_FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone)\ 36121.149SkamilATF_TC(name); \ 36131.149SkamilATF_TC_HEAD(name, tc) \ 36141.149Skamil{ \ 36151.149Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 36161.149Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 36171.149Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 36181.149Skamil tfork ? "|PTRACE_FORK" : "", \ 36191.149Skamil tvfork ? "|PTRACE_VFORK" : "", \ 36201.149Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 36211.149Skamil} \ 36221.149Skamil \ 36231.149SkamilATF_TC_BODY(name, tc) \ 36241.149Skamil{ \ 36251.149Skamil \ 36261.149Skamil unrelated_tracer_fork_body(fun, tspawn, tfork, tvfork, \ 36271.149Skamil tvforkdone); \ 36281.149Skamil} 36291.149Skamil 36301.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork1, "fork", false, false, false, false) 36311.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork2, "fork", false, true, false, false) 36321.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork3, "fork", false, false, true, false) 36331.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork4, "fork", false, true, true, false) 36341.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork5, "fork", false, false, false, true) 36351.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork6, "fork", false, true, false, true) 36361.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork7, "fork", false, false, true, true) 36371.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork8, "fork", false, true, true, true) 36381.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork9, "fork", true, false, false, false) 36391.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork10, "fork", true, true, false, false) 36401.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork11, "fork", true, false, true, false) 36411.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork12, "fork", true, true, true, false) 36421.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork13, "fork", true, false, false, true) 36431.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork14, "fork", true, true, false, true) 36441.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork15, "fork", true, false, true, true) 36451.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork16, "fork", true, true, true, true) 36461.149Skamil 36471.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork1, "vfork", false, false, false, false) 36481.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork2, "vfork", false, true, false, false) 36491.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork3, "vfork", false, false, true, false) 36501.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork4, "vfork", false, true, true, false) 36511.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork5, "vfork", false, false, false, true) 36521.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork6, "vfork", false, true, false, true) 36531.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork7, "vfork", false, false, true, true) 36541.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork8, "vfork", false, true, true, true) 36551.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork9, "vfork", true, false, false, false) 36561.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork10, "vfork", true, true, false, false) 36571.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork11, "vfork", true, false, true, false) 36581.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork12, "vfork", true, true, true, false) 36591.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork13, "vfork", true, false, false, true) 36601.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork14, "vfork", true, true, false, true) 36611.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork15, "vfork", true, false, true, true) 36621.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork16, "vfork", true, true, true, true) 36631.149Skamil 36641.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn1, "spawn", false, false, false, false) 36651.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn2, "spawn", false, true, false, false) 36661.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn3, "spawn", false, false, true, false) 36671.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn4, "spawn", false, true, true, false) 36681.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn5, "spawn", false, false, false, true) 36691.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn6, "spawn", false, true, false, true) 36701.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn7, "spawn", false, false, true, true) 36711.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn8, "spawn", false, true, true, true) 36721.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn9, "spawn", true, false, false, false) 36731.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn10, "spawn", true, true, false, false) 36741.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn11, "spawn", true, false, true, false) 36751.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn12, "spawn", true, true, true, false) 36761.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn13, "spawn", true, false, false, true) 36771.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn14, "spawn", true, true, false, true) 36781.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn15, "spawn", true, false, true, true) 36791.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn16, "spawn", true, true, true, true) 36801.149Skamil#endif 36811.149Skamil 36821.149Skamil/// ---------------------------------------------------------------------------- 36831.149Skamil 36841.149Skamil#if defined(TWAIT_HAVE_PID) 36851.149Skamilstatic void 36861.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 36871.116Skamil{ 36881.116Skamil const int exitval = 5; 36891.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 36901.116Skamil const int sigval = SIGSTOP; 36911.116Skamil pid_t child, child2 = 0, wpid; 36921.116Skamil#if defined(TWAIT_HAVE_STATUS) 36931.116Skamil int status; 36941.116Skamil#endif 36951.116Skamil ptrace_state_t state; 36961.116Skamil const int slen = sizeof(state); 36971.116Skamil ptrace_event_t event; 36981.116Skamil const int elen = sizeof(event); 36991.116Skamil 37001.116Skamil int op; 37011.116Skamil 37021.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 37031.116Skamil 37041.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 37051.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 37061.116Skamil if (child == 0) { 37071.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 37081.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 37091.116Skamil 37101.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37111.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 37121.116Skamil 37131.126Skamil if (strcmp(fn, "spawn") == 0) { 37141.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 37151.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 37161.126Skamil } else { 37171.126Skamil if (strcmp(fn, "fork") == 0) { 37181.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 37191.126Skamil } else { 37201.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 37211.126Skamil } 37221.116Skamil 37231.126Skamil if (child2 == 0) 37241.126Skamil _exit(exitval2); 37251.126Skamil } 37261.116Skamil 37271.116Skamil FORKEE_REQUIRE_SUCCESS 37281.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 37291.116Skamil 37301.116Skamil forkee_status_exited(status, exitval2); 37311.116Skamil 37321.116Skamil DPRINTF("Before exiting of the child process\n"); 37331.116Skamil _exit(exitval); 37341.116Skamil } 37351.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37361.116Skamil 37371.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37381.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37391.116Skamil 37401.116Skamil validate_status_stopped(status, sigval); 37411.116Skamil 37421.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 37431.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 37441.126Skamil | PTRACE_VFORK_DONE; 37451.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 37461.116Skamil 37471.116Skamil DPRINTF("Before resuming the child process where it left off and " 37481.116Skamil "without signal to be sent\n"); 37491.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 37501.116Skamil 37511.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 37521.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37531.116Skamil 37541.116Skamil validate_status_stopped(status, SIGTRAP); 37551.116Skamil 37561.116Skamil SYSCALL_REQUIRE( 37571.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 37581.126Skamil 37591.126Skamil if (strcmp(fn, "spawn") == 0) 37601.126Skamil op = PTRACE_POSIX_SPAWN; 37611.126Skamil else if (strcmp(fn, "fork") == 0) 37621.126Skamil op = PTRACE_FORK; 37631.126Skamil else 37641.126Skamil op = PTRACE_VFORK; 37651.126Skamil 37661.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 37671.116Skamil 37681.116Skamil child2 = state.pe_other_pid; 37691.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 37701.116Skamil 37711.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 37721.126Skamil strcmp(fn, "vfork") == 0) 37731.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 37741.116Skamil else 37751.116Skamil op = PT_CONTINUE; 37761.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 37771.116Skamil 37781.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 37791.116Skamil TWAIT_FNAME, child2, child); 37801.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 37811.116Skamil 37821.116Skamil validate_status_stopped(status, SIGTRAP); 37831.116Skamil 37841.116Skamil SYSCALL_REQUIRE( 37851.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 37861.126Skamil if (strcmp(fn, "spawn") == 0) 37871.126Skamil op = PTRACE_POSIX_SPAWN; 37881.126Skamil else if (strcmp(fn, "fork") == 0) 37891.126Skamil op = PTRACE_FORK; 37901.126Skamil else 37911.126Skamil op = PTRACE_VFORK; 37921.126Skamil 37931.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 37941.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 37951.116Skamil 37961.116Skamil DPRINTF("Before resuming the forkee process where it left off " 37971.116Skamil "and without signal to be sent\n"); 37981.116Skamil SYSCALL_REQUIRE( 37991.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 38001.116Skamil 38011.126Skamil if (strcmp(fn, "vforkdone") == 0) { 38021.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 38031.116Skamil child); 38041.116Skamil TWAIT_REQUIRE_SUCCESS( 38051.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 38061.116Skamil 38071.116Skamil validate_status_stopped(status, SIGTRAP); 38081.116Skamil 38091.116Skamil SYSCALL_REQUIRE( 38101.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 38111.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 38121.116Skamil 38131.116Skamil child2 = state.pe_other_pid; 38141.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 38151.116Skamil child2); 38161.116Skamil 38171.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 38181.116Skamil DPRINTF("Before resuming the child process where it left off " 38191.116Skamil "and without signal to be sent\n"); 38201.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 38211.116Skamil } 38221.116Skamil 38231.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 38241.116Skamil TWAIT_FNAME); 38251.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 38261.116Skamil 38271.116Skamil validate_status_exited(status, exitval2); 38281.116Skamil 38291.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 38301.116Skamil TWAIT_FNAME); 38311.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 38321.116Skamil 38331.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 38341.116Skamil TWAIT_FNAME); 38351.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38361.116Skamil 38371.116Skamil if (kill_process) { 38381.116Skamil validate_status_signaled(status, SIGKILL, 0); 38391.116Skamil } else { 38401.116Skamil validate_status_exited(status, exitval); 38411.116Skamil } 38421.116Skamil 38431.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 38441.116Skamil TWAIT_FNAME); 38451.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 38461.116Skamil} 38471.116Skamil 38481.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 38491.116SkamilATF_TC(name); \ 38501.116SkamilATF_TC_HEAD(name, tc) \ 38511.116Skamil{ \ 38521.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 38531.126Skamil kprocess ? "killed" : "detached"); \ 38541.116Skamil} \ 38551.116Skamil \ 38561.116SkamilATF_TC_BODY(name, tc) \ 38571.116Skamil{ \ 38581.116Skamil \ 38591.126Skamil fork_detach_forker_body(event, kprocess); \ 38601.116Skamil} 38611.116Skamil 38621.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 38631.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 38641.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 38651.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 38661.126Skamil 38671.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 38681.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 38691.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 38701.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 38711.116Skamil#endif 38721.116Skamil 38731.116Skamil/// ---------------------------------------------------------------------------- 38741.116Skamil 38751.150Skamil#if defined(TWAIT_HAVE_PID) 38761.150Skamilstatic void 38771.150Skamilunrelated_tracer_fork_detach_forker_body(const char *fn, bool kill_process) 38781.150Skamil{ 38791.150Skamil const int sigval = SIGSTOP; 38801.150Skamil struct msg_fds parent_tracee, parent_tracer; 38811.150Skamil const int exitval = 10; 38821.150Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 38831.150Skamil pid_t tracee, tracer, wpid; 38841.150Skamil pid_t tracee2 = 0; 38851.150Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 38861.150Skamil#if defined(TWAIT_HAVE_STATUS) 38871.150Skamil int status; 38881.150Skamil#endif 38891.150Skamil int op; 38901.150Skamil 38911.150Skamil struct ptrace_siginfo info; 38921.150Skamil ptrace_state_t state; 38931.150Skamil const int slen = sizeof(state); 38941.150Skamil ptrace_event_t event; 38951.150Skamil const int elen = sizeof(event); 38961.150Skamil 38971.150Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 38981.150Skamil 38991.150Skamil DPRINTF("Spawn tracee\n"); 39001.150Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 39011.150Skamil tracee = atf_utils_fork(); 39021.150Skamil if (tracee == 0) { 39031.150Skamil // Wait for parent to let us crash 39041.150Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 39051.150Skamil 39061.150Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 39071.150Skamil FORKEE_ASSERT(raise(sigval) == 0); 39081.150Skamil 39091.150Skamil if (strcmp(fn, "spawn") == 0) { 39101.150Skamil FORKEE_ASSERT_EQ(posix_spawn(&tracee2, 39111.150Skamil arg[0], NULL, NULL, arg, NULL), 0); 39121.150Skamil } else { 39131.150Skamil if (strcmp(fn, "fork") == 0) { 39141.150Skamil FORKEE_ASSERT((tracee2 = fork()) != -1); 39151.150Skamil } else { 39161.150Skamil FORKEE_ASSERT((tracee2 = vfork()) != -1); 39171.150Skamil } 39181.150Skamil 39191.150Skamil if (tracee2 == 0) 39201.150Skamil _exit(exitval2); 39211.150Skamil } 39221.150Skamil 39231.150Skamil FORKEE_REQUIRE_SUCCESS 39241.150Skamil (wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 39251.150Skamil 39261.150Skamil forkee_status_exited(status, exitval2); 39271.150Skamil 39281.150Skamil DPRINTF("Before exiting of the child process\n"); 39291.150Skamil _exit(exitval); 39301.150Skamil } 39311.150Skamil 39321.150Skamil DPRINTF("Spawn debugger\n"); 39331.150Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 39341.150Skamil tracer = atf_utils_fork(); 39351.150Skamil if (tracer == 0) { 39361.150Skamil /* Fork again and drop parent to reattach to PID 1 */ 39371.150Skamil tracer = atf_utils_fork(); 39381.150Skamil if (tracer != 0) 39391.150Skamil _exit(exitval); 39401.150Skamil 39411.150Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 39421.150Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 39431.150Skamil 39441.150Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 39451.150Skamil FORKEE_REQUIRE_SUCCESS( 39461.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 39471.150Skamil 39481.150Skamil forkee_status_stopped(status, SIGSTOP); 39491.150Skamil 39501.150Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 39511.150Skamil "traced process\n"); 39521.150Skamil SYSCALL_REQUIRE( 39531.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 39541.150Skamil 39551.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39561.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39571.150Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 39581.150Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 39591.150Skamil 39601.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 39611.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 39621.150Skamil 39631.150Skamil /* Resume tracee with PT_CONTINUE */ 39641.150Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 39651.150Skamil 39661.150Skamil /* Inform parent that tracer has attached to tracee */ 39671.150Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 39681.150Skamil 39691.150Skamil /* Wait for parent to tell use that tracee should have exited */ 39701.150Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 39711.150Skamil 39721.150Skamil /* Wait for tracee and assert that it exited */ 39731.150Skamil FORKEE_REQUIRE_SUCCESS( 39741.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 39751.150Skamil 39761.150Skamil forkee_status_stopped(status, sigval); 39771.150Skamil 39781.150Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 39791.150Skamil "traced process\n"); 39801.150Skamil SYSCALL_REQUIRE( 39811.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 39821.150Skamil 39831.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39841.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39851.150Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 39861.150Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 39871.150Skamil 39881.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 39891.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 39901.150Skamil 39911.150Skamil DPRINTF("Set EVENT_MASK for the child %d\n", tracee); 39921.150Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 39931.150Skamil | PTRACE_VFORK_DONE; 39941.150Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, tracee, &event, elen) != -1); 39951.150Skamil 39961.150Skamil DPRINTF("Before resuming the child process where it left off and " 39971.150Skamil "without signal to be sent\n"); 39981.150Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 39991.150Skamil 40001.150Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, tracee); 40011.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40021.150Skamil 40031.150Skamil validate_status_stopped(status, SIGTRAP); 40041.150Skamil 40051.150Skamil SYSCALL_REQUIRE( 40061.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 40071.150Skamil 40081.150Skamil if (strcmp(fn, "spawn") == 0) 40091.150Skamil op = PTRACE_POSIX_SPAWN; 40101.150Skamil else if (strcmp(fn, "fork") == 0) 40111.150Skamil op = PTRACE_FORK; 40121.150Skamil else 40131.150Skamil op = PTRACE_VFORK; 40141.150Skamil 40151.150Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 40161.150Skamil 40171.150Skamil tracee2 = state.pe_other_pid; 40181.150Skamil DPRINTF("Reported ptrace event with forkee %d\n", tracee2); 40191.150Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 40201.150Skamil strcmp(fn, "vfork") == 0) 40211.150Skamil op = kill_process ? PT_KILL : PT_DETACH; 40221.150Skamil else 40231.150Skamil op = PT_CONTINUE; 40241.150Skamil SYSCALL_REQUIRE(ptrace(op, tracee, (void *)1, 0) != -1); 40251.150Skamil 40261.150Skamil DPRINTF("Before calling %s() for the forkee %d of the tracee %d\n", 40271.150Skamil TWAIT_FNAME, tracee2, tracee); 40281.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 40291.150Skamil 40301.150Skamil validate_status_stopped(status, SIGTRAP); 40311.150Skamil 40321.150Skamil SYSCALL_REQUIRE( 40331.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee2, &state, slen) != -1); 40341.150Skamil if (strcmp(fn, "spawn") == 0) 40351.150Skamil op = PTRACE_POSIX_SPAWN; 40361.150Skamil else if (strcmp(fn, "fork") == 0) 40371.150Skamil op = PTRACE_FORK; 40381.150Skamil else 40391.150Skamil op = PTRACE_VFORK; 40401.150Skamil 40411.150Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 40421.150Skamil ATF_REQUIRE_EQ(state.pe_other_pid, tracee); 40431.150Skamil 40441.150Skamil DPRINTF("Before resuming the forkee process where it left off " 40451.150Skamil "and without signal to be sent\n"); 40461.150Skamil SYSCALL_REQUIRE( 40471.150Skamil ptrace(PT_CONTINUE, tracee2, (void *)1, 0) != -1); 40481.150Skamil 40491.150Skamil if (strcmp(fn, "vforkdone") == 0) { 40501.150Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 40511.150Skamil tracee); 40521.150Skamil TWAIT_REQUIRE_SUCCESS( 40531.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40541.150Skamil 40551.150Skamil validate_status_stopped(status, SIGTRAP); 40561.150Skamil 40571.150Skamil SYSCALL_REQUIRE( 40581.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 40591.150Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 40601.150Skamil 40611.150Skamil tracee2 = state.pe_other_pid; 40621.150Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 40631.150Skamil tracee2); 40641.150Skamil 40651.150Skamil op = kill_process ? PT_KILL : PT_DETACH; 40661.150Skamil DPRINTF("Before resuming the child process where it left off " 40671.150Skamil "and without signal to be sent\n"); 40681.150Skamil SYSCALL_REQUIRE(ptrace(op, tracee, (void *)1, 0) != -1); 40691.150Skamil } 40701.150Skamil 40711.150Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 40721.150Skamil TWAIT_FNAME); 40731.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 40741.150Skamil 40751.150Skamil validate_status_exited(status, exitval2); 40761.150Skamil 40771.150Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 40781.150Skamil TWAIT_FNAME); 40791.150Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(tracee2, &status, 0)); 40801.150Skamil 40811.150Skamil if (kill_process) { 40821.150Skamil DPRINTF("Before calling %s() for the forkee - expected signaled\n", 40831.150Skamil TWAIT_FNAME); 40841.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40851.150Skamil 40861.150Skamil validate_status_signaled(status, SIGKILL, 0); 40871.150Skamil } 40881.150Skamil 40891.150Skamil /* Inform parent that tracer is exiting normally */ 40901.150Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 40911.150Skamil 40921.150Skamil DPRINTF("Before exiting of the tracer process\n"); 40931.150Skamil _exit(0 /* collect by initproc */); 40941.150Skamil } 40951.150Skamil 40961.150Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 40971.150Skamil "calling %s()\n", TWAIT_FNAME); 40981.150Skamil TWAIT_REQUIRE_SUCCESS( 40991.150Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 41001.150Skamil 41011.150Skamil validate_status_exited(status, exitval); 41021.150Skamil 41031.150Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 41041.150Skamil TWAIT_FNAME); 41051.150Skamil TWAIT_REQUIRE_SUCCESS( 41061.150Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 41071.150Skamil 41081.150Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 41091.150Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 41101.150Skamil 41111.150Skamil DPRINTF("Resume the tracee and let it crash\n"); 41121.150Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 41131.150Skamil 41141.150Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 41151.150Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 41161.150Skamil 41171.150Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 41181.150Skamil TWAIT_FNAME); 41191.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 41201.150Skamil 41211.150Skamil if (kill_process) { 41221.150Skamil validate_status_signaled(status, SIGKILL, 0); 41231.150Skamil } else { 41241.150Skamil validate_status_exited(status, exitval); 41251.150Skamil } 41261.150Skamil 41271.150Skamil DPRINTF("Await normal exit of tracer\n"); 41281.150Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 41291.150Skamil 41301.150Skamil msg_close(&parent_tracer); 41311.150Skamil msg_close(&parent_tracee); 41321.150Skamil} 41331.150Skamil 41341.150Skamil#define UNRELATED_TRACER_FORK_DETACH_FORKER(name,event,kprocess) \ 41351.150SkamilATF_TC(name); \ 41361.150SkamilATF_TC_HEAD(name, tc) \ 41371.150Skamil{ \ 41381.150Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 41391.150Skamil kprocess ? "killed" : "detached"); \ 41401.150Skamil} \ 41411.150Skamil \ 41421.150SkamilATF_TC_BODY(name, tc) \ 41431.150Skamil{ \ 41441.150Skamil \ 41451.150Skamil unrelated_tracer_fork_detach_forker_body(event, kprocess); \ 41461.150Skamil} 41471.150Skamil 41481.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_posix_spawn_detach_spawner, "spawn", false) 41491.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_fork_detach_forker, "fork", false) 41501.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_detach_vforker, "vfork", false) 41511.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_detach_vforkerdone, "vforkdone", false) 41521.150Skamil 41531.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_posix_spawn_kill_spawner, "spawn", true) 41541.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_fork_kill_forker, "fork", true) 41551.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_kill_vforker, "vfork", true) 41561.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_kill_vforkerdone, "vforkdone", true) 41571.150Skamil#endif 41581.150Skamil 41591.150Skamil/// ---------------------------------------------------------------------------- 41601.150Skamil 41611.108Skamilstatic void 41621.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 41631.108Skamil{ 41641.108Skamil const int exitval = 5; 41651.108Skamil const int exitval2 = 15; 41661.108Skamil pid_t child, child2 = 0, wpid; 41671.108Skamil#if defined(TWAIT_HAVE_STATUS) 41681.108Skamil int status; 41691.108Skamil#endif 41701.108Skamil 41711.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 41721.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 41731.108Skamil if (child == 0) { 41741.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41751.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41761.108Skamil 41771.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 41781.108Skamil 41791.108Skamil if (child2 == 0) 41801.108Skamil _exit(exitval2); 41811.108Skamil 41821.108Skamil FORKEE_REQUIRE_SUCCESS 41831.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 41841.108Skamil 41851.108Skamil forkee_status_exited(status, exitval2); 41861.108Skamil 41871.108Skamil DPRINTF("Before exiting of the child process\n"); 41881.108Skamil _exit(exitval); 41891.108Skamil } 41901.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41911.108Skamil 41921.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 41931.108Skamil TWAIT_FNAME); 41941.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41951.108Skamil 41961.108Skamil validate_status_exited(status, exitval); 41971.108Skamil 41981.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 41991.108Skamil TWAIT_FNAME); 42001.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 42011.108Skamil} 42021.108Skamil 42031.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 42041.108SkamilATF_TC(name); \ 42051.108SkamilATF_TC_HEAD(name, tc) \ 42061.108Skamil{ \ 42071.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 42081.108Skamil "called from vfork(2)ed child"); \ 42091.108Skamil} \ 42101.108Skamil \ 42111.108SkamilATF_TC_BODY(name, tc) \ 42121.108Skamil{ \ 42131.108Skamil \ 42141.108Skamil traceme_vfork_fork_body(fun); \ 42151.108Skamil} 42161.108Skamil 42171.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 42181.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 42191.108Skamil 42201.108Skamil/// ---------------------------------------------------------------------------- 42211.108Skamil 42221.54Skamilenum bytes_transfer_type { 42231.54Skamil BYTES_TRANSFER_DATA, 42241.54Skamil BYTES_TRANSFER_DATAIO, 42251.54Skamil BYTES_TRANSFER_TEXT, 42261.54Skamil BYTES_TRANSFER_TEXTIO, 42271.54Skamil BYTES_TRANSFER_AUXV 42281.54Skamil}; 42291.31Skamil 42301.54Skamilstatic int __used 42311.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 42321.54Skamil{ 42331.54Skamil int e, f, g, h; 42341.1Skamil 42351.54Skamil a *= 4; 42361.54Skamil b += 3; 42371.54Skamil c -= 2; 42381.54Skamil d /= 1; 42391.1Skamil 42401.54Skamil e = strtol("10", NULL, 10); 42411.54Skamil f = strtol("20", NULL, 10); 42421.54Skamil g = strtol("30", NULL, 10); 42431.54Skamil h = strtol("40", NULL, 10); 42441.1Skamil 42451.54Skamil return (a + b * c - d) + (e * f - g / h); 42461.1Skamil} 42471.1Skamil 42481.54Skamilstatic void 42491.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 42501.1Skamil{ 42511.1Skamil const int exitval = 5; 42521.1Skamil const int sigval = SIGSTOP; 42531.1Skamil pid_t child, wpid; 42541.54Skamil bool skip = false; 42551.1Skamil 42561.54Skamil int lookup_me = 0; 42571.54Skamil uint8_t lookup_me8 = 0; 42581.54Skamil uint16_t lookup_me16 = 0; 42591.54Skamil uint32_t lookup_me32 = 0; 42601.54Skamil uint64_t lookup_me64 = 0; 42611.1Skamil 42621.54Skamil int magic = 0x13579246; 42631.54Skamil uint8_t magic8 = 0xab; 42641.54Skamil uint16_t magic16 = 0x1234; 42651.54Skamil uint32_t magic32 = 0x98765432; 42661.54Skamil uint64_t magic64 = 0xabcdef0123456789; 42671.1Skamil 42681.54Skamil struct ptrace_io_desc io; 42691.1Skamil#if defined(TWAIT_HAVE_STATUS) 42701.1Skamil int status; 42711.1Skamil#endif 42721.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 42731.60Skre AuxInfo ai[513], *aip; 42741.55Schristos 42751.55Schristos ATF_REQUIRE(size < sizeof(ai)); 42761.1Skamil 42771.54Skamil /* Prepare variables for .TEXT transfers */ 42781.54Skamil switch (type) { 42791.54Skamil case BYTES_TRANSFER_TEXT: 42801.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 42811.54Skamil break; 42821.54Skamil case BYTES_TRANSFER_TEXTIO: 42831.54Skamil switch (size) { 42841.54Skamil case 8: 42851.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 42861.54Skamil break; 42871.54Skamil case 16: 42881.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 42891.54Skamil break; 42901.54Skamil case 32: 42911.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 42921.54Skamil break; 42931.54Skamil case 64: 42941.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 42951.54Skamil break; 42961.54Skamil } 42971.54Skamil break; 42981.54Skamil default: 42991.54Skamil break; 43001.54Skamil } 43011.1Skamil 43021.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 43031.54Skamil switch (type) { 43041.54Skamil case BYTES_TRANSFER_TEXTIO: 43051.54Skamil case BYTES_TRANSFER_DATAIO: 43061.54Skamil io.piod_op = operation; 43071.54Skamil switch (size) { 43081.54Skamil case 8: 43091.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 43101.54Skamil (void *)bytes_transfer_dummy : 43111.54Skamil &lookup_me8; 43121.54Skamil io.piod_addr = &lookup_me8; 43131.54Skamil io.piod_len = sizeof(lookup_me8); 43141.54Skamil break; 43151.54Skamil case 16: 43161.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 43171.54Skamil (void *)bytes_transfer_dummy : 43181.54Skamil &lookup_me16; 43191.54Skamil io.piod_addr = &lookup_me16; 43201.54Skamil io.piod_len = sizeof(lookup_me16); 43211.54Skamil break; 43221.54Skamil case 32: 43231.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 43241.54Skamil (void *)bytes_transfer_dummy : 43251.54Skamil &lookup_me32; 43261.54Skamil io.piod_addr = &lookup_me32; 43271.54Skamil io.piod_len = sizeof(lookup_me32); 43281.54Skamil break; 43291.54Skamil case 64: 43301.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 43311.54Skamil (void *)bytes_transfer_dummy : 43321.54Skamil &lookup_me64; 43331.54Skamil io.piod_addr = &lookup_me64; 43341.54Skamil io.piod_len = sizeof(lookup_me64); 43351.54Skamil break; 43361.54Skamil default: 43371.54Skamil break; 43381.54Skamil } 43391.54Skamil break; 43401.54Skamil case BYTES_TRANSFER_AUXV: 43411.54Skamil io.piod_op = operation; 43421.54Skamil io.piod_offs = 0; 43431.54Skamil io.piod_addr = ai; 43441.54Skamil io.piod_len = size; 43451.54Skamil break; 43461.54Skamil default: 43471.54Skamil break; 43481.1Skamil } 43491.1Skamil 43501.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43511.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43521.1Skamil if (child == 0) { 43531.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43541.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 43551.1Skamil 43561.54Skamil switch (type) { 43571.54Skamil case BYTES_TRANSFER_DATA: 43581.54Skamil switch (operation) { 43591.54Skamil case PT_READ_D: 43601.54Skamil case PT_READ_I: 43611.54Skamil lookup_me = magic; 43621.54Skamil break; 43631.54Skamil default: 43641.54Skamil break; 43651.54Skamil } 43661.54Skamil break; 43671.54Skamil case BYTES_TRANSFER_DATAIO: 43681.54Skamil switch (operation) { 43691.54Skamil case PIOD_READ_D: 43701.54Skamil case PIOD_READ_I: 43711.54Skamil switch (size) { 43721.54Skamil case 8: 43731.54Skamil lookup_me8 = magic8; 43741.54Skamil break; 43751.54Skamil case 16: 43761.54Skamil lookup_me16 = magic16; 43771.54Skamil break; 43781.54Skamil case 32: 43791.54Skamil lookup_me32 = magic32; 43801.54Skamil break; 43811.54Skamil case 64: 43821.54Skamil lookup_me64 = magic64; 43831.54Skamil break; 43841.54Skamil default: 43851.54Skamil break; 43861.54Skamil } 43871.54Skamil break; 43881.54Skamil default: 43891.54Skamil break; 43901.54Skamil } 43911.54Skamil default: 43921.54Skamil break; 43931.54Skamil } 43941.54Skamil 43951.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 43961.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 43971.1Skamil 43981.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 43991.54Skamil switch (type) { 44001.54Skamil case BYTES_TRANSFER_DATA: 44011.54Skamil switch (operation) { 44021.54Skamil case PT_WRITE_D: 44031.54Skamil case PT_WRITE_I: 44041.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 44051.54Skamil break; 44061.54Skamil default: 44071.54Skamil break; 44081.54Skamil } 44091.54Skamil break; 44101.54Skamil case BYTES_TRANSFER_DATAIO: 44111.54Skamil switch (operation) { 44121.54Skamil case PIOD_WRITE_D: 44131.54Skamil case PIOD_WRITE_I: 44141.54Skamil switch (size) { 44151.54Skamil case 8: 44161.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 44171.54Skamil break; 44181.54Skamil case 16: 44191.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 44201.54Skamil break; 44211.54Skamil case 32: 44221.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 44231.54Skamil break; 44241.54Skamil case 64: 44251.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 44261.54Skamil break; 44271.54Skamil default: 44281.54Skamil break; 44291.54Skamil } 44301.54Skamil break; 44311.54Skamil default: 44321.54Skamil break; 44331.54Skamil } 44341.54Skamil break; 44351.54Skamil case BYTES_TRANSFER_TEXT: 44361.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 44371.54Skamil sizeof(magic)) == 0); 44381.54Skamil break; 44391.54Skamil case BYTES_TRANSFER_TEXTIO: 44401.54Skamil switch (size) { 44411.54Skamil case 8: 44421.54Skamil FORKEE_ASSERT(memcmp(&magic8, 44431.54Skamil bytes_transfer_dummy, 44441.54Skamil sizeof(magic8)) == 0); 44451.54Skamil break; 44461.54Skamil case 16: 44471.54Skamil FORKEE_ASSERT(memcmp(&magic16, 44481.54Skamil bytes_transfer_dummy, 44491.54Skamil sizeof(magic16)) == 0); 44501.54Skamil break; 44511.54Skamil case 32: 44521.54Skamil FORKEE_ASSERT(memcmp(&magic32, 44531.54Skamil bytes_transfer_dummy, 44541.54Skamil sizeof(magic32)) == 0); 44551.54Skamil break; 44561.54Skamil case 64: 44571.54Skamil FORKEE_ASSERT(memcmp(&magic64, 44581.54Skamil bytes_transfer_dummy, 44591.54Skamil sizeof(magic64)) == 0); 44601.54Skamil break; 44611.54Skamil } 44621.54Skamil break; 44631.54Skamil default: 44641.54Skamil break; 44651.54Skamil } 44661.54Skamil 44671.13Schristos DPRINTF("Before exiting of the child process\n"); 44681.1Skamil _exit(exitval); 44691.1Skamil } 44701.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44711.1Skamil 44721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44741.1Skamil 44751.1Skamil validate_status_stopped(status, sigval); 44761.1Skamil 44771.54Skamil /* Check PaX MPROTECT */ 44781.54Skamil if (!can_we_write_to_text(child)) { 44791.54Skamil switch (type) { 44801.54Skamil case BYTES_TRANSFER_TEXTIO: 44811.54Skamil switch (operation) { 44821.54Skamil case PIOD_WRITE_D: 44831.54Skamil case PIOD_WRITE_I: 44841.54Skamil skip = true; 44851.54Skamil break; 44861.54Skamil default: 44871.54Skamil break; 44881.54Skamil } 44891.54Skamil break; 44901.54Skamil case BYTES_TRANSFER_TEXT: 44911.54Skamil switch (operation) { 44921.54Skamil case PT_WRITE_D: 44931.54Skamil case PT_WRITE_I: 44941.54Skamil skip = true; 44951.54Skamil break; 44961.54Skamil default: 44971.54Skamil break; 44981.54Skamil } 44991.54Skamil break; 45001.54Skamil default: 45011.54Skamil break; 45021.54Skamil } 45031.54Skamil } 45041.1Skamil 45051.54Skamil /* Bailout cleanly killing the child process */ 45061.54Skamil if (skip) { 45071.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 45081.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45091.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 45101.54Skamil child); 45111.1Skamil 45121.54Skamil validate_status_signaled(status, SIGKILL, 0); 45131.1Skamil 45141.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 45151.54Skamil } 45161.1Skamil 45171.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 45181.54Skamil "parent=%d\n", child, getpid()); 45191.1Skamil 45201.54Skamil switch (type) { 45211.54Skamil case BYTES_TRANSFER_TEXTIO: 45221.54Skamil case BYTES_TRANSFER_DATAIO: 45231.54Skamil case BYTES_TRANSFER_AUXV: 45241.54Skamil switch (operation) { 45251.54Skamil case PIOD_WRITE_D: 45261.54Skamil case PIOD_WRITE_I: 45271.54Skamil switch (size) { 45281.54Skamil case 8: 45291.54Skamil lookup_me8 = magic8; 45301.54Skamil break; 45311.54Skamil case 16: 45321.54Skamil lookup_me16 = magic16; 45331.54Skamil break; 45341.54Skamil case 32: 45351.54Skamil lookup_me32 = magic32; 45361.54Skamil break; 45371.54Skamil case 64: 45381.54Skamil lookup_me64 = magic64; 45391.54Skamil break; 45401.54Skamil default: 45411.54Skamil break; 45421.54Skamil } 45431.54Skamil break; 45441.54Skamil default: 45451.54Skamil break; 45461.54Skamil } 45471.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 45481.54Skamil switch (operation) { 45491.54Skamil case PIOD_READ_D: 45501.54Skamil case PIOD_READ_I: 45511.54Skamil switch (size) { 45521.54Skamil case 8: 45531.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 45541.54Skamil break; 45551.54Skamil case 16: 45561.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 45571.54Skamil break; 45581.54Skamil case 32: 45591.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 45601.54Skamil break; 45611.54Skamil case 64: 45621.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 45631.54Skamil break; 45641.54Skamil default: 45651.54Skamil break; 45661.54Skamil } 45671.54Skamil break; 45681.54Skamil case PIOD_READ_AUXV: 45691.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 45701.54Skamil io.piod_len); 45711.54Skamil ATF_REQUIRE(io.piod_len > 0); 45721.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 45731.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 45741.54Skamil (long long int)aip->a_type, 45751.54Skamil (long long int)aip->a_v); 45761.54Skamil break; 45771.54Skamil default: 45781.54Skamil break; 45791.54Skamil } 45801.54Skamil break; 45811.54Skamil case BYTES_TRANSFER_TEXT: 45821.54Skamil switch (operation) { 45831.54Skamil case PT_READ_D: 45841.54Skamil case PT_READ_I: 45851.54Skamil errno = 0; 45861.54Skamil lookup_me = ptrace(operation, child, 45871.54Skamil bytes_transfer_dummy, 0); 45881.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 45891.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 45901.54Skamil break; 45911.54Skamil case PT_WRITE_D: 45921.54Skamil case PT_WRITE_I: 45931.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 45941.54Skamil bytes_transfer_dummy, magic) 45951.54Skamil != -1); 45961.54Skamil break; 45971.54Skamil default: 45981.54Skamil break; 45991.54Skamil } 46001.54Skamil break; 46011.54Skamil case BYTES_TRANSFER_DATA: 46021.54Skamil switch (operation) { 46031.54Skamil case PT_READ_D: 46041.54Skamil case PT_READ_I: 46051.54Skamil errno = 0; 46061.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 46071.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 46081.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 46091.54Skamil break; 46101.54Skamil case PT_WRITE_D: 46111.54Skamil case PT_WRITE_I: 46121.54Skamil lookup_me = magic; 46131.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 46141.54Skamil magic) != -1); 46151.54Skamil break; 46161.54Skamil default: 46171.54Skamil break; 46181.54Skamil } 46191.54Skamil break; 46201.54Skamil default: 46211.54Skamil break; 46221.54Skamil } 46231.1Skamil 46241.13Schristos DPRINTF("Before resuming the child process where it left off and " 46251.1Skamil "without signal to be sent\n"); 46261.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46271.1Skamil 46281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46301.1Skamil 46311.1Skamil validate_status_exited(status, exitval); 46321.1Skamil 46331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46341.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46351.1Skamil} 46361.1Skamil 46371.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 46381.61SkreATF_TC(test); \ 46391.61SkreATF_TC_HEAD(test, tc) \ 46401.61Skre{ \ 46411.61Skre atf_tc_set_md_var(tc, "descr", \ 46421.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 46431.61Skre " of type " #type); \ 46441.61Skre} \ 46451.61Skre \ 46461.61SkreATF_TC_BODY(test, tc) \ 46471.61Skre{ \ 46481.61Skre \ 46491.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 46501.1Skamil} 46511.1Skamil 46521.54Skamil// DATA 46531.1Skamil 46541.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 46551.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 46561.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 46571.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 46581.54Skamil 46591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 46601.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 46611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 46621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 46631.54Skamil 46641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 46651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 46661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 46671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 46681.54Skamil 46691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 46701.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 46711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 46721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 46731.54Skamil 46741.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 46751.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 46761.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 46771.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 46781.54Skamil 46791.54Skamil// TEXT 46801.54Skamil 46811.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 46821.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 46831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 46841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 46851.54Skamil 46861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 46871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 46881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 46891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 46901.54Skamil 46911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 46921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 46931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 46941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 46951.54Skamil 46961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 46971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 46981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 46991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 47001.54Skamil 47011.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 47021.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 47031.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 47041.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 47051.1Skamil 47061.54Skamil// AUXV 47071.1Skamil 47081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 47091.1Skamil 47101.54Skamil/// ---------------------------------------------------------------------------- 47111.1Skamil 47121.101Skamilstatic void 47131.101Skamilbytes_transfer_alignment(const char *operation) 47141.101Skamil{ 47151.101Skamil const int exitval = 5; 47161.101Skamil const int sigval = SIGSTOP; 47171.101Skamil pid_t child, wpid; 47181.101Skamil#if defined(TWAIT_HAVE_STATUS) 47191.101Skamil int status; 47201.101Skamil#endif 47211.101Skamil char *buffer; 47221.101Skamil int vector; 47231.101Skamil size_t len; 47241.101Skamil size_t i; 47251.101Skamil int op; 47261.101Skamil 47271.101Skamil struct ptrace_io_desc io; 47281.101Skamil struct ptrace_siginfo info; 47291.101Skamil 47301.101Skamil memset(&io, 0, sizeof(io)); 47311.101Skamil memset(&info, 0, sizeof(info)); 47321.101Skamil 47331.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 47341.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 47351.101Skamil buffer = malloc(len); 47361.101Skamil ATF_REQUIRE(buffer != NULL); 47371.101Skamil 47381.101Skamil /* Initialize the buffer with random data */ 47391.101Skamil for (i = 0; i < len; i++) 47401.101Skamil buffer[i] = i & 0xff; 47411.101Skamil 47421.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 47431.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 47441.101Skamil if (child == 0) { 47451.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47461.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47471.101Skamil 47481.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47491.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 47501.101Skamil 47511.101Skamil DPRINTF("Before exiting of the child process\n"); 47521.101Skamil _exit(exitval); 47531.101Skamil } 47541.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47551.101Skamil 47561.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47571.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47581.101Skamil 47591.101Skamil validate_status_stopped(status, sigval); 47601.101Skamil 47611.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 47621.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 47631.101Skamil != -1); 47641.101Skamil 47651.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47661.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 47671.101Skamil "si_errno=%#x\n", 47681.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47691.101Skamil info.psi_siginfo.si_errno); 47701.101Skamil 47711.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 47721.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 47731.101Skamil 47741.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 47751.101Skamil strcmp(operation, "PT_READ_D") == 0) { 47761.101Skamil if (strcmp(operation, "PT_READ_I")) 47771.101Skamil op = PT_READ_I; 47781.101Skamil else 47791.101Skamil op = PT_READ_D; 47801.101Skamil 47811.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 47821.101Skamil errno = 0; 47831.101Skamil vector = ptrace(op, child, buffer + i, 0); 47841.101Skamil ATF_REQUIRE_EQ(errno, 0); 47851.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 47861.101Skamil } 47871.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 47881.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 47891.101Skamil if (strcmp(operation, "PT_WRITE_I")) 47901.101Skamil op = PT_WRITE_I; 47911.101Skamil else 47921.101Skamil op = PT_WRITE_D; 47931.101Skamil 47941.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 47951.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 47961.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 47971.101Skamil != -1); 47981.101Skamil } 47991.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 48001.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 48011.101Skamil if (strcmp(operation, "PIOD_READ_I")) 48021.101Skamil op = PIOD_READ_I; 48031.101Skamil else 48041.101Skamil op = PIOD_READ_D; 48051.101Skamil 48061.101Skamil io.piod_op = op; 48071.101Skamil io.piod_addr = &vector; 48081.101Skamil io.piod_len = sizeof(int); 48091.101Skamil 48101.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 48111.101Skamil io.piod_offs = buffer + i; 48121.101Skamil 48131.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 48141.101Skamil != -1); 48151.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 48161.101Skamil } 48171.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 48181.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 48191.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 48201.101Skamil op = PIOD_WRITE_I; 48211.101Skamil else 48221.101Skamil op = PIOD_WRITE_D; 48231.101Skamil 48241.101Skamil io.piod_op = op; 48251.101Skamil io.piod_addr = &vector; 48261.101Skamil io.piod_len = sizeof(int); 48271.101Skamil 48281.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 48291.101Skamil io.piod_offs = buffer + i; 48301.101Skamil 48311.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 48321.101Skamil != -1); 48331.101Skamil } 48341.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 48351.101Skamil io.piod_op = PIOD_READ_AUXV; 48361.101Skamil io.piod_addr = &vector; 48371.101Skamil io.piod_len = sizeof(int); 48381.101Skamil 48391.101Skamil errno = 0; 48401.101Skamil i = 0; 48411.101Skamil /* Read the whole AUXV vector, it has no clear length */ 48421.120Skamil while (io.piod_len > 0) { 48431.101Skamil io.piod_offs = (void *)(intptr_t)i; 48441.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 48451.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 48461.101Skamil ++i; 48471.101Skamil } 48481.101Skamil } 48491.101Skamil 48501.101Skamil DPRINTF("Before resuming the child process where it left off " 48511.101Skamil "and without signal to be sent\n"); 48521.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48531.101Skamil 48541.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48551.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 48561.101Skamil child); 48571.101Skamil 48581.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48591.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48601.101Skamil} 48611.101Skamil 48621.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 48631.101SkamilATF_TC(test); \ 48641.101SkamilATF_TC_HEAD(test, tc) \ 48651.101Skamil{ \ 48661.101Skamil atf_tc_set_md_var(tc, "descr", \ 48671.101Skamil "Verify bytes transfer for potentially misaligned " \ 48681.101Skamil "operation " operation); \ 48691.101Skamil} \ 48701.101Skamil \ 48711.101SkamilATF_TC_BODY(test, tc) \ 48721.101Skamil{ \ 48731.101Skamil \ 48741.101Skamil bytes_transfer_alignment(operation); \ 48751.101Skamil} 48761.101Skamil 48771.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 48781.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 48791.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 48801.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 48811.101Skamil 48821.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 48831.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 48841.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 48851.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 48861.101Skamil 48871.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 48881.101Skamil 48891.101Skamil/// ---------------------------------------------------------------------------- 48901.101Skamil 48911.115Skamilstatic void 48921.115Skamilbytes_transfer_eof(const char *operation) 48931.115Skamil{ 48941.115Skamil const int exitval = 5; 48951.115Skamil const int sigval = SIGSTOP; 48961.115Skamil pid_t child, wpid; 48971.115Skamil#if defined(TWAIT_HAVE_STATUS) 48981.115Skamil int status; 48991.115Skamil#endif 49001.115Skamil FILE *fp; 49011.115Skamil char *p; 49021.115Skamil int vector; 49031.115Skamil int op; 49041.115Skamil 49051.115Skamil struct ptrace_io_desc io; 49061.115Skamil struct ptrace_siginfo info; 49071.115Skamil 49081.115Skamil memset(&io, 0, sizeof(io)); 49091.115Skamil memset(&info, 0, sizeof(info)); 49101.115Skamil 49111.115Skamil vector = 0; 49121.115Skamil 49131.115Skamil fp = tmpfile(); 49141.115Skamil ATF_REQUIRE(fp != NULL); 49151.115Skamil 49161.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 49171.115Skamil ATF_REQUIRE(p != MAP_FAILED); 49181.115Skamil 49191.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 49201.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 49211.115Skamil if (child == 0) { 49221.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 49231.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 49241.115Skamil 49251.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49261.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 49271.115Skamil 49281.115Skamil DPRINTF("Before exiting of the child process\n"); 49291.115Skamil _exit(exitval); 49301.115Skamil } 49311.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 49321.115Skamil 49331.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49341.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49351.115Skamil 49361.115Skamil validate_status_stopped(status, sigval); 49371.115Skamil 49381.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 49391.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 49401.115Skamil != -1); 49411.115Skamil 49421.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49431.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49441.115Skamil "si_errno=%#x\n", 49451.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49461.115Skamil info.psi_siginfo.si_errno); 49471.115Skamil 49481.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 49491.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 49501.115Skamil 49511.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 49521.115Skamil strcmp(operation, "PT_READ_D") == 0) { 49531.115Skamil if (strcmp(operation, "PT_READ_I")) 49541.115Skamil op = PT_READ_I; 49551.115Skamil else 49561.115Skamil op = PT_READ_D; 49571.115Skamil 49581.115Skamil errno = 0; 49591.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 49601.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49611.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 49621.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 49631.115Skamil if (strcmp(operation, "PT_WRITE_I")) 49641.115Skamil op = PT_WRITE_I; 49651.115Skamil else 49661.115Skamil op = PT_WRITE_D; 49671.115Skamil 49681.115Skamil errno = 0; 49691.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 49701.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49711.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 49721.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 49731.115Skamil if (strcmp(operation, "PIOD_READ_I")) 49741.115Skamil op = PIOD_READ_I; 49751.115Skamil else 49761.115Skamil op = PIOD_READ_D; 49771.115Skamil 49781.115Skamil io.piod_op = op; 49791.115Skamil io.piod_addr = &vector; 49801.115Skamil io.piod_len = sizeof(int); 49811.115Skamil io.piod_offs = p; 49821.115Skamil 49831.115Skamil errno = 0; 49841.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 49851.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49861.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 49871.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 49881.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 49891.115Skamil op = PIOD_WRITE_I; 49901.115Skamil else 49911.115Skamil op = PIOD_WRITE_D; 49921.115Skamil 49931.115Skamil io.piod_op = op; 49941.115Skamil io.piod_addr = &vector; 49951.115Skamil io.piod_len = sizeof(int); 49961.115Skamil io.piod_offs = p; 49971.115Skamil 49981.115Skamil errno = 0; 49991.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 50001.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 50011.115Skamil } 50021.115Skamil 50031.115Skamil DPRINTF("Before resuming the child process where it left off " 50041.115Skamil "and without signal to be sent\n"); 50051.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 50061.115Skamil 50071.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50081.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 50091.115Skamil child); 50101.115Skamil 50111.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50121.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 50131.115Skamil} 50141.115Skamil 50151.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 50161.115SkamilATF_TC(test); \ 50171.115SkamilATF_TC_HEAD(test, tc) \ 50181.115Skamil{ \ 50191.115Skamil atf_tc_set_md_var(tc, "descr", \ 50201.115Skamil "Verify bytes EOF byte transfer for the " operation \ 50211.115Skamil " operation"); \ 50221.115Skamil} \ 50231.115Skamil \ 50241.115SkamilATF_TC_BODY(test, tc) \ 50251.115Skamil{ \ 50261.115Skamil \ 50271.115Skamil bytes_transfer_eof(operation); \ 50281.115Skamil} 50291.115Skamil 50301.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 50311.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 50321.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 50331.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 50341.115Skamil 50351.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 50361.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 50371.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 50381.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 50391.115Skamil 50401.115Skamil/// ---------------------------------------------------------------------------- 50411.115Skamil 50421.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 50431.72Skamilstatic void 50441.72Skamilaccess_regs(const char *regset, const char *aux) 50451.1Skamil{ 50461.1Skamil const int exitval = 5; 50471.1Skamil const int sigval = SIGSTOP; 50481.1Skamil pid_t child, wpid; 50491.1Skamil#if defined(TWAIT_HAVE_STATUS) 50501.1Skamil int status; 50511.1Skamil#endif 50521.72Skamil#if defined(HAVE_GPREGS) 50531.72Skamil struct reg gpr; 50541.76Sscole register_t rgstr; 50551.1Skamil#endif 50561.72Skamil#if defined(HAVE_FPREGS) 50571.72Skamil struct fpreg fpr; 50581.1Skamil#endif 50591.76Sscole 50601.72Skamil#if !defined(HAVE_GPREGS) 50611.72Skamil if (strcmp(regset, "regs") == 0) 50621.72Skamil atf_tc_fail("Impossible test scenario!"); 50631.1Skamil#endif 50641.1Skamil 50651.72Skamil#if !defined(HAVE_FPREGS) 50661.72Skamil if (strcmp(regset, "fpregs") == 0) 50671.72Skamil atf_tc_fail("Impossible test scenario!"); 50681.1Skamil#endif 50691.1Skamil 50701.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 50711.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 50721.1Skamil if (child == 0) { 50731.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 50741.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 50751.1Skamil 50761.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 50771.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 50781.1Skamil 50791.13Schristos DPRINTF("Before exiting of the child process\n"); 50801.1Skamil _exit(exitval); 50811.1Skamil } 50821.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 50831.1Skamil 50841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50861.1Skamil 50871.1Skamil validate_status_stopped(status, sigval); 50881.1Skamil 50891.1Skamil#if defined(HAVE_GPREGS) 50901.72Skamil if (strcmp(regset, "regs") == 0) { 50911.72Skamil DPRINTF("Call GETREGS for the child process\n"); 50921.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 50931.72Skamil 50941.72Skamil if (strcmp(aux, "none") == 0) { 50951.72Skamil DPRINTF("Retrieved registers\n"); 50961.72Skamil } else if (strcmp(aux, "pc") == 0) { 50971.72Skamil rgstr = PTRACE_REG_PC(&gpr); 50981.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 50991.147Skamil } else if (strstr(aux, "set_pc") != NULL) { 51001.72Skamil rgstr = PTRACE_REG_PC(&gpr); 51011.147Skamil DPRINTF("Retrieved PC %" PRIxREGISTER "\n", rgstr); 51021.147Skamil if (strstr(aux, "0x1") != NULL) { 51031.147Skamil rgstr |= 0x1; 51041.147Skamil } else if (strstr(aux, "0x3") != NULL) { 51051.147Skamil rgstr |= 0x3; 51061.147Skamil } else if (strstr(aux, "0x7") != NULL) { 51071.147Skamil rgstr |= 0x7; 51081.147Skamil } 51091.147Skamil DPRINTF("Set PC %" PRIxREGISTER "\n", rgstr); 51101.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 51111.147Skamil if (strcmp(aux, "set_pc") != 0) { 51121.147Skamil /* This call can fail with EINVAL or similar. */ 51131.147Skamil ptrace(PT_SETREGS, child, &gpr, 0); 51141.147Skamil } 51151.72Skamil } else if (strcmp(aux, "sp") == 0) { 51161.72Skamil rgstr = PTRACE_REG_SP(&gpr); 51171.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 51181.72Skamil } else if (strcmp(aux, "intrv") == 0) { 51191.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 51201.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 51211.72Skamil } else if (strcmp(aux, "setregs") == 0) { 51221.72Skamil DPRINTF("Call SETREGS for the child process\n"); 51231.72Skamil SYSCALL_REQUIRE( 51241.147Skamil ptrace(PT_SETREGS, child, &gpr, 0) != -1); 51251.72Skamil } 51261.72Skamil } 51271.1Skamil#endif 51281.1Skamil 51291.72Skamil#if defined(HAVE_FPREGS) 51301.72Skamil if (strcmp(regset, "fpregs") == 0) { 51311.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 51321.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 51331.72Skamil 51341.72Skamil if (strcmp(aux, "getfpregs") == 0) { 51351.72Skamil DPRINTF("Retrieved FP registers\n"); 51361.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 51371.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 51381.72Skamil SYSCALL_REQUIRE( 51391.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 51401.72Skamil } 51411.1Skamil } 51421.1Skamil#endif 51431.1Skamil 51441.13Schristos DPRINTF("Before resuming the child process where it left off and " 51451.1Skamil "without signal to be sent\n"); 51461.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 51471.1Skamil 51481.147Skamil if (strstr(aux, "unaligned") != NULL) { 51491.147Skamil DPRINTF("Before resuming the child process where it left off " 51501.147Skamil "and without signal to be sent\n"); 51511.147Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 51521.147Skamil 51531.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51541.147Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 51551.147Skamil child); 51561.147Skamil 51571.147Skamil validate_status_signaled(status, SIGKILL, 0); 51581.147Skamil 51591.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51601.147Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 51611.147Skamil wpid = TWAIT_GENERIC(child, &status, 0)); 51621.147Skamil } else { 51631.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51641.147Skamil TWAIT_REQUIRE_SUCCESS( 51651.147Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 51661.1Skamil 51671.147Skamil validate_status_exited(status, exitval); 51681.1Skamil 51691.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51701.147Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 51711.147Skamil wpid = TWAIT_GENERIC(child, &status, 0)); 51721.147Skamil } 51731.1Skamil} 51741.1Skamil 51751.72Skamil#define ACCESS_REGS(test, regset, aux) \ 51761.72SkamilATF_TC(test); \ 51771.72SkamilATF_TC_HEAD(test, tc) \ 51781.72Skamil{ \ 51791.72Skamil atf_tc_set_md_var(tc, "descr", \ 51801.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 51811.72Skamil} \ 51821.72Skamil \ 51831.72SkamilATF_TC_BODY(test, tc) \ 51841.72Skamil{ \ 51851.72Skamil \ 51861.72Skamil access_regs(regset, aux); \ 51871.1Skamil} 51881.1Skamil#endif 51891.1Skamil 51901.72Skamil#if defined(HAVE_GPREGS) 51911.72SkamilACCESS_REGS(access_regs1, "regs", "none") 51921.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 51931.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 51941.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 51951.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 51961.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 51971.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x1, "regs", "set_pc+unaligned+0x1") 51981.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x3, "regs", "set_pc+unaligned+0x3") 51991.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x7, "regs", "set_pc+unaligned+0x7") 52001.1Skamil#endif 52011.1Skamil#if defined(HAVE_FPREGS) 52021.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 52031.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 52041.1Skamil#endif 52051.1Skamil 52061.72Skamil/// ---------------------------------------------------------------------------- 52071.1Skamil 52081.1Skamil#if defined(PT_STEP) 52091.1Skamilstatic void 52101.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 52111.1Skamil{ 52121.1Skamil const int exitval = 5; 52131.1Skamil const int sigval = SIGSTOP; 52141.1Skamil pid_t child, wpid; 52151.1Skamil#if defined(TWAIT_HAVE_STATUS) 52161.1Skamil int status; 52171.1Skamil#endif 52181.1Skamil int happy; 52191.95Skamil struct sigaction sa; 52201.81Skamil struct ptrace_siginfo info; 52211.95Skamil sigset_t intmask; 52221.95Skamil struct kinfo_proc2 kp; 52231.95Skamil size_t len = sizeof(kp); 52241.95Skamil 52251.95Skamil int name[6]; 52261.95Skamil const size_t namelen = __arraycount(name); 52271.95Skamil ki_sigset_t kp_sigmask; 52281.95Skamil ki_sigset_t kp_sigignore; 52291.1Skamil 52301.1Skamil#if defined(__arm__) 52311.1Skamil /* PT_STEP not supported on arm 32-bit */ 52321.1Skamil atf_tc_expect_fail("PR kern/52119"); 52331.1Skamil#endif 52341.1Skamil 52351.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52361.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52371.1Skamil if (child == 0) { 52381.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 52391.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 52401.1Skamil 52411.95Skamil if (masked) { 52421.95Skamil sigemptyset(&intmask); 52431.95Skamil sigaddset(&intmask, SIGTRAP); 52441.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 52451.95Skamil } 52461.95Skamil 52471.95Skamil if (ignored) { 52481.95Skamil memset(&sa, 0, sizeof(sa)); 52491.95Skamil sa.sa_handler = SIG_IGN; 52501.95Skamil sigemptyset(&sa.sa_mask); 52511.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 52521.95Skamil } 52531.95Skamil 52541.1Skamil happy = check_happy(999); 52551.1Skamil 52561.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 52571.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 52581.1Skamil 52591.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 52601.1Skamil 52611.13Schristos DPRINTF("Before exiting of the child process\n"); 52621.1Skamil _exit(exitval); 52631.1Skamil } 52641.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52651.1Skamil 52661.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52681.1Skamil 52691.1Skamil validate_status_stopped(status, sigval); 52701.1Skamil 52711.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52721.81Skamil SYSCALL_REQUIRE( 52731.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52741.81Skamil 52751.81Skamil DPRINTF("Before checking siginfo_t\n"); 52761.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 52771.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 52781.81Skamil 52791.95Skamil name[0] = CTL_KERN, 52801.95Skamil name[1] = KERN_PROC2, 52811.95Skamil name[2] = KERN_PROC_PID; 52821.95Skamil name[3] = child; 52831.95Skamil name[4] = sizeof(kp); 52841.95Skamil name[5] = 1; 52851.95Skamil 52861.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52871.95Skamil 52881.95Skamil if (masked) 52891.95Skamil kp_sigmask = kp.p_sigmask; 52901.95Skamil 52911.95Skamil if (ignored) 52921.95Skamil kp_sigignore = kp.p_sigignore; 52931.95Skamil 52941.1Skamil while (N --> 0) { 52951.2Skamil if (setstep) { 52961.13Schristos DPRINTF("Before resuming the child process where it " 52971.2Skamil "left off and without signal to be sent (use " 52981.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 52991.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 53001.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 53011.2Skamil != -1); 53021.2Skamil } else { 53031.13Schristos DPRINTF("Before resuming the child process where it " 53041.2Skamil "left off and without signal to be sent (use " 53051.2Skamil "PT_STEP)\n"); 53061.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 53071.2Skamil != -1); 53081.2Skamil } 53091.1Skamil 53101.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 53121.1Skamil child); 53131.1Skamil 53141.1Skamil validate_status_stopped(status, SIGTRAP); 53151.2Skamil 53161.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 53171.81Skamil SYSCALL_REQUIRE( 53181.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 53191.81Skamil 53201.81Skamil DPRINTF("Before checking siginfo_t\n"); 53211.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 53221.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 53231.81Skamil 53241.2Skamil if (setstep) { 53251.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 53261.2Skamil } 53271.95Skamil 53281.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53291.95Skamil 53301.95Skamil if (masked) { 53311.95Skamil DPRINTF("kp_sigmask=" 53321.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53331.95Skamil PRIx32 "\n", 53341.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53351.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53361.95Skamil 53371.95Skamil DPRINTF("kp.p_sigmask=" 53381.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53391.95Skamil PRIx32 "\n", 53401.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53411.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53421.95Skamil 53431.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53441.95Skamil sizeof(kp_sigmask))); 53451.95Skamil } 53461.95Skamil 53471.95Skamil if (ignored) { 53481.95Skamil DPRINTF("kp_sigignore=" 53491.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53501.95Skamil PRIx32 "\n", 53511.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53521.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53531.95Skamil 53541.95Skamil DPRINTF("kp.p_sigignore=" 53551.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53561.95Skamil PRIx32 "\n", 53571.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53581.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53591.95Skamil 53601.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53611.95Skamil sizeof(kp_sigignore))); 53621.95Skamil } 53631.1Skamil } 53641.1Skamil 53651.13Schristos DPRINTF("Before resuming the child process where it left off and " 53661.1Skamil "without signal to be sent\n"); 53671.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53681.1Skamil 53691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53711.1Skamil 53721.1Skamil validate_status_exited(status, exitval); 53731.1Skamil 53741.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53751.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53761.1Skamil} 53771.1Skamil 53781.73Skamil#define PTRACE_STEP(test, N, setstep) \ 53791.73SkamilATF_TC(test); \ 53801.73SkamilATF_TC_HEAD(test, tc) \ 53811.73Skamil{ \ 53821.73Skamil atf_tc_set_md_var(tc, "descr", \ 53831.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 53841.73Skamil} \ 53851.73Skamil \ 53861.73SkamilATF_TC_BODY(test, tc) \ 53871.73Skamil{ \ 53881.73Skamil \ 53891.95Skamil ptrace_step(N, setstep, false, false); \ 53901.1Skamil} 53911.1Skamil 53921.73SkamilPTRACE_STEP(step1, 1, 0) 53931.73SkamilPTRACE_STEP(step2, 2, 0) 53941.73SkamilPTRACE_STEP(step3, 3, 0) 53951.73SkamilPTRACE_STEP(step4, 4, 0) 53961.73SkamilPTRACE_STEP(setstep1, 1, 1) 53971.73SkamilPTRACE_STEP(setstep2, 2, 1) 53981.73SkamilPTRACE_STEP(setstep3, 3, 1) 53991.73SkamilPTRACE_STEP(setstep4, 4, 1) 54001.95Skamil 54011.95SkamilATF_TC(step_signalmasked); 54021.95SkamilATF_TC_HEAD(step_signalmasked, tc) 54031.95Skamil{ 54041.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 54051.95Skamil} 54061.95Skamil 54071.95SkamilATF_TC_BODY(step_signalmasked, tc) 54081.95Skamil{ 54091.95Skamil 54101.95Skamil ptrace_step(1, 0, true, false); 54111.95Skamil} 54121.95Skamil 54131.95SkamilATF_TC(step_signalignored); 54141.95SkamilATF_TC_HEAD(step_signalignored, tc) 54151.95Skamil{ 54161.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 54171.95Skamil} 54181.95Skamil 54191.95SkamilATF_TC_BODY(step_signalignored, tc) 54201.95Skamil{ 54211.95Skamil 54221.95Skamil ptrace_step(1, 0, false, true); 54231.95Skamil} 54241.1Skamil#endif 54251.1Skamil 54261.73Skamil/// ---------------------------------------------------------------------------- 54271.1Skamil 54281.75Skamilstatic void 54291.75Skamilptrace_kill(const char *type) 54301.1Skamil{ 54311.75Skamil const int sigval = SIGSTOP; 54321.1Skamil pid_t child, wpid; 54331.1Skamil#if defined(TWAIT_HAVE_STATUS) 54341.1Skamil int status; 54351.1Skamil#endif 54361.1Skamil 54371.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54381.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54391.1Skamil if (child == 0) { 54401.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54411.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54421.1Skamil 54431.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54441.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54451.1Skamil 54461.1Skamil /* NOTREACHED */ 54471.1Skamil FORKEE_ASSERTX(0 && 54481.1Skamil "Child should be terminated by a signal from its parent"); 54491.1Skamil } 54501.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54511.1Skamil 54521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54541.1Skamil 54551.1Skamil validate_status_stopped(status, sigval); 54561.1Skamil 54571.75Skamil DPRINTF("Before killing the child process with %s\n", type); 54581.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 54591.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 54601.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 54611.75Skamil kill(child, SIGKILL); 54621.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 54631.75Skamil setpgid(child, 0); 54641.75Skamil killpg(getpgid(child), SIGKILL); 54651.75Skamil } 54661.1Skamil 54671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54691.1Skamil 54701.75Skamil validate_status_signaled(status, SIGKILL, 0); 54711.1Skamil 54721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54731.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54741.1Skamil} 54751.1Skamil 54761.75Skamil#define PTRACE_KILL(test, type) \ 54771.75SkamilATF_TC(test); \ 54781.75SkamilATF_TC_HEAD(test, tc) \ 54791.75Skamil{ \ 54801.75Skamil atf_tc_set_md_var(tc, "descr", \ 54811.75Skamil "Verify killing the child with " type); \ 54821.75Skamil} \ 54831.75Skamil \ 54841.75SkamilATF_TC_BODY(test, tc) \ 54851.75Skamil{ \ 54861.75Skamil \ 54871.75Skamil ptrace_kill(type); \ 54881.1Skamil} 54891.1Skamil 54901.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 54911.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 54921.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 54931.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 54941.1Skamil 54951.75Skamil/// ---------------------------------------------------------------------------- 54961.1Skamil 54971.143Skamilstatic int lwpinfo_thread_sigmask[] = {SIGXCPU, SIGPIPE, SIGALRM, SIGURG}; 54981.143Skamil 54991.143Skamilstatic pthread_mutex_t lwpinfo_thread_mtx = PTHREAD_MUTEX_INITIALIZER; 55001.143Skamilstatic pthread_cond_t lwpinfo_thread_cnd = PTHREAD_COND_INITIALIZER; 55011.143Skamilstatic volatile size_t lwpinfo_thread_done; 55021.143Skamil 55031.143Skamilstatic void * 55041.143Skamillwpinfo_thread(void *arg) 55051.143Skamil{ 55061.143Skamil sigset_t s; 55071.143Skamil volatile void **tcb; 55081.143Skamil 55091.143Skamil tcb = (volatile void **)arg; 55101.143Skamil 55111.145Skamil *tcb = _lwp_getprivate(); 55121.143Skamil DPRINTF("Storing tcb[] = %p from thread %d\n", *tcb, _lwp_self()); 55131.143Skamil 55141.143Skamil pthread_setname_np(pthread_self(), "thread %d", 55151.143Skamil (void *)(intptr_t)_lwp_self()); 55161.143Skamil 55171.143Skamil sigemptyset(&s); 55181.143Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 55191.143Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 55201.143Skamil lwpinfo_thread_done++; 55211.143Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 55221.143Skamil pthread_cond_signal(&lwpinfo_thread_cnd); 55231.143Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 55241.143Skamil 55251.143Skamil return infinite_thread(NULL); 55261.143Skamil} 55271.143Skamil 55281.77Skamilstatic void 55291.143Skamiltraceme_lwpinfo(const size_t threads, const char *iter) 55301.1Skamil{ 55311.1Skamil const int sigval = SIGSTOP; 55321.77Skamil const int sigval2 = SIGINT; 55331.1Skamil pid_t child, wpid; 55341.1Skamil#if defined(TWAIT_HAVE_STATUS) 55351.1Skamil int status; 55361.1Skamil#endif 55371.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 55381.143Skamil struct ptrace_lwpstatus lwpstatus = {0}; 55391.77Skamil struct ptrace_siginfo info; 55401.143Skamil void *private; 55411.143Skamil char *name; 55421.143Skamil char namebuf[PL_LNAMELEN]; 55431.143Skamil volatile void *tcb[4]; 55441.143Skamil bool found; 55451.143Skamil sigset_t s; 55461.77Skamil 55471.77Skamil /* Maximum number of supported threads in this test */ 55481.143Skamil pthread_t t[__arraycount(tcb) - 1]; 55491.143Skamil size_t n, m; 55501.143Skamil int rv; 55511.143Skamil size_t bytes_read; 55521.143Skamil 55531.143Skamil struct ptrace_io_desc io; 55541.143Skamil sigset_t sigmask; 55551.77Skamil 55561.143Skamil ATF_REQUIRE(__arraycount(t) >= threads); 55571.143Skamil memset(tcb, 0, sizeof(tcb)); 55581.1Skamil 55591.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 55601.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 55611.1Skamil if (child == 0) { 55621.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 55631.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55641.1Skamil 55651.145Skamil tcb[0] = _lwp_getprivate(); 55661.143Skamil DPRINTF("Storing tcb[0] = %p\n", tcb[0]); 55671.143Skamil 55681.143Skamil pthread_setname_np(pthread_self(), "thread %d", 55691.143Skamil (void *)(intptr_t)_lwp_self()); 55701.143Skamil 55711.143Skamil sigemptyset(&s); 55721.143Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 55731.143Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 55741.143Skamil 55751.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 55761.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 55771.1Skamil 55781.77Skamil for (n = 0; n < threads; n++) { 55791.143Skamil rv = pthread_create(&t[n], NULL, lwpinfo_thread, 55801.143Skamil &tcb[n + 1]); 55811.77Skamil FORKEE_ASSERT(rv == 0); 55821.77Skamil } 55831.77Skamil 55841.143Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 55851.143Skamil while (lwpinfo_thread_done < threads) { 55861.143Skamil pthread_cond_wait(&lwpinfo_thread_cnd, 55871.143Skamil &lwpinfo_thread_mtx); 55881.143Skamil } 55891.143Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 55901.143Skamil 55911.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 55921.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 55931.77Skamil 55941.77Skamil /* NOTREACHED */ 55951.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 55961.1Skamil } 55971.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55981.1Skamil 55991.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56011.1Skamil 56021.1Skamil validate_status_stopped(status, sigval); 56031.1Skamil 56041.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 56051.77Skamil SYSCALL_REQUIRE( 56061.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56071.77Skamil 56081.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 56091.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 56101.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 56111.77Skamil info.psi_siginfo.si_errno); 56121.77Skamil 56131.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 56141.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 56151.77Skamil 56161.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 56171.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 56181.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 56191.143Skamil != -1); 56201.1Skamil 56211.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 56221.143Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 56231.1Skamil 56241.143Skamil DPRINTF("Assert that lwp thread %d received event " 56251.143Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 56261.143Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 56271.143Skamil 56281.143Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 56291.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPSTATUS " 56301.143Skamil "for child\n"); 56311.143Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 56321.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, &lwpstatus, 56331.143Skamil sizeof(lwpstatus)) != -1); 56341.143Skamil } 56351.1Skamil 56361.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 56371.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 56381.143Skamil != -1); 56391.1Skamil 56401.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 56411.143Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 56421.143Skamil } else { 56431.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 56441.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 56451.143Skamil sizeof(lwpstatus)) != -1); 56461.143Skamil 56471.143Skamil DPRINTF("Assert that there exists a single thread only %d\n", lwpstatus.pl_lwpid); 56481.143Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 56491.143Skamil 56501.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 56511.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 56521.143Skamil sizeof(lwpstatus)) != -1); 56531.143Skamil 56541.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 56551.143Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 56561.143Skamil } 56571.1Skamil 56581.13Schristos DPRINTF("Before resuming the child process where it left off and " 56591.1Skamil "without signal to be sent\n"); 56601.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56611.1Skamil 56621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56641.1Skamil 56651.77Skamil validate_status_stopped(status, sigval2); 56661.77Skamil 56671.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 56681.77Skamil SYSCALL_REQUIRE( 56691.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56701.77Skamil 56711.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 56721.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 56731.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 56741.77Skamil info.psi_siginfo.si_errno); 56751.77Skamil 56761.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 56771.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 56781.77Skamil 56791.77Skamil memset(&lwp, 0, sizeof(lwp)); 56801.143Skamil memset(&lwpstatus, 0, sizeof(lwpstatus)); 56811.143Skamil 56821.143Skamil memset(&io, 0, sizeof(io)); 56831.143Skamil 56841.143Skamil bytes_read = 0; 56851.143Skamil io.piod_op = PIOD_READ_D; 56861.143Skamil io.piod_len = sizeof(tcb); 56871.143Skamil 56881.143Skamil do { 56891.143Skamil io.piod_addr = (char *)&tcb + bytes_read; 56901.143Skamil io.piod_offs = io.piod_addr; 56911.143Skamil 56921.143Skamil rv = ptrace(PT_IO, child, &io, sizeof(io)); 56931.143Skamil ATF_REQUIRE(rv != -1 && io.piod_len != 0); 56941.143Skamil 56951.143Skamil bytes_read += io.piod_len; 56961.143Skamil io.piod_len = sizeof(tcb) - bytes_read; 56971.143Skamil } while (bytes_read < sizeof(tcb)); 56981.77Skamil 56991.77Skamil for (n = 0; n <= threads; n++) { 57001.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 57011.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 57021.143Skamil "child\n"); 57031.143Skamil SYSCALL_REQUIRE( 57041.143Skamil ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 57051.143Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 57061.143Skamil 57071.143Skamil DPRINTF("Assert that the thread exists\n"); 57081.143Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 57091.143Skamil 57101.143Skamil DPRINTF("Assert that lwp thread %d received expected " 57111.143Skamil "event\n", lwp.pl_lwpid); 57121.143Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 57131.143Skamil info.psi_lwpid == lwp.pl_lwpid ? 57141.143Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 57151.143Skamil 57161.143Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 57171.143Skamil DPRINTF("Before calling ptrace(2) with " 57181.143Skamil "PT_LWPSTATUS for child\n"); 57191.143Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 57201.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, 57211.143Skamil &lwpstatus, sizeof(lwpstatus)) != -1); 57221.143Skamil 57231.143Skamil goto check_lwpstatus; 57241.143Skamil } 57251.143Skamil } else { 57261.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for " 57271.143Skamil "child\n"); 57281.143Skamil SYSCALL_REQUIRE( 57291.143Skamil ptrace(PT_LWPNEXT, child, &lwpstatus, 57301.143Skamil sizeof(lwpstatus)) != -1); 57311.143Skamil DPRINTF("LWP=%d\n", lwpstatus.pl_lwpid); 57321.143Skamil 57331.143Skamil DPRINTF("Assert that the thread exists\n"); 57341.143Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 57351.143Skamil 57361.143Skamil check_lwpstatus: 57371.143Skamil 57381.143Skamil if (strstr(iter, "pl_sigmask") != NULL) { 57391.143Skamil sigmask = lwpstatus.pl_sigmask; 57401.143Skamil 57411.143Skamil DPRINTF("Retrieved sigmask: " 57421.143Skamil "%02x%02x%02x%02x\n", 57431.143Skamil sigmask.__bits[0], sigmask.__bits[1], 57441.143Skamil sigmask.__bits[2], sigmask.__bits[3]); 57451.143Skamil 57461.143Skamil found = false; 57471.143Skamil for (m = 0; 57481.143Skamil m < __arraycount(lwpinfo_thread_sigmask); 57491.143Skamil m++) { 57501.143Skamil if (sigismember(&sigmask, 57511.143Skamil lwpinfo_thread_sigmask[m])) { 57521.143Skamil found = true; 57531.143Skamil lwpinfo_thread_sigmask[m] = 0; 57541.143Skamil break; 57551.143Skamil } 57561.143Skamil } 57571.143Skamil ATF_REQUIRE(found == true); 57581.143Skamil } else if (strstr(iter, "pl_name") != NULL) { 57591.143Skamil name = lwpstatus.pl_name; 57601.143Skamil 57611.143Skamil DPRINTF("Retrieved thread name: " 57621.143Skamil "%s\n", name); 57631.143Skamil 57641.143Skamil snprintf(namebuf, sizeof namebuf, "thread %d", 57651.143Skamil lwpstatus.pl_lwpid); 57661.143Skamil 57671.143Skamil ATF_REQUIRE(strcmp(name, namebuf) == 0); 57681.143Skamil } else if (strstr(iter, "pl_private") != NULL) { 57691.143Skamil private = lwpstatus.pl_private; 57701.143Skamil 57711.143Skamil DPRINTF("Retrieved thread private pointer: " 57721.143Skamil "%p\n", private); 57731.143Skamil 57741.143Skamil found = false; 57751.143Skamil for (m = 0; m < __arraycount(tcb); m++) { 57761.143Skamil DPRINTF("Comparing %p and %p\n", 57771.143Skamil private, tcb[m]); 57781.143Skamil if (private == tcb[m]) { 57791.143Skamil found = true; 57801.143Skamil break; 57811.143Skamil } 57821.143Skamil } 57831.143Skamil ATF_REQUIRE(found == true); 57841.143Skamil } 57851.143Skamil } 57861.143Skamil } 57871.143Skamil 57881.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 57891.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 57901.143Skamil "child\n"); 57911.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 57921.143Skamil != -1); 57931.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 57941.77Skamil 57951.143Skamil DPRINTF("Assert that there are no more threads\n"); 57961.143Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 57971.143Skamil } else { 57981.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 57991.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 58001.143Skamil sizeof(lwpstatus)) != -1); 58011.77Skamil 58021.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 58031.143Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 58041.143Skamil } 58051.77Skamil 58061.77Skamil DPRINTF("Before resuming the child process where it left off and " 58071.77Skamil "without signal to be sent\n"); 58081.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 58091.77Skamil 58101.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 58111.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58121.77Skamil 58131.77Skamil validate_status_signaled(status, SIGKILL, 0); 58141.1Skamil 58151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 58161.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 58171.1Skamil} 58181.1Skamil 58191.143Skamil#define TRACEME_LWPINFO(test, threads, iter) \ 58201.77SkamilATF_TC(test); \ 58211.77SkamilATF_TC_HEAD(test, tc) \ 58221.77Skamil{ \ 58231.77Skamil atf_tc_set_md_var(tc, "descr", \ 58241.143Skamil "Verify " iter " with the child with " #threads \ 58251.77Skamil " spawned extra threads"); \ 58261.77Skamil} \ 58271.77Skamil \ 58281.77SkamilATF_TC_BODY(test, tc) \ 58291.77Skamil{ \ 58301.77Skamil \ 58311.143Skamil traceme_lwpinfo(threads, iter); \ 58321.1Skamil} 58331.1Skamil 58341.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0, "LWPINFO") 58351.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1, "LWPINFO") 58361.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2, "LWPINFO") 58371.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3, "LWPINFO") 58381.143Skamil 58391.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus, 0, "LWPINFO+LWPSTATUS") 58401.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus, 1, "LWPINFO+LWPSTATUS") 58411.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus, 2, "LWPINFO+LWPSTATUS") 58421.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus, 3, "LWPINFO+LWPSTATUS") 58431.143Skamil 58441.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_sigmask, 0, 58451.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58461.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_sigmask, 1, 58471.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58481.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_sigmask, 2, 58491.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58501.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_sigmask, 3, 58511.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58521.143Skamil 58531.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_name, 0, 58541.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58551.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_name, 1, 58561.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58571.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_name, 2, 58581.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58591.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_name, 3, 58601.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58611.143Skamil 58621.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_private, 0, 58631.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58641.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_private, 1, 58651.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58661.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_private, 2, 58671.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58681.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_private, 3, 58691.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58701.143Skamil 58711.143SkamilTRACEME_LWPINFO(traceme_lwpnext0, 0, "LWPNEXT") 58721.143SkamilTRACEME_LWPINFO(traceme_lwpnext1, 1, "LWPNEXT") 58731.143SkamilTRACEME_LWPINFO(traceme_lwpnext2, 2, "LWPNEXT") 58741.143SkamilTRACEME_LWPINFO(traceme_lwpnext3, 3, "LWPNEXT") 58751.143Skamil 58761.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_sigmask, 0, "LWPNEXT+pl_sigmask") 58771.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_sigmask, 1, "LWPNEXT+pl_sigmask") 58781.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_sigmask, 2, "LWPNEXT+pl_sigmask") 58791.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_sigmask, 3, "LWPNEXT+pl_sigmask") 58801.143Skamil 58811.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_name, 0, "LWPNEXT+pl_name") 58821.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_name, 1, "LWPNEXT+pl_name") 58831.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_name, 2, "LWPNEXT+pl_name") 58841.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_name, 3, "LWPNEXT+pl_name") 58851.143Skamil 58861.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_private, 0, "LWPNEXT+pl_private") 58871.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_private, 1, "LWPNEXT+pl_private") 58881.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_private, 2, "LWPNEXT+pl_private") 58891.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_private, 3, "LWPNEXT+pl_private") 58901.77Skamil 58911.77Skamil/// ---------------------------------------------------------------------------- 58921.77Skamil 58931.77Skamil#if defined(TWAIT_HAVE_PID) 58941.77Skamilstatic void 58951.77Skamilattach_lwpinfo(const int threads) 58961.1Skamil{ 58971.77Skamil const int sigval = SIGINT; 58981.1Skamil struct msg_fds parent_tracee, parent_tracer; 58991.1Skamil const int exitval_tracer = 10; 59001.1Skamil pid_t tracee, tracer, wpid; 59011.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 59021.1Skamil#if defined(TWAIT_HAVE_STATUS) 59031.1Skamil int status; 59041.1Skamil#endif 59051.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 59061.77Skamil struct ptrace_siginfo info; 59071.77Skamil 59081.77Skamil /* Maximum number of supported threads in this test */ 59091.77Skamil pthread_t t[3]; 59101.77Skamil int n, rv; 59111.1Skamil 59121.13Schristos DPRINTF("Spawn tracee\n"); 59131.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 59141.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 59151.1Skamil tracee = atf_utils_fork(); 59161.1Skamil if (tracee == 0) { 59171.1Skamil /* Wait for message from the parent */ 59181.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 59191.1Skamil 59201.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 59211.77Skamil 59221.77Skamil for (n = 0; n < threads; n++) { 59231.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 59241.77Skamil FORKEE_ASSERT(rv == 0); 59251.77Skamil } 59261.77Skamil 59271.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 59281.77Skamil 59291.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 59301.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 59311.77Skamil 59321.77Skamil /* NOTREACHED */ 59331.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 59341.1Skamil } 59351.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 59361.1Skamil 59371.13Schristos DPRINTF("Spawn debugger\n"); 59381.1Skamil tracer = atf_utils_fork(); 59391.1Skamil if (tracer == 0) { 59401.1Skamil /* No IPC to communicate with the child */ 59411.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 59421.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 59431.1Skamil 59441.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 59451.1Skamil FORKEE_REQUIRE_SUCCESS( 59461.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 59471.1Skamil 59481.1Skamil forkee_status_stopped(status, SIGSTOP); 59491.1Skamil 59501.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 59511.77Skamil "tracee"); 59521.77Skamil FORKEE_ASSERT( 59531.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 59541.77Skamil 59551.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 59561.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 59571.77Skamil "si_errno=%#x\n", 59581.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 59591.77Skamil info.psi_siginfo.si_errno); 59601.77Skamil 59611.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 59621.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 59631.77Skamil 59641.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 59651.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 59661.1Skamil != -1); 59671.1Skamil 59681.13Schristos DPRINTF("Assert that there exists a thread\n"); 59691.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 59701.1Skamil 59711.13Schristos DPRINTF("Assert that lwp thread %d received event " 59721.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 59731.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 59741.1Skamil 59751.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 59761.77Skamil "tracee\n"); 59771.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 59781.1Skamil != -1); 59791.1Skamil 59801.77Skamil DPRINTF("Assert that there are no more lwp threads in " 59811.77Skamil "tracee\n"); 59821.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 59831.1Skamil 59841.1Skamil /* Resume tracee with PT_CONTINUE */ 59851.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 59861.1Skamil 59871.1Skamil /* Inform parent that tracer has attached to tracee */ 59881.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 59891.77Skamil 59901.1Skamil /* Wait for parent */ 59911.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 59921.1Skamil 59931.77Skamil /* Wait for tracee and assert that it raised a signal */ 59941.77Skamil FORKEE_REQUIRE_SUCCESS( 59951.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 59961.77Skamil 59971.77Skamil forkee_status_stopped(status, SIGINT); 59981.77Skamil 59991.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 60001.77Skamil "child"); 60011.77Skamil FORKEE_ASSERT( 60021.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 60031.77Skamil 60041.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 60051.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 60061.77Skamil "si_errno=%#x\n", 60071.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 60081.77Skamil info.psi_siginfo.si_errno); 60091.77Skamil 60101.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 60111.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 60121.77Skamil 60131.77Skamil memset(&lwp, 0, sizeof(lwp)); 60141.77Skamil 60151.77Skamil for (n = 0; n <= threads; n++) { 60161.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 60171.77Skamil "child\n"); 60181.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 60191.77Skamil sizeof(lwp)) != -1); 60201.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 60211.77Skamil 60221.77Skamil DPRINTF("Assert that the thread exists\n"); 60231.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 60241.77Skamil 60251.77Skamil DPRINTF("Assert that lwp thread %d received expected " 60261.77Skamil "event\n", lwp.pl_lwpid); 60271.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 60281.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 60291.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 60301.77Skamil } 60311.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 60321.77Skamil "tracee\n"); 60331.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 60341.77Skamil != -1); 60351.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 60361.77Skamil 60371.77Skamil DPRINTF("Assert that there are no more threads\n"); 60381.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 60391.77Skamil 60401.77Skamil DPRINTF("Before resuming the child process where it left off " 60411.77Skamil "and without signal to be sent\n"); 60421.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 60431.77Skamil != -1); 60441.77Skamil 60451.1Skamil /* Wait for tracee and assert that it exited */ 60461.1Skamil FORKEE_REQUIRE_SUCCESS( 60471.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 60481.1Skamil 60491.77Skamil forkee_status_signaled(status, SIGKILL, 0); 60501.1Skamil 60511.13Schristos DPRINTF("Before exiting of the tracer process\n"); 60521.1Skamil _exit(exitval_tracer); 60531.1Skamil } 60541.1Skamil 60551.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 60561.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 60571.1Skamil 60581.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 60591.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 60601.77Skamil 60611.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 60621.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 60631.1Skamil 60641.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 60651.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 60661.1Skamil 60671.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 60681.1Skamil TWAIT_FNAME); 60691.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 60701.1Skamil tracer); 60711.1Skamil 60721.1Skamil validate_status_exited(status, exitval_tracer); 60731.1Skamil 60741.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 60751.1Skamil TWAIT_FNAME); 60761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 60771.1Skamil tracee); 60781.1Skamil 60791.77Skamil validate_status_signaled(status, SIGKILL, 0); 60801.1Skamil 60811.1Skamil msg_close(&parent_tracer); 60821.1Skamil msg_close(&parent_tracee); 60831.1Skamil} 60841.77Skamil 60851.77Skamil#define ATTACH_LWPINFO(test, threads) \ 60861.77SkamilATF_TC(test); \ 60871.77SkamilATF_TC_HEAD(test, tc) \ 60881.77Skamil{ \ 60891.77Skamil atf_tc_set_md_var(tc, "descr", \ 60901.77Skamil "Verify LWPINFO with the child with " #threads \ 60911.77Skamil " spawned extra threads (tracer is not the original " \ 60921.77Skamil "parent)"); \ 60931.77Skamil} \ 60941.77Skamil \ 60951.77SkamilATF_TC_BODY(test, tc) \ 60961.77Skamil{ \ 60971.77Skamil \ 60981.77Skamil attach_lwpinfo(threads); \ 60991.77Skamil} 61001.77Skamil 61011.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 61021.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 61031.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 61041.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 61051.1Skamil#endif 61061.1Skamil 61071.77Skamil/// ---------------------------------------------------------------------------- 61081.77Skamil 61091.1Skamilstatic void 61101.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 61111.1Skamil{ 61121.1Skamil const int exitval = 5; 61131.1Skamil const int sigval = SIGINT; 61141.1Skamil const int sigfaked = SIGTRAP; 61151.1Skamil const int sicodefaked = TRAP_BRKPT; 61161.1Skamil pid_t child, wpid; 61171.1Skamil struct sigaction sa; 61181.1Skamil#if defined(TWAIT_HAVE_STATUS) 61191.1Skamil int status; 61201.1Skamil#endif 61211.1Skamil struct ptrace_siginfo info; 61221.1Skamil memset(&info, 0, sizeof(info)); 61231.1Skamil 61241.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61251.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61261.1Skamil if (child == 0) { 61271.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61281.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61291.1Skamil 61301.79Skamil sa.sa_sigaction = sah; 61311.1Skamil sa.sa_flags = SA_SIGINFO; 61321.1Skamil sigemptyset(&sa.sa_mask); 61331.1Skamil 61341.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 61351.79Skamil != -1); 61361.1Skamil 61371.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61381.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61391.1Skamil 61401.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 61411.1Skamil 61421.13Schristos DPRINTF("Before exiting of the child process\n"); 61431.1Skamil _exit(exitval); 61441.1Skamil } 61451.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61461.1Skamil 61471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61491.1Skamil 61501.1Skamil validate_status_stopped(status, sigval); 61511.1Skamil 61521.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 61531.61Skre SYSCALL_REQUIRE( 61541.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 61551.1Skamil 61561.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 61571.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 61581.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 61591.1Skamil info.psi_siginfo.si_errno); 61601.1Skamil 61611.79Skamil if (faked) { 61621.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 61631.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 61641.79Skamil info.psi_siginfo.si_signo = sigfaked; 61651.79Skamil info.psi_siginfo.si_code = sicodefaked; 61661.79Skamil } 61671.1Skamil 61681.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 61691.61Skre SYSCALL_REQUIRE( 61701.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 61711.1Skamil 61721.79Skamil if (faked) { 61731.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 61741.79Skamil "child\n"); 61751.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 61761.79Skamil sizeof(info)) != -1); 61771.1Skamil 61781.79Skamil DPRINTF("Before checking siginfo_t\n"); 61791.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 61801.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 61811.79Skamil } 61821.1Skamil 61831.13Schristos DPRINTF("Before resuming the child process where it left off and " 61841.1Skamil "without signal to be sent\n"); 61851.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 61861.79Skamil faked ? sigfaked : sigval) != -1); 61871.1Skamil 61881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61901.1Skamil 61911.1Skamil validate_status_exited(status, exitval); 61921.1Skamil 61931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61941.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 61951.1Skamil} 61961.1Skamil 61971.79Skamil#define PTRACE_SIGINFO(test, faked) \ 61981.79SkamilATF_TC(test); \ 61991.79SkamilATF_TC_HEAD(test, tc) \ 62001.79Skamil{ \ 62011.79Skamil atf_tc_set_md_var(tc, "descr", \ 62021.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 62031.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 62041.79Skamil} \ 62051.79Skamil \ 62061.79Skamilstatic int test##_caught = 0; \ 62071.79Skamil \ 62081.79Skamilstatic void \ 62091.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 62101.79Skamil{ \ 62111.79Skamil if (faked) { \ 62121.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 62131.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 62141.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 62151.79Skamil } else { \ 62161.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 62171.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 62181.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 62191.79Skamil } \ 62201.79Skamil \ 62211.79Skamil ++ test##_caught; \ 62221.79Skamil} \ 62231.79Skamil \ 62241.79SkamilATF_TC_BODY(test, tc) \ 62251.79Skamil{ \ 62261.79Skamil \ 62271.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 62281.79Skamil} 62291.79Skamil 62301.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 62311.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 62321.79Skamil 62331.79Skamil/// ---------------------------------------------------------------------------- 62341.79Skamil 62351.97Skamilstatic void 62361.97Skamiltraceme_exec(bool masked, bool ignored) 62371.1Skamil{ 62381.1Skamil const int sigval = SIGTRAP; 62391.1Skamil pid_t child, wpid; 62401.1Skamil#if defined(TWAIT_HAVE_STATUS) 62411.1Skamil int status; 62421.1Skamil#endif 62431.97Skamil struct sigaction sa; 62441.97Skamil struct ptrace_siginfo info; 62451.97Skamil sigset_t intmask; 62461.97Skamil struct kinfo_proc2 kp; 62471.97Skamil size_t len = sizeof(kp); 62481.97Skamil 62491.97Skamil int name[6]; 62501.97Skamil const size_t namelen = __arraycount(name); 62511.97Skamil ki_sigset_t kp_sigmask; 62521.97Skamil ki_sigset_t kp_sigignore; 62531.1Skamil 62541.1Skamil memset(&info, 0, sizeof(info)); 62551.1Skamil 62561.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62571.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62581.1Skamil if (child == 0) { 62591.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62601.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62611.1Skamil 62621.97Skamil if (masked) { 62631.97Skamil sigemptyset(&intmask); 62641.97Skamil sigaddset(&intmask, sigval); 62651.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62661.97Skamil } 62671.97Skamil 62681.97Skamil if (ignored) { 62691.97Skamil memset(&sa, 0, sizeof(sa)); 62701.97Skamil sa.sa_handler = SIG_IGN; 62711.97Skamil sigemptyset(&sa.sa_mask); 62721.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 62731.97Skamil } 62741.97Skamil 62751.13Schristos DPRINTF("Before calling execve(2) from child\n"); 62761.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 62771.1Skamil 62781.1Skamil FORKEE_ASSERT(0 && "Not reached"); 62791.1Skamil } 62801.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62811.1Skamil 62821.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62841.1Skamil 62851.1Skamil validate_status_stopped(status, sigval); 62861.1Skamil 62871.97Skamil name[0] = CTL_KERN, 62881.97Skamil name[1] = KERN_PROC2, 62891.97Skamil name[2] = KERN_PROC_PID; 62901.97Skamil name[3] = getpid(); 62911.97Skamil name[4] = sizeof(kp); 62921.97Skamil name[5] = 1; 62931.97Skamil 62941.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 62951.97Skamil 62961.97Skamil if (masked) 62971.97Skamil kp_sigmask = kp.p_sigmask; 62981.97Skamil 62991.97Skamil if (ignored) 63001.97Skamil kp_sigignore = kp.p_sigignore; 63011.97Skamil 63021.97Skamil name[3] = getpid(); 63031.97Skamil 63041.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 63051.97Skamil 63061.97Skamil if (masked) { 63071.97Skamil DPRINTF("kp_sigmask=" 63081.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 63091.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 63101.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 63111.97Skamil 63121.97Skamil DPRINTF("kp.p_sigmask=" 63131.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 63141.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 63151.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 63161.97Skamil 63171.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 63181.97Skamil sizeof(kp_sigmask))); 63191.97Skamil } 63201.97Skamil 63211.97Skamil if (ignored) { 63221.97Skamil DPRINTF("kp_sigignore=" 63231.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 63241.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 63251.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 63261.97Skamil 63271.97Skamil DPRINTF("kp.p_sigignore=" 63281.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 63291.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 63301.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 63311.97Skamil 63321.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 63331.97Skamil sizeof(kp_sigignore))); 63341.97Skamil } 63351.97Skamil 63361.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 63371.61Skre SYSCALL_REQUIRE( 63381.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 63391.1Skamil 63401.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 63411.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 63421.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 63431.1Skamil info.psi_siginfo.si_errno); 63441.1Skamil 63451.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 63461.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 63471.1Skamil 63481.13Schristos DPRINTF("Before resuming the child process where it left off and " 63491.1Skamil "without signal to be sent\n"); 63501.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63511.1Skamil 63521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63541.1Skamil 63551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63561.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63571.1Skamil} 63581.1Skamil 63591.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 63601.97SkamilATF_TC(test); \ 63611.97SkamilATF_TC_HEAD(test, tc) \ 63621.97Skamil{ \ 63631.97Skamil atf_tc_set_md_var(tc, "descr", \ 63641.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 63651.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 63661.97Skamil masked ? " with ignored signal" : ""); \ 63671.97Skamil} \ 63681.97Skamil \ 63691.97SkamilATF_TC_BODY(test, tc) \ 63701.97Skamil{ \ 63711.97Skamil \ 63721.97Skamil traceme_exec(masked, ignored); \ 63731.97Skamil} 63741.97Skamil 63751.97SkamilTRACEME_EXEC(traceme_exec, false, false) 63761.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 63771.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 63781.97Skamil 63791.82Skamil/// ---------------------------------------------------------------------------- 63801.82Skamil 63811.135Skamil#define TRACE_THREADS_NUM 100 63821.135Skamil 63831.83Skamilstatic volatile int done; 63841.137Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER; 63851.1Skamil 63861.83Skamilstatic void * 63871.83Skamiltrace_threads_cb(void *arg __unused) 63881.1Skamil{ 63891.1Skamil 63901.137Skamil pthread_mutex_lock(&trace_threads_mtx); 63911.83Skamil done++; 63921.137Skamil pthread_mutex_unlock(&trace_threads_mtx); 63931.83Skamil 63941.135Skamil while (done < TRACE_THREADS_NUM) 63951.135Skamil sched_yield(); 63961.83Skamil 63971.83Skamil return NULL; 63981.1Skamil} 63991.1Skamil 64001.83Skamilstatic void 64011.153Skamiltrace_threads(bool trace_create, bool trace_exit, bool masked) 64021.1Skamil{ 64031.1Skamil const int sigval = SIGSTOP; 64041.1Skamil pid_t child, wpid; 64051.1Skamil#if defined(TWAIT_HAVE_STATUS) 64061.1Skamil int status; 64071.1Skamil#endif 64081.1Skamil ptrace_state_t state; 64091.1Skamil const int slen = sizeof(state); 64101.1Skamil ptrace_event_t event; 64111.1Skamil const int elen = sizeof(event); 64121.83Skamil struct ptrace_siginfo info; 64131.83Skamil 64141.153Skamil sigset_t intmask; 64151.153Skamil 64161.135Skamil pthread_t t[TRACE_THREADS_NUM]; 64171.83Skamil int rv; 64181.83Skamil size_t n; 64191.1Skamil lwpid_t lid; 64201.83Skamil 64211.83Skamil /* Track created and exited threads */ 64221.141Skamil struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}}; 64231.83Skamil 64241.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64251.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64261.1Skamil if (child == 0) { 64271.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64281.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64291.1Skamil 64301.153Skamil if (masked) { 64311.153Skamil sigemptyset(&intmask); 64321.153Skamil sigaddset(&intmask, SIGTRAP); 64331.153Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 64341.153Skamil } 64351.153Skamil 64361.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64371.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64381.1Skamil 64391.83Skamil for (n = 0; n < __arraycount(t); n++) { 64401.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 64411.83Skamil NULL); 64421.83Skamil FORKEE_ASSERT(rv == 0); 64431.83Skamil } 64441.1Skamil 64451.83Skamil for (n = 0; n < __arraycount(t); n++) { 64461.83Skamil rv = pthread_join(t[n], NULL); 64471.83Skamil FORKEE_ASSERT(rv == 0); 64481.83Skamil } 64491.1Skamil 64501.83Skamil /* 64511.83Skamil * There is race between _exit() and pthread_join() detaching 64521.83Skamil * a thread. For simplicity kill the process after detecting 64531.83Skamil * LWP events. 64541.83Skamil */ 64551.83Skamil while (true) 64561.83Skamil continue; 64571.1Skamil 64581.83Skamil FORKEE_ASSERT(0 && "Not reached"); 64591.1Skamil } 64601.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64611.1Skamil 64621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64641.1Skamil 64651.1Skamil validate_status_stopped(status, sigval); 64661.1Skamil 64671.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 64681.83Skamil SYSCALL_REQUIRE( 64691.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 64701.1Skamil 64711.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 64721.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 64731.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 64741.83Skamil info.psi_siginfo.si_errno); 64751.1Skamil 64761.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 64771.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 64781.1Skamil 64791.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 64801.83Skamil memset(&event, 0, sizeof(event)); 64811.83Skamil if (trace_create) 64821.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 64831.83Skamil if (trace_exit) 64841.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 64851.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 64861.1Skamil 64871.13Schristos DPRINTF("Before resuming the child process where it left off and " 64881.1Skamil "without signal to be sent\n"); 64891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64901.1Skamil 64911.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 64921.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 64931.83Skamil "SIGTRAP\n", TWAIT_FNAME); 64941.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 64951.83Skamil child); 64961.1Skamil 64971.83Skamil validate_status_stopped(status, SIGTRAP); 64981.1Skamil 64991.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 65001.83Skamil "child\n"); 65011.83Skamil SYSCALL_REQUIRE( 65021.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 65031.1Skamil 65041.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 65051.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 65061.83Skamil "si_errno=%#x\n", 65071.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 65081.83Skamil info.psi_siginfo.si_errno); 65091.1Skamil 65101.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 65111.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 65121.1Skamil 65131.83Skamil SYSCALL_REQUIRE( 65141.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 65151.1Skamil 65161.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 65171.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 65181.1Skamil 65191.83Skamil lid = state.pe_lwp; 65201.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 65211.1Skamil 65221.141Skamil *FIND_EVENT_COUNT(traced_lwps, lid) += 1; 65231.1Skamil 65241.83Skamil DPRINTF("Before resuming the child process where it left off " 65251.83Skamil "and without signal to be sent\n"); 65261.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65271.83Skamil } 65281.1Skamil 65291.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 65301.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 65311.83Skamil "SIGTRAP\n", TWAIT_FNAME); 65321.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 65331.83Skamil child); 65341.1Skamil 65351.83Skamil validate_status_stopped(status, SIGTRAP); 65361.1Skamil 65371.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 65381.83Skamil "child\n"); 65391.83Skamil SYSCALL_REQUIRE( 65401.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 65411.1Skamil 65421.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 65431.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 65441.83Skamil "si_errno=%#x\n", 65451.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 65461.83Skamil info.psi_siginfo.si_errno); 65471.1Skamil 65481.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 65491.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 65501.1Skamil 65511.83Skamil SYSCALL_REQUIRE( 65521.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 65531.1Skamil 65541.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 65551.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 65561.1Skamil 65571.83Skamil lid = state.pe_lwp; 65581.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 65591.1Skamil 65601.83Skamil if (trace_create) { 65611.141Skamil int *count = FIND_EVENT_COUNT(traced_lwps, lid); 65621.141Skamil ATF_REQUIRE_EQ(*count, 1); 65631.141Skamil *count = 0; 65641.83Skamil } 65651.1Skamil 65661.83Skamil DPRINTF("Before resuming the child process where it left off " 65671.83Skamil "and without signal to be sent\n"); 65681.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65691.83Skamil } 65701.1Skamil 65711.83Skamil kill(child, SIGKILL); 65721.1Skamil 65731.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65741.1Skamil TWAIT_FNAME); 65751.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65761.1Skamil 65771.83Skamil validate_status_signaled(status, SIGKILL, 0); 65781.1Skamil 65791.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65801.1Skamil TWAIT_FNAME); 65811.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65821.1Skamil} 65831.1Skamil 65841.153Skamil#define TRACE_THREADS(test, trace_create, trace_exit, mask) \ 65851.83SkamilATF_TC(test); \ 65861.83SkamilATF_TC_HEAD(test, tc) \ 65871.83Skamil{ \ 65881.83Skamil atf_tc_set_md_var(tc, "descr", \ 65891.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 65901.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 65911.83Skamil trace_exit ? "" : "out"); \ 65921.83Skamil} \ 65931.83Skamil \ 65941.83SkamilATF_TC_BODY(test, tc) \ 65951.83Skamil{ \ 65961.83Skamil \ 65971.153Skamil trace_threads(trace_create, trace_exit, mask); \ 65981.83Skamil} 65991.83Skamil 66001.153SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false, false) 66011.153SkamilTRACE_THREADS(trace_thread_lwpexit, false, true, false) 66021.153SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false, false) 66031.153SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true, false) 66041.153Skamil 66051.153SkamilTRACE_THREADS(trace_thread_lwpexit_masked_sigtrap, false, true, true) 66061.153SkamilTRACE_THREADS(trace_thread_lwpcreate_masked_sigtrap, true, false, true) 66071.153SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit_masked_sigtrap, true, true, true) 66081.83Skamil 66091.83Skamil/// ---------------------------------------------------------------------------- 66101.83Skamil 66111.84SkamilATF_TC(signal_mask_unrelated); 66121.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 66131.1Skamil{ 66141.1Skamil atf_tc_set_md_var(tc, "descr", 66151.1Skamil "Verify that masking single unrelated signal does not stop tracer " 66161.1Skamil "from catching other signals"); 66171.1Skamil} 66181.1Skamil 66191.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 66201.1Skamil{ 66211.1Skamil const int exitval = 5; 66221.1Skamil const int sigval = SIGSTOP; 66231.1Skamil const int sigmasked = SIGTRAP; 66241.1Skamil const int signotmasked = SIGINT; 66251.1Skamil pid_t child, wpid; 66261.1Skamil#if defined(TWAIT_HAVE_STATUS) 66271.1Skamil int status; 66281.1Skamil#endif 66291.1Skamil sigset_t intmask; 66301.1Skamil 66311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66331.1Skamil if (child == 0) { 66341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66361.1Skamil 66371.1Skamil sigemptyset(&intmask); 66381.1Skamil sigaddset(&intmask, sigmasked); 66391.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 66401.1Skamil 66411.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66421.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66431.1Skamil 66441.13Schristos DPRINTF("Before raising %s from child\n", 66451.1Skamil strsignal(signotmasked)); 66461.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 66471.1Skamil 66481.13Schristos DPRINTF("Before exiting of the child process\n"); 66491.1Skamil _exit(exitval); 66501.1Skamil } 66511.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66521.1Skamil 66531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66551.1Skamil 66561.1Skamil validate_status_stopped(status, sigval); 66571.1Skamil 66581.13Schristos DPRINTF("Before resuming the child process where it left off and " 66591.1Skamil "without signal to be sent\n"); 66601.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66611.1Skamil 66621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66641.1Skamil 66651.1Skamil validate_status_stopped(status, signotmasked); 66661.1Skamil 66671.13Schristos DPRINTF("Before resuming the child process where it left off and " 66681.1Skamil "without signal to be sent\n"); 66691.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66701.1Skamil 66711.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66721.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66731.1Skamil 66741.1Skamil validate_status_exited(status, exitval); 66751.1Skamil 66761.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66771.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66781.1Skamil} 66791.1Skamil 66801.84Skamil/// ---------------------------------------------------------------------------- 66811.84Skamil 66821.1Skamil#if defined(TWAIT_HAVE_PID) 66831.99Skamilstatic void 66841.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 66851.1Skamil{ 66861.1Skamil const int exitval = 5; 66871.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 66881.1Skamil const int sigval = SIGSTOP; 66891.99Skamil pid_t child, child2 = 0, wpid; 66901.1Skamil#if defined(TWAIT_HAVE_STATUS) 66911.1Skamil int status; 66921.1Skamil#endif 66931.1Skamil ptrace_state_t state; 66941.1Skamil const int slen = sizeof(state); 66951.1Skamil ptrace_event_t event; 66961.1Skamil const int elen = sizeof(event); 66971.99Skamil struct sigaction sa; 66981.99Skamil struct ptrace_siginfo info; 66991.99Skamil sigset_t intmask; 67001.99Skamil struct kinfo_proc2 kp; 67011.99Skamil size_t len = sizeof(kp); 67021.99Skamil 67031.99Skamil int name[6]; 67041.99Skamil const size_t namelen = __arraycount(name); 67051.99Skamil ki_sigset_t kp_sigmask; 67061.99Skamil ki_sigset_t kp_sigignore; 67071.1Skamil 67081.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 67091.14Schristos 67101.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 67111.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 67121.1Skamil if (child == 0) { 67131.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67141.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67151.1Skamil 67161.99Skamil if (masked) { 67171.99Skamil sigemptyset(&intmask); 67181.99Skamil sigaddset(&intmask, SIGTRAP); 67191.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 67201.99Skamil } 67211.99Skamil 67221.99Skamil if (ignored) { 67231.99Skamil memset(&sa, 0, sizeof(sa)); 67241.99Skamil sa.sa_handler = SIG_IGN; 67251.99Skamil sigemptyset(&sa.sa_mask); 67261.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 67271.99Skamil } 67281.1Skamil 67291.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67301.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67311.1Skamil 67321.126Skamil if (strcmp(fn, "spawn") == 0) { 67331.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 67341.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 67351.126Skamil } else { 67361.126Skamil if (strcmp(fn, "fork") == 0) { 67371.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 67381.126Skamil } else { 67391.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 67401.126Skamil } 67411.126Skamil if (child2 == 0) 67421.126Skamil _exit(exitval2); 67431.126Skamil } 67441.1Skamil 67451.1Skamil FORKEE_REQUIRE_SUCCESS 67461.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 67471.1Skamil 67481.1Skamil forkee_status_exited(status, exitval2); 67491.1Skamil 67501.13Schristos DPRINTF("Before exiting of the child process\n"); 67511.1Skamil _exit(exitval); 67521.1Skamil } 67531.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67541.1Skamil 67551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67571.1Skamil 67581.1Skamil validate_status_stopped(status, sigval); 67591.1Skamil 67601.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67611.99Skamil SYSCALL_REQUIRE( 67621.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67631.99Skamil 67641.99Skamil DPRINTF("Before checking siginfo_t\n"); 67651.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 67661.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 67671.1Skamil 67681.99Skamil name[0] = CTL_KERN, 67691.99Skamil name[1] = KERN_PROC2, 67701.99Skamil name[2] = KERN_PROC_PID; 67711.99Skamil name[3] = child; 67721.99Skamil name[4] = sizeof(kp); 67731.99Skamil name[5] = 1; 67741.1Skamil 67751.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 67761.1Skamil 67771.99Skamil if (masked) 67781.99Skamil kp_sigmask = kp.p_sigmask; 67791.1Skamil 67801.99Skamil if (ignored) 67811.99Skamil kp_sigignore = kp.p_sigignore; 67821.1Skamil 67831.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 67841.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 67851.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 67861.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 67871.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 67881.99Skamil event.pe_set_event = 0; 67891.126Skamil if (strcmp(fn, "spawn") == 0) 67901.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 67911.126Skamil if (strcmp(fn, "fork") == 0) 67921.99Skamil event.pe_set_event |= PTRACE_FORK; 67931.126Skamil if (strcmp(fn, "vfork") == 0) 67941.99Skamil event.pe_set_event |= PTRACE_VFORK; 67951.126Skamil if (strcmp(fn, "vforkdone") == 0) 67961.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 67971.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 67981.1Skamil 67991.99Skamil DPRINTF("Before resuming the child process where it left off and " 68001.99Skamil "without signal to be sent\n"); 68011.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68021.1Skamil 68031.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 68041.126Skamil strcmp(fn, "vfork") == 0) { 68051.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68061.99Skamil child); 68071.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 68081.99Skamil child); 68091.1Skamil 68101.99Skamil validate_status_stopped(status, SIGTRAP); 68111.1Skamil 68121.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 68131.1Skamil 68141.99Skamil if (masked) { 68151.99Skamil DPRINTF("kp_sigmask=" 68161.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68171.99Skamil PRIx32 "\n", 68181.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 68191.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 68201.1Skamil 68211.99Skamil DPRINTF("kp.p_sigmask=" 68221.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68231.99Skamil PRIx32 "\n", 68241.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 68251.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 68261.1Skamil 68271.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 68281.99Skamil sizeof(kp_sigmask))); 68291.99Skamil } 68301.1Skamil 68311.99Skamil if (ignored) { 68321.99Skamil DPRINTF("kp_sigignore=" 68331.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68341.99Skamil PRIx32 "\n", 68351.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 68361.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 68371.1Skamil 68381.99Skamil DPRINTF("kp.p_sigignore=" 68391.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68401.99Skamil PRIx32 "\n", 68411.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 68421.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 68431.1Skamil 68441.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 68451.99Skamil sizeof(kp_sigignore))); 68461.99Skamil } 68471.1Skamil 68481.99Skamil SYSCALL_REQUIRE( 68491.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68501.126Skamil if (strcmp(fn, "spawn") == 0) { 68511.126Skamil ATF_REQUIRE_EQ( 68521.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 68531.126Skamil PTRACE_POSIX_SPAWN); 68541.126Skamil } 68551.126Skamil if (strcmp(fn, "fork") == 0) { 68561.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68571.99Skamil PTRACE_FORK); 68581.99Skamil } 68591.126Skamil if (strcmp(fn, "vfork") == 0) { 68601.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68611.99Skamil PTRACE_VFORK); 68621.99Skamil } 68631.1Skamil 68641.99Skamil child2 = state.pe_other_pid; 68651.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 68661.1Skamil 68671.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 68681.99Skamil "%d\n", TWAIT_FNAME, child2, child); 68691.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 68701.99Skamil child2); 68711.1Skamil 68721.99Skamil validate_status_stopped(status, SIGTRAP); 68731.1Skamil 68741.99Skamil name[3] = child2; 68751.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 68761.1Skamil 68771.99Skamil if (masked) { 68781.99Skamil DPRINTF("kp_sigmask=" 68791.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68801.99Skamil PRIx32 "\n", 68811.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 68821.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 68831.1Skamil 68841.99Skamil DPRINTF("kp.p_sigmask=" 68851.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68861.99Skamil PRIx32 "\n", 68871.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 68881.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 68891.14Schristos 68901.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 68911.99Skamil sizeof(kp_sigmask))); 68921.99Skamil } 68931.1Skamil 68941.99Skamil if (ignored) { 68951.99Skamil DPRINTF("kp_sigignore=" 68961.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68971.99Skamil PRIx32 "\n", 68981.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 68991.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 69001.1Skamil 69011.99Skamil DPRINTF("kp.p_sigignore=" 69021.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69031.99Skamil PRIx32 "\n", 69041.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 69051.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 69061.1Skamil 69071.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 69081.99Skamil sizeof(kp_sigignore))); 69091.99Skamil } 69101.1Skamil 69111.99Skamil SYSCALL_REQUIRE( 69121.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 69131.126Skamil if (strcmp(fn, "spawn") == 0) { 69141.126Skamil ATF_REQUIRE_EQ( 69151.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 69161.126Skamil PTRACE_POSIX_SPAWN); 69171.126Skamil } 69181.126Skamil if (strcmp(fn, "fork") == 0) { 69191.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69201.99Skamil PTRACE_FORK); 69211.99Skamil } 69221.126Skamil if (strcmp(fn, "vfork") == 0) { 69231.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69241.99Skamil PTRACE_VFORK); 69251.99Skamil } 69261.1Skamil 69271.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 69281.1Skamil 69291.99Skamil DPRINTF("Before resuming the forkee process where it left off " 69301.99Skamil "and without signal to be sent\n"); 69311.99Skamil SYSCALL_REQUIRE( 69321.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 69331.1Skamil 69341.99Skamil DPRINTF("Before resuming the child process where it left off " 69351.99Skamil "and without signal to be sent\n"); 69361.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69371.1Skamil } 69381.1Skamil 69391.126Skamil if (strcmp(fn, "vforkdone") == 0) { 69401.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69411.99Skamil child); 69421.99Skamil TWAIT_REQUIRE_SUCCESS( 69431.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 69441.1Skamil 69451.99Skamil validate_status_stopped(status, SIGTRAP); 69461.1Skamil 69471.99Skamil name[3] = child; 69481.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 69491.1Skamil 69501.102Skamil /* 69511.102Skamil * SIGCHLD is now pending in the signal queue and 69521.102Skamil * the kernel presents it to userland as a masked signal. 69531.102Skamil */ 69541.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 69551.102Skamil 69561.99Skamil if (masked) { 69571.99Skamil DPRINTF("kp_sigmask=" 69581.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69591.99Skamil PRIx32 "\n", 69601.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 69611.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 69621.1Skamil 69631.99Skamil DPRINTF("kp.p_sigmask=" 69641.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69651.99Skamil PRIx32 "\n", 69661.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 69671.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 69681.1Skamil 69691.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 69701.99Skamil sizeof(kp_sigmask))); 69711.99Skamil } 69721.1Skamil 69731.99Skamil if (ignored) { 69741.99Skamil DPRINTF("kp_sigignore=" 69751.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69761.99Skamil PRIx32 "\n", 69771.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 69781.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 69791.1Skamil 69801.99Skamil DPRINTF("kp.p_sigignore=" 69811.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69821.99Skamil PRIx32 "\n", 69831.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 69841.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 69851.1Skamil 69861.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 69871.99Skamil sizeof(kp_sigignore))); 69881.99Skamil } 69891.1Skamil 69901.99Skamil SYSCALL_REQUIRE( 69911.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69921.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 69931.1Skamil 69941.99Skamil child2 = state.pe_other_pid; 69951.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 69961.99Skamil child2); 69971.1Skamil 69981.99Skamil DPRINTF("Before resuming the child process where it left off " 69991.99Skamil "and without signal to be sent\n"); 70001.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70011.99Skamil } 70021.1Skamil 70031.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 70041.126Skamil strcmp(fn, "vfork") == 0) { 70051.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 70061.99Skamil "\n", TWAIT_FNAME); 70071.99Skamil TWAIT_REQUIRE_SUCCESS( 70081.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 70091.1Skamil 70101.99Skamil validate_status_exited(status, exitval2); 70111.1Skamil 70121.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 70131.99Skamil "process\n", TWAIT_FNAME); 70141.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 70151.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 70161.99Skamil } 70171.1Skamil 70181.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 70191.1Skamil "SIGCHLD\n", TWAIT_FNAME); 70201.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70211.1Skamil 70221.1Skamil validate_status_stopped(status, SIGCHLD); 70231.1Skamil 70241.57Skamil DPRINTF("Before resuming the child process where it left off and " 70251.1Skamil "without signal to be sent\n"); 70261.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70271.1Skamil 70281.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 70291.1Skamil TWAIT_FNAME); 70301.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70311.1Skamil 70321.1Skamil validate_status_exited(status, exitval); 70331.1Skamil 70341.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 70351.57Skamil TWAIT_FNAME); 70361.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 70371.1Skamil} 70381.1Skamil 70391.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 70401.99SkamilATF_TC(name); \ 70411.99SkamilATF_TC_HEAD(name, tc) \ 70421.99Skamil{ \ 70431.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 70441.99Skamil "regardless of signal %s%s", \ 70451.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 70461.99Skamil} \ 70471.99Skamil \ 70481.99SkamilATF_TC_BODY(name, tc) \ 70491.99Skamil{ \ 70501.99Skamil \ 70511.126Skamil fork2_body(fn, masked, ignored); \ 70521.1Skamil} 70531.1Skamil 70541.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 70551.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 70561.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 70571.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 70581.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 70591.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 70601.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 70611.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 70621.1Skamil#endif 70631.1Skamil 70641.99Skamil/// ---------------------------------------------------------------------------- 70651.1Skamil 70661.151Skamilstatic void * 70671.151Skamilthread_and_exec_thread_cb(void *arg __unused) 70681.151Skamil{ 70691.151Skamil 70701.151Skamil execlp("/bin/echo", "/bin/echo", NULL); 70711.151Skamil 70721.151Skamil abort(); 70731.151Skamil} 70741.151Skamil 70751.151Skamilstatic void 70761.151Skamilthreads_and_exec(void) 70771.151Skamil{ 70781.151Skamil const int sigval = SIGSTOP; 70791.151Skamil pid_t child, wpid; 70801.151Skamil#if defined(TWAIT_HAVE_STATUS) 70811.151Skamil int status; 70821.151Skamil#endif 70831.151Skamil ptrace_state_t state; 70841.151Skamil const int slen = sizeof(state); 70851.151Skamil ptrace_event_t event; 70861.151Skamil const int elen = sizeof(event); 70871.151Skamil struct ptrace_siginfo info; 70881.151Skamil 70891.151Skamil pthread_t t; 70901.151Skamil lwpid_t lid; 70911.151Skamil 70921.151Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 70931.151Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70941.151Skamil if (child == 0) { 70951.151Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70961.151Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70971.151Skamil 70981.151Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70991.151Skamil FORKEE_ASSERT(raise(sigval) == 0); 71001.151Skamil 71011.151Skamil FORKEE_ASSERT(pthread_create(&t, NULL, 71021.151Skamil thread_and_exec_thread_cb, NULL) == 0); 71031.151Skamil 71041.151Skamil for (;;) 71051.151Skamil continue; 71061.151Skamil 71071.151Skamil FORKEE_ASSERT(0 && "Not reached"); 71081.151Skamil } 71091.151Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 71101.151Skamil 71111.151Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 71121.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71131.151Skamil 71141.151Skamil validate_status_stopped(status, sigval); 71151.151Skamil 71161.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 71171.151Skamil SYSCALL_REQUIRE( 71181.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71191.151Skamil 71201.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71211.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 71221.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71231.151Skamil info.psi_siginfo.si_errno); 71241.151Skamil 71251.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 71261.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71271.151Skamil 71281.151Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 71291.151Skamil memset(&event, 0, sizeof(event)); 71301.151Skamil event.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT; 71311.151Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 71321.151Skamil 71331.151Skamil DPRINTF("Before resuming the child process where it left off and " 71341.151Skamil "without signal to be sent\n"); 71351.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71361.151Skamil 71371.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71381.151Skamil "SIGTRAP\n", TWAIT_FNAME); 71391.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71401.151Skamil child); 71411.151Skamil 71421.151Skamil validate_status_stopped(status, SIGTRAP); 71431.151Skamil 71441.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 71451.151Skamil "child\n"); 71461.151Skamil SYSCALL_REQUIRE( 71471.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71481.151Skamil 71491.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71501.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 71511.151Skamil "si_errno=%#x\n", 71521.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71531.151Skamil info.psi_siginfo.si_errno); 71541.151Skamil 71551.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 71561.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 71571.151Skamil 71581.151Skamil SYSCALL_REQUIRE( 71591.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71601.151Skamil 71611.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 71621.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 71631.151Skamil 71641.151Skamil lid = state.pe_lwp; 71651.151Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 71661.151Skamil 71671.151Skamil DPRINTF("Before resuming the child process where it left off " 71681.151Skamil "and without signal to be sent\n"); 71691.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71701.151Skamil 71711.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71721.151Skamil "SIGTRAP\n", TWAIT_FNAME); 71731.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71741.151Skamil child); 71751.151Skamil 71761.151Skamil validate_status_stopped(status, SIGTRAP); 71771.151Skamil 71781.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 71791.151Skamil "child\n"); 71801.151Skamil SYSCALL_REQUIRE( 71811.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71821.151Skamil 71831.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71841.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 71851.151Skamil "si_errno=%#x\n", 71861.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71871.151Skamil info.psi_siginfo.si_errno); 71881.151Skamil 71891.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 71901.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 71911.151Skamil 71921.151Skamil SYSCALL_REQUIRE( 71931.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71941.151Skamil 71951.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 71961.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 71971.151Skamil 71981.151Skamil lid = state.pe_lwp; 71991.151Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 72001.151Skamil 72011.151Skamil DPRINTF("Before resuming the child process where it left off " 72021.151Skamil "and without signal to be sent\n"); 72031.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72041.151Skamil 72051.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 72061.151Skamil "SIGTRAP\n", TWAIT_FNAME); 72071.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 72081.151Skamil child); 72091.151Skamil 72101.151Skamil validate_status_stopped(status, SIGTRAP); 72111.151Skamil 72121.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 72131.151Skamil "child\n"); 72141.151Skamil SYSCALL_REQUIRE( 72151.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 72161.151Skamil 72171.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 72181.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 72191.151Skamil "si_errno=%#x\n", 72201.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 72211.151Skamil info.psi_siginfo.si_errno); 72221.151Skamil 72231.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 72241.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 72251.151Skamil 72261.151Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 72271.151Skamil 72281.151Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 72291.151Skamil TWAIT_FNAME); 72301.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72311.151Skamil 72321.151Skamil validate_status_signaled(status, SIGKILL, 0); 72331.151Skamil 72341.151Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 72351.151Skamil TWAIT_FNAME); 72361.151Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 72371.151Skamil} 72381.151Skamil 72391.151SkamilATF_TC(threads_and_exec); 72401.151SkamilATF_TC_HEAD(threads_and_exec, tc) 72411.151Skamil{ 72421.151Skamil atf_tc_set_md_var(tc, "descr", 72431.151Skamil "Verify that multithreaded application on exec() will report " 72441.151Skamil "LWP_EXIT events"); 72451.151Skamil} 72461.151Skamil 72471.151SkamilATF_TC_BODY(threads_and_exec, tc) 72481.151Skamil{ 72491.151Skamil 72501.151Skamil threads_and_exec(); 72511.151Skamil} 72521.151Skamil 72531.151Skamil/// ---------------------------------------------------------------------------- 72541.151Skamil 72551.154SkamilATF_TC(suspend_no_deadlock); 72561.154SkamilATF_TC_HEAD(suspend_no_deadlock, tc) 72571.1Skamil{ 72581.1Skamil atf_tc_set_md_var(tc, "descr", 72591.1Skamil "Verify that the while the only thread within a process is " 72601.1Skamil "suspended, the whole process cannot be unstopped"); 72611.1Skamil} 72621.1Skamil 72631.154SkamilATF_TC_BODY(suspend_no_deadlock, tc) 72641.1Skamil{ 72651.1Skamil const int exitval = 5; 72661.1Skamil const int sigval = SIGSTOP; 72671.1Skamil pid_t child, wpid; 72681.1Skamil#if defined(TWAIT_HAVE_STATUS) 72691.1Skamil int status; 72701.1Skamil#endif 72711.1Skamil struct ptrace_siginfo psi; 72721.1Skamil 72731.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 72741.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 72751.1Skamil if (child == 0) { 72761.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 72771.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 72781.1Skamil 72791.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 72801.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 72811.1Skamil 72821.13Schristos DPRINTF("Before exiting of the child process\n"); 72831.1Skamil _exit(exitval); 72841.1Skamil } 72851.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 72861.1Skamil 72871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 72881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72891.1Skamil 72901.1Skamil validate_status_stopped(status, sigval); 72911.1Skamil 72921.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 72931.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 72941.1Skamil 72951.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 72961.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 72971.1Skamil 72981.13Schristos DPRINTF("Before resuming the child process where it left off and " 72991.1Skamil "without signal to be sent\n"); 73001.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 73011.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 73021.1Skamil 73031.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 73041.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 73051.1Skamil 73061.13Schristos DPRINTF("Before resuming the child process where it left off and " 73071.1Skamil "without signal to be sent\n"); 73081.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73091.1Skamil 73101.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 73111.1Skamil TWAIT_FNAME); 73121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73131.1Skamil 73141.1Skamil validate_status_exited(status, exitval); 73151.1Skamil 73161.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 73171.1Skamil TWAIT_FNAME); 73181.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 73191.1Skamil} 73201.1Skamil 73211.154Skamil/// ---------------------------------------------------------------------------- 73221.154Skamil 73231.155Skamilstatic pthread_barrier_t barrier1_resume; 73241.155Skamilstatic pthread_barrier_t barrier2_resume; 73251.154Skamil 73261.155Skamilstatic void * 73271.155Skamilresume_thread(void *arg) 73281.154Skamil{ 73291.154Skamil 73301.155Skamil raise(SIGUSR1); 73311.155Skamil 73321.155Skamil pthread_barrier_wait(&barrier1_resume); 73331.155Skamil 73341.155Skamil /* Debugger will suspend the process here */ 73351.155Skamil 73361.155Skamil pthread_barrier_wait(&barrier2_resume); 73371.154Skamil 73381.155Skamil raise(SIGUSR2); 73391.155Skamil 73401.155Skamil return infinite_thread(arg); 73411.154Skamil} 73421.154Skamil 73431.155SkamilATF_TC(resume); 73441.155SkamilATF_TC_HEAD(resume, tc) 73451.1Skamil{ 73461.1Skamil atf_tc_set_md_var(tc, "descr", 73471.1Skamil "Verify that a thread can be suspended by a debugger and later " 73481.1Skamil "resumed by the debugger"); 73491.1Skamil} 73501.1Skamil 73511.155SkamilATF_TC_BODY(resume, tc) 73521.1Skamil{ 73531.1Skamil const int sigval = SIGSTOP; 73541.1Skamil pid_t child, wpid; 73551.1Skamil#if defined(TWAIT_HAVE_STATUS) 73561.1Skamil int status; 73571.1Skamil#endif 73581.1Skamil lwpid_t lid; 73591.1Skamil struct ptrace_siginfo psi; 73601.155Skamil pthread_t t; 73611.1Skamil 73621.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 73631.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 73641.1Skamil if (child == 0) { 73651.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 73661.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 73671.1Skamil 73681.155Skamil pthread_barrier_init(&barrier1_resume, NULL, 2); 73691.155Skamil pthread_barrier_init(&barrier2_resume, NULL, 2); 73701.155Skamil 73711.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 73721.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 73731.1Skamil 73741.155Skamil DPRINTF("Before creating new thread in child\n"); 73751.155Skamil FORKEE_ASSERT(pthread_create(&t, NULL, resume_thread, NULL) == 0); 73761.1Skamil 73771.155Skamil pthread_barrier_wait(&barrier1_resume); 73781.1Skamil 73791.155Skamil pthread_barrier_wait(&barrier2_resume); 73801.1Skamil 73811.155Skamil infinite_thread(NULL); 73821.1Skamil } 73831.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 73841.1Skamil 73851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 73861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73871.1Skamil 73881.1Skamil validate_status_stopped(status, sigval); 73891.1Skamil 73901.13Schristos DPRINTF("Before resuming the child process where it left off and " 73911.1Skamil "without signal to be sent\n"); 73921.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73931.1Skamil 73941.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 73951.155Skamil "SIGUSR1\n", TWAIT_FNAME); 73961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73971.1Skamil 73981.155Skamil validate_status_stopped(status, SIGUSR1); 73991.1Skamil 74001.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 74011.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 74021.1Skamil 74031.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 74041.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 74051.1Skamil 74061.155Skamil lid = psi.psi_lwpid; 74071.1Skamil 74081.13Schristos DPRINTF("Before resuming the child process where it left off and " 74091.1Skamil "without signal to be sent\n"); 74101.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74111.1Skamil 74121.155Skamil DPRINTF("Before suspending the parent for 1 second, we expect no signals\n"); 74131.155Skamil SYSCALL_REQUIRE(sleep(1) == 0); 74141.155Skamil 74151.155Skamil#if defined(TWAIT_HAVE_OPTIONS) 74161.155Skamil DPRINTF("Before calling %s() for the child - expected no status\n", 74171.155Skamil TWAIT_FNAME); 74181.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, WNOHANG), 0); 74191.155Skamil#endif 74201.155Skamil 74211.155Skamil DPRINTF("Before resuming the child process where it left off and " 74221.155Skamil "without signal to be sent\n"); 74231.155Skamil SYSCALL_REQUIRE(ptrace(PT_STOP, child, NULL, 0) != -1); 74241.155Skamil 74251.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 74261.155Skamil "SIGSTOP\n", TWAIT_FNAME); 74271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74281.1Skamil 74291.155Skamil validate_status_stopped(status, SIGSTOP); 74301.1Skamil 74311.155Skamil DPRINTF("Before resuming LWP %d\n", lid); 74321.155Skamil SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, lid) != -1); 74331.155Skamil 74341.155Skamil DPRINTF("Before resuming the child process where it left off and " 74351.155Skamil "without signal to be sent\n"); 74361.155Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74371.1Skamil 74381.155Skamil DPRINTF("Before calling %s() for the child - expected stopped " 74391.155Skamil "SIGUSR2\n", TWAIT_FNAME); 74401.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74411.1Skamil 74421.155Skamil validate_status_stopped(status, SIGUSR2); 74431.1Skamil 74441.13Schristos DPRINTF("Before resuming the child process where it left off and " 74451.1Skamil "without signal to be sent\n"); 74461.155Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 74471.1Skamil 74481.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 74491.1Skamil TWAIT_FNAME); 74501.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74511.1Skamil 74521.155Skamil validate_status_signaled(status, SIGKILL, 0); 74531.1Skamil 74541.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 74551.1Skamil TWAIT_FNAME); 74561.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74571.155Skamil} 74581.1Skamil 74591.155Skamil/// ---------------------------------------------------------------------------- 74601.1Skamil 74611.1SkamilATF_TC(syscall1); 74621.1SkamilATF_TC_HEAD(syscall1, tc) 74631.1Skamil{ 74641.1Skamil atf_tc_set_md_var(tc, "descr", 74651.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 74661.1Skamil} 74671.1Skamil 74681.1SkamilATF_TC_BODY(syscall1, tc) 74691.1Skamil{ 74701.1Skamil const int exitval = 5; 74711.1Skamil const int sigval = SIGSTOP; 74721.1Skamil pid_t child, wpid; 74731.1Skamil#if defined(TWAIT_HAVE_STATUS) 74741.1Skamil int status; 74751.1Skamil#endif 74761.1Skamil struct ptrace_siginfo info; 74771.1Skamil memset(&info, 0, sizeof(info)); 74781.1Skamil 74791.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 74801.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 74811.1Skamil if (child == 0) { 74821.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74831.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74841.1Skamil 74851.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 74861.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 74871.1Skamil 74881.1Skamil syscall(SYS_getpid); 74891.1Skamil 74901.13Schristos DPRINTF("Before exiting of the child process\n"); 74911.1Skamil _exit(exitval); 74921.1Skamil } 74931.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74941.1Skamil 74951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74971.1Skamil 74981.1Skamil validate_status_stopped(status, sigval); 74991.1Skamil 75001.13Schristos DPRINTF("Before resuming the child process where it left off and " 75011.1Skamil "without signal to be sent\n"); 75021.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 75031.1Skamil 75041.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75061.1Skamil 75071.1Skamil validate_status_stopped(status, SIGTRAP); 75081.1Skamil 75091.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 75101.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 75111.1Skamil 75121.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 75131.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 75141.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 75151.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 75161.1Skamil 75171.13Schristos DPRINTF("Before resuming the child process where it left off and " 75181.1Skamil "without signal to be sent\n"); 75191.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 75201.1Skamil 75211.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75231.1Skamil 75241.1Skamil validate_status_stopped(status, SIGTRAP); 75251.1Skamil 75261.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 75271.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 75281.1Skamil 75291.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 75301.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 75311.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 75321.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 75331.1Skamil 75341.13Schristos DPRINTF("Before resuming the child process where it left off and " 75351.1Skamil "without signal to be sent\n"); 75361.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 75371.1Skamil 75381.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75391.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75401.1Skamil 75411.1Skamil validate_status_exited(status, exitval); 75421.1Skamil 75431.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75441.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75451.1Skamil} 75461.1Skamil 75471.164Skamil/// ---------------------------------------------------------------------------- 75481.164Skamil 75491.1SkamilATF_TC(syscallemu1); 75501.1SkamilATF_TC_HEAD(syscallemu1, tc) 75511.1Skamil{ 75521.1Skamil atf_tc_set_md_var(tc, "descr", 75531.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 75541.1Skamil} 75551.1Skamil 75561.1SkamilATF_TC_BODY(syscallemu1, tc) 75571.1Skamil{ 75581.1Skamil const int exitval = 5; 75591.1Skamil const int sigval = SIGSTOP; 75601.1Skamil pid_t child, wpid; 75611.1Skamil#if defined(TWAIT_HAVE_STATUS) 75621.1Skamil int status; 75631.1Skamil#endif 75641.1Skamil 75651.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 75661.6Skamil /* syscallemu does not work on sparc (32-bit) */ 75671.6Skamil atf_tc_expect_fail("PR kern/52166"); 75681.6Skamil#endif 75691.6Skamil 75701.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 75711.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 75721.1Skamil if (child == 0) { 75731.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 75741.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 75751.1Skamil 75761.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 75771.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 75781.1Skamil 75791.1Skamil syscall(SYS_exit, 100); 75801.1Skamil 75811.13Schristos DPRINTF("Before exiting of the child process\n"); 75821.1Skamil _exit(exitval); 75831.1Skamil } 75841.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75851.1Skamil 75861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75881.1Skamil 75891.1Skamil validate_status_stopped(status, sigval); 75901.1Skamil 75911.13Schristos DPRINTF("Before resuming the child process where it left off and " 75921.1Skamil "without signal to be sent\n"); 75931.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 75941.1Skamil 75951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75971.1Skamil 75981.1Skamil validate_status_stopped(status, SIGTRAP); 75991.1Skamil 76001.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 76011.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 76021.1Skamil 76031.13Schristos DPRINTF("Before resuming the child process where it left off and " 76041.1Skamil "without signal to be sent\n"); 76051.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 76061.1Skamil 76071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76091.1Skamil 76101.1Skamil validate_status_stopped(status, SIGTRAP); 76111.1Skamil 76121.13Schristos DPRINTF("Before resuming the child process where it left off and " 76131.1Skamil "without signal to be sent\n"); 76141.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 76151.1Skamil 76161.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76171.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76181.1Skamil 76191.1Skamil validate_status_exited(status, exitval); 76201.1Skamil 76211.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76221.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76231.1Skamil} 76241.1Skamil 76251.103Skamil/// ---------------------------------------------------------------------------- 76261.103Skamil 76271.106Skamilstatic void 76281.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 76291.106Skamil bool trackvforkdone) 76301.106Skamil{ 76311.106Skamil const int exitval = 5; 76321.106Skamil const int exitval2 = 15; 76331.106Skamil const int sigval = SIGSTOP; 76341.106Skamil pid_t child, child2 = 0, wpid; 76351.106Skamil#if defined(TWAIT_HAVE_STATUS) 76361.106Skamil int status; 76371.106Skamil#endif 76381.106Skamil ptrace_state_t state; 76391.106Skamil const int slen = sizeof(state); 76401.106Skamil ptrace_event_t event; 76411.106Skamil const int elen = sizeof(event); 76421.106Skamil 76431.106Skamil const size_t stack_size = 1024 * 1024; 76441.106Skamil void *stack, *stack_base; 76451.106Skamil 76461.106Skamil stack = malloc(stack_size); 76471.106Skamil ATF_REQUIRE(stack != NULL); 76481.106Skamil 76491.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 76501.106Skamil stack_base = stack; 76511.106Skamil#else 76521.106Skamil stack_base = (char *)stack + stack_size; 76531.106Skamil#endif 76541.106Skamil 76551.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 76561.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 76571.106Skamil if (child == 0) { 76581.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 76591.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 76601.106Skamil 76611.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 76621.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 76631.106Skamil 76641.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 76651.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 76661.106Skamil 76671.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 76681.106Skamil child2); 76691.106Skamil 76701.106Skamil // XXX WALLSIG? 76711.106Skamil FORKEE_REQUIRE_SUCCESS 76721.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 76731.106Skamil 76741.106Skamil forkee_status_exited(status, exitval2); 76751.106Skamil 76761.106Skamil DPRINTF("Before exiting of the child process\n"); 76771.106Skamil _exit(exitval); 76781.106Skamil } 76791.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 76801.106Skamil 76811.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76821.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76831.106Skamil 76841.106Skamil validate_status_stopped(status, sigval); 76851.106Skamil 76861.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 76871.106Skamil trackfork ? "|PTRACE_FORK" : "", 76881.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 76891.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 76901.106Skamil event.pe_set_event = 0; 76911.106Skamil if (trackfork) 76921.106Skamil event.pe_set_event |= PTRACE_FORK; 76931.106Skamil if (trackvfork) 76941.106Skamil event.pe_set_event |= PTRACE_VFORK; 76951.106Skamil if (trackvforkdone) 76961.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 76971.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 76981.106Skamil 76991.106Skamil DPRINTF("Before resuming the child process where it left off and " 77001.106Skamil "without signal to be sent\n"); 77011.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 77021.106Skamil 77031.106Skamil#if defined(TWAIT_HAVE_PID) 77041.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 77051.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 77061.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 77071.106Skamil child); 77081.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 77091.106Skamil child); 77101.106Skamil 77111.106Skamil validate_status_stopped(status, SIGTRAP); 77121.106Skamil 77131.106Skamil SYSCALL_REQUIRE( 77141.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 77151.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 77161.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 77171.106Skamil PTRACE_FORK); 77181.106Skamil } 77191.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 77201.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 77211.106Skamil PTRACE_VFORK); 77221.106Skamil } 77231.106Skamil 77241.106Skamil child2 = state.pe_other_pid; 77251.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 77261.106Skamil 77271.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 77281.106Skamil "%d\n", TWAIT_FNAME, child2, child); 77291.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 77301.106Skamil child2); 77311.106Skamil 77321.106Skamil validate_status_stopped(status, SIGTRAP); 77331.106Skamil 77341.106Skamil SYSCALL_REQUIRE( 77351.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 77361.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 77371.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 77381.106Skamil PTRACE_FORK); 77391.106Skamil } 77401.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 77411.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 77421.106Skamil PTRACE_VFORK); 77431.106Skamil } 77441.106Skamil 77451.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 77461.106Skamil 77471.106Skamil DPRINTF("Before resuming the forkee process where it left off " 77481.106Skamil "and without signal to be sent\n"); 77491.106Skamil SYSCALL_REQUIRE( 77501.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 77511.106Skamil 77521.106Skamil DPRINTF("Before resuming the child process where it left off " 77531.106Skamil "and without signal to be sent\n"); 77541.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 77551.106Skamil } 77561.106Skamil#endif 77571.106Skamil 77581.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 77591.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 77601.106Skamil child); 77611.106Skamil TWAIT_REQUIRE_SUCCESS( 77621.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 77631.106Skamil 77641.106Skamil validate_status_stopped(status, SIGTRAP); 77651.106Skamil 77661.106Skamil SYSCALL_REQUIRE( 77671.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 77681.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 77691.106Skamil 77701.106Skamil child2 = state.pe_other_pid; 77711.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 77721.106Skamil child2); 77731.106Skamil 77741.106Skamil DPRINTF("Before resuming the child process where it left off " 77751.106Skamil "and without signal to be sent\n"); 77761.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 77771.106Skamil } 77781.106Skamil 77791.103Skamil#if defined(TWAIT_HAVE_PID) 77801.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 77811.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 77821.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 77831.106Skamil "\n", TWAIT_FNAME); 77841.106Skamil TWAIT_REQUIRE_SUCCESS( 77851.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 77861.106Skamil 77871.106Skamil validate_status_exited(status, exitval2); 77881.106Skamil 77891.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 77901.106Skamil "process\n", TWAIT_FNAME); 77911.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 77921.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 77931.106Skamil } 77941.106Skamil#endif 77951.106Skamil 77961.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 77971.106Skamil "SIGCHLD\n", TWAIT_FNAME); 77981.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77991.106Skamil 78001.106Skamil validate_status_stopped(status, SIGCHLD); 78011.106Skamil 78021.106Skamil DPRINTF("Before resuming the child process where it left off and " 78031.106Skamil "without signal to be sent\n"); 78041.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78051.106Skamil 78061.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 78071.106Skamil TWAIT_FNAME); 78081.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 78091.106Skamil 78101.106Skamil validate_status_exited(status, exitval); 78111.103Skamil 78121.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 78131.106Skamil TWAIT_FNAME); 78141.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 78151.106Skamil} 78161.103Skamil 78171.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 78181.106SkamilATF_TC(name); \ 78191.106SkamilATF_TC_HEAD(name, tc) \ 78201.106Skamil{ \ 78211.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 78221.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 78231.106Skamil #flags, \ 78241.106Skamil tfork ? "|PTRACE_FORK" : "", \ 78251.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 78261.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 78271.106Skamil} \ 78281.106Skamil \ 78291.106SkamilATF_TC_BODY(name, tc) \ 78301.106Skamil{ \ 78311.106Skamil \ 78321.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 78331.103Skamil} 78341.103Skamil 78351.106SkamilCLONE_TEST(clone1, 0, false, false, false) 78361.106Skamil#if defined(TWAIT_HAVE_PID) 78371.106SkamilCLONE_TEST(clone2, 0, true, false, false) 78381.106SkamilCLONE_TEST(clone3, 0, false, true, false) 78391.106SkamilCLONE_TEST(clone4, 0, true, true, false) 78401.106Skamil#endif 78411.106SkamilCLONE_TEST(clone5, 0, false, false, true) 78421.106Skamil#if defined(TWAIT_HAVE_PID) 78431.106SkamilCLONE_TEST(clone6, 0, true, false, true) 78441.106SkamilCLONE_TEST(clone7, 0, false, true, true) 78451.106SkamilCLONE_TEST(clone8, 0, true, true, true) 78461.106Skamil#endif 78471.106Skamil 78481.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 78491.106Skamil#if defined(TWAIT_HAVE_PID) 78501.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 78511.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 78521.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 78531.106Skamil#endif 78541.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 78551.106Skamil#if defined(TWAIT_HAVE_PID) 78561.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 78571.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 78581.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 78591.106Skamil#endif 78601.106Skamil 78611.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 78621.106Skamil#if defined(TWAIT_HAVE_PID) 78631.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 78641.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 78651.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 78661.106Skamil#endif 78671.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 78681.106Skamil#if defined(TWAIT_HAVE_PID) 78691.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 78701.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 78711.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 78721.106Skamil#endif 78731.106Skamil 78741.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 78751.106Skamil#if defined(TWAIT_HAVE_PID) 78761.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 78771.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 78781.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 78791.106Skamil#endif 78801.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 78811.106Skamil#if defined(TWAIT_HAVE_PID) 78821.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 78831.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 78841.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 78851.106Skamil#endif 78861.106Skamil 78871.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 78881.106Skamil#if defined(TWAIT_HAVE_PID) 78891.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 78901.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 78911.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 78921.106Skamil#endif 78931.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 78941.106Skamil#if defined(TWAIT_HAVE_PID) 78951.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 78961.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 78971.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 78981.106Skamil#endif 78991.106Skamil 79001.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 79011.106Skamil#if defined(TWAIT_HAVE_PID) 79021.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 79031.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 79041.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 79051.106Skamil#endif 79061.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 79071.106Skamil#if defined(TWAIT_HAVE_PID) 79081.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 79091.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 79101.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 79111.106Skamil#endif 79121.106Skamil 79131.106Skamil/// ---------------------------------------------------------------------------- 79141.106Skamil 79151.106Skamil#if defined(TWAIT_HAVE_PID) 79161.103Skamilstatic void 79171.106Skamilclone_body2(int flags, bool masked, bool ignored) 79181.103Skamil{ 79191.103Skamil const int exitval = 5; 79201.103Skamil const int exitval2 = 15; 79211.103Skamil const int sigval = SIGSTOP; 79221.103Skamil pid_t child, child2 = 0, wpid; 79231.103Skamil#if defined(TWAIT_HAVE_STATUS) 79241.103Skamil int status; 79251.103Skamil#endif 79261.103Skamil ptrace_state_t state; 79271.103Skamil const int slen = sizeof(state); 79281.103Skamil ptrace_event_t event; 79291.103Skamil const int elen = sizeof(event); 79301.103Skamil struct sigaction sa; 79311.103Skamil struct ptrace_siginfo info; 79321.103Skamil sigset_t intmask; 79331.103Skamil struct kinfo_proc2 kp; 79341.103Skamil size_t len = sizeof(kp); 79351.103Skamil 79361.103Skamil int name[6]; 79371.103Skamil const size_t namelen = __arraycount(name); 79381.103Skamil ki_sigset_t kp_sigmask; 79391.103Skamil ki_sigset_t kp_sigignore; 79401.103Skamil 79411.103Skamil const size_t stack_size = 1024 * 1024; 79421.103Skamil void *stack, *stack_base; 79431.103Skamil 79441.103Skamil stack = malloc(stack_size); 79451.103Skamil ATF_REQUIRE(stack != NULL); 79461.103Skamil 79471.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 79481.103Skamil stack_base = stack; 79491.103Skamil#else 79501.103Skamil stack_base = (char *)stack + stack_size; 79511.103Skamil#endif 79521.103Skamil 79531.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 79541.103Skamil if (child == 0) { 79551.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 79561.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 79571.103Skamil 79581.103Skamil if (masked) { 79591.103Skamil sigemptyset(&intmask); 79601.103Skamil sigaddset(&intmask, SIGTRAP); 79611.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 79621.103Skamil } 79631.103Skamil 79641.103Skamil if (ignored) { 79651.103Skamil memset(&sa, 0, sizeof(sa)); 79661.103Skamil sa.sa_handler = SIG_IGN; 79671.103Skamil sigemptyset(&sa.sa_mask); 79681.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 79691.103Skamil } 79701.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 79711.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 79721.103Skamil 79731.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 79741.103Skamil flags); 79751.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 79761.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 79771.103Skamil 79781.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 79791.103Skamil child2); 79801.103Skamil 79811.103Skamil // XXX WALLSIG? 79821.103Skamil FORKEE_REQUIRE_SUCCESS 79831.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 79841.103Skamil 79851.103Skamil forkee_status_exited(status, exitval2); 79861.103Skamil 79871.103Skamil DPRINTF("Before exiting of the child process\n"); 79881.103Skamil _exit(exitval); 79891.103Skamil } 79901.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 79911.103Skamil 79921.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 79931.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 79941.103Skamil 79951.103Skamil validate_status_stopped(status, sigval); 79961.103Skamil 79971.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 79981.103Skamil SYSCALL_REQUIRE( 79991.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 80001.103Skamil 80011.103Skamil DPRINTF("Before checking siginfo_t\n"); 80021.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 80031.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 80041.103Skamil 80051.103Skamil name[0] = CTL_KERN, 80061.103Skamil name[1] = KERN_PROC2, 80071.103Skamil name[2] = KERN_PROC_PID; 80081.103Skamil name[3] = child; 80091.103Skamil name[4] = sizeof(kp); 80101.103Skamil name[5] = 1; 80111.103Skamil 80121.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 80131.103Skamil 80141.103Skamil if (masked) 80151.103Skamil kp_sigmask = kp.p_sigmask; 80161.103Skamil 80171.103Skamil if (ignored) 80181.103Skamil kp_sigignore = kp.p_sigignore; 80191.103Skamil 80201.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 80211.103Skamil "EVENT_MASK for the child %d\n", child); 80221.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 80231.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 80241.103Skamil 80251.103Skamil DPRINTF("Before resuming the child process where it left off and " 80261.103Skamil "without signal to be sent\n"); 80271.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 80281.103Skamil 80291.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 80301.103Skamil child); 80311.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 80321.103Skamil child); 80331.103Skamil 80341.103Skamil validate_status_stopped(status, SIGTRAP); 80351.103Skamil 80361.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 80371.103Skamil 80381.103Skamil if (masked) { 80391.103Skamil DPRINTF("kp_sigmask=" 80401.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 80411.103Skamil PRIx32 "\n", 80421.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 80431.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 80441.103Skamil 80451.103Skamil DPRINTF("kp.p_sigmask=" 80461.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 80471.103Skamil PRIx32 "\n", 80481.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 80491.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 80501.103Skamil 80511.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 80521.103Skamil sizeof(kp_sigmask))); 80531.103Skamil } 80541.103Skamil 80551.103Skamil if (ignored) { 80561.103Skamil DPRINTF("kp_sigignore=" 80571.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 80581.103Skamil PRIx32 "\n", 80591.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 80601.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 80611.103Skamil 80621.103Skamil DPRINTF("kp.p_sigignore=" 80631.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 80641.103Skamil PRIx32 "\n", 80651.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 80661.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 80671.103Skamil 80681.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 80691.103Skamil sizeof(kp_sigignore))); 80701.103Skamil } 80711.103Skamil 80721.103Skamil SYSCALL_REQUIRE( 80731.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 80741.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 80751.103Skamil child2); 80761.103Skamil if (!(flags & CLONE_VFORK)) { 80771.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 80781.103Skamil PTRACE_FORK); 80791.103Skamil } else { 80801.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 80811.103Skamil PTRACE_VFORK); 80821.103Skamil } 80831.103Skamil 80841.103Skamil child2 = state.pe_other_pid; 80851.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 80861.103Skamil 80871.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 80881.103Skamil "%d\n", TWAIT_FNAME, child2, child); 80891.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 80901.103Skamil child2); 80911.103Skamil 80921.103Skamil validate_status_stopped(status, SIGTRAP); 80931.103Skamil 80941.103Skamil name[3] = child2; 80951.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 80961.103Skamil 80971.103Skamil if (masked) { 80981.103Skamil DPRINTF("kp_sigmask=" 80991.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81001.103Skamil PRIx32 "\n", 81011.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 81021.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 81031.103Skamil 81041.103Skamil DPRINTF("kp.p_sigmask=" 81051.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81061.103Skamil PRIx32 "\n", 81071.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 81081.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 81091.103Skamil 81101.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 81111.103Skamil sizeof(kp_sigmask))); 81121.103Skamil } 81131.103Skamil 81141.103Skamil if (ignored) { 81151.103Skamil DPRINTF("kp_sigignore=" 81161.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81171.103Skamil PRIx32 "\n", 81181.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 81191.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 81201.103Skamil 81211.103Skamil DPRINTF("kp.p_sigignore=" 81221.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81231.103Skamil PRIx32 "\n", 81241.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 81251.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 81261.103Skamil 81271.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 81281.103Skamil sizeof(kp_sigignore))); 81291.103Skamil } 81301.103Skamil 81311.103Skamil SYSCALL_REQUIRE( 81321.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 81331.103Skamil if (!(flags & CLONE_VFORK)) { 81341.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 81351.103Skamil PTRACE_FORK); 81361.103Skamil } else { 81371.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 81381.103Skamil PTRACE_VFORK); 81391.103Skamil } 81401.103Skamil 81411.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 81421.103Skamil 81431.103Skamil DPRINTF("Before resuming the forkee process where it left off " 81441.103Skamil "and without signal to be sent\n"); 81451.103Skamil SYSCALL_REQUIRE( 81461.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 81471.103Skamil 81481.103Skamil DPRINTF("Before resuming the child process where it left off " 81491.103Skamil "and without signal to be sent\n"); 81501.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 81511.103Skamil 81521.103Skamil if (flags & CLONE_VFORK) { 81531.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 81541.103Skamil child); 81551.103Skamil TWAIT_REQUIRE_SUCCESS( 81561.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 81571.103Skamil 81581.103Skamil validate_status_stopped(status, SIGTRAP); 81591.103Skamil 81601.103Skamil name[3] = child; 81611.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 81621.103Skamil 81631.103Skamil /* 81641.103Skamil * SIGCHLD is now pending in the signal queue and 81651.103Skamil * the kernel presents it to userland as a masked signal. 81661.103Skamil */ 81671.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 81681.103Skamil 81691.103Skamil if (masked) { 81701.103Skamil DPRINTF("kp_sigmask=" 81711.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81721.103Skamil PRIx32 "\n", 81731.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 81741.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 81751.103Skamil 81761.103Skamil DPRINTF("kp.p_sigmask=" 81771.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81781.103Skamil PRIx32 "\n", 81791.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 81801.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 81811.103Skamil 81821.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 81831.103Skamil sizeof(kp_sigmask))); 81841.103Skamil } 81851.103Skamil 81861.103Skamil if (ignored) { 81871.103Skamil DPRINTF("kp_sigignore=" 81881.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81891.103Skamil PRIx32 "\n", 81901.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 81911.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 81921.103Skamil 81931.103Skamil DPRINTF("kp.p_sigignore=" 81941.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81951.103Skamil PRIx32 "\n", 81961.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 81971.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 81981.103Skamil 81991.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 82001.103Skamil sizeof(kp_sigignore))); 82011.103Skamil } 82021.103Skamil 82031.103Skamil SYSCALL_REQUIRE( 82041.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 82051.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 82061.103Skamil 82071.103Skamil child2 = state.pe_other_pid; 82081.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 82091.103Skamil child2); 82101.103Skamil 82111.103Skamil DPRINTF("Before resuming the child process where it left off " 82121.103Skamil "and without signal to be sent\n"); 82131.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 82141.103Skamil } 82151.103Skamil 82161.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 82171.103Skamil "\n", TWAIT_FNAME); 82181.103Skamil TWAIT_REQUIRE_SUCCESS( 82191.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 82201.103Skamil 82211.103Skamil validate_status_exited(status, exitval2); 82221.103Skamil 82231.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 82241.103Skamil "process\n", TWAIT_FNAME); 82251.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 82261.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 82271.103Skamil 82281.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 82291.103Skamil "SIGCHLD\n", TWAIT_FNAME); 82301.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 82311.103Skamil 82321.103Skamil validate_status_stopped(status, SIGCHLD); 82331.103Skamil 82341.103Skamil DPRINTF("Before resuming the child process where it left off and " 82351.103Skamil "without signal to be sent\n"); 82361.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 82371.103Skamil 82381.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 82391.103Skamil TWAIT_FNAME); 82401.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 82411.103Skamil 82421.103Skamil validate_status_exited(status, exitval); 82431.103Skamil 82441.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 82451.103Skamil TWAIT_FNAME); 82461.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 82471.103Skamil} 82481.103Skamil 82491.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 82501.103SkamilATF_TC(name); \ 82511.103SkamilATF_TC_HEAD(name, tc) \ 82521.103Skamil{ \ 82531.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 82541.103Skamil " regardless of signal %s%s", \ 82551.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 82561.103Skamil} \ 82571.103Skamil \ 82581.103SkamilATF_TC_BODY(name, tc) \ 82591.103Skamil{ \ 82601.103Skamil \ 82611.106Skamil clone_body2(flags, masked, ignored); \ 82621.103Skamil} 82631.103Skamil 82641.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 82651.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 82661.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 82671.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 82681.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 82691.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 82701.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 82711.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 82721.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 82731.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 82741.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 82751.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 82761.103Skamil#endif 82771.103Skamil 82781.103Skamil/// ---------------------------------------------------------------------------- 82791.103Skamil 82801.107Skamil#if defined(TWAIT_HAVE_PID) 82811.107Skamilstatic void 82821.107Skamiltraceme_vfork_clone_body(int flags) 82831.107Skamil{ 82841.107Skamil const int exitval = 5; 82851.107Skamil const int exitval2 = 15; 82861.107Skamil pid_t child, child2 = 0, wpid; 82871.107Skamil#if defined(TWAIT_HAVE_STATUS) 82881.107Skamil int status; 82891.107Skamil#endif 82901.107Skamil 82911.107Skamil const size_t stack_size = 1024 * 1024; 82921.107Skamil void *stack, *stack_base; 82931.107Skamil 82941.107Skamil stack = malloc(stack_size); 82951.107Skamil ATF_REQUIRE(stack != NULL); 82961.107Skamil 82971.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 82981.107Skamil stack_base = stack; 82991.107Skamil#else 83001.107Skamil stack_base = (char *)stack + stack_size; 83011.107Skamil#endif 83021.107Skamil 83031.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 83041.107Skamil if (child == 0) { 83051.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 83061.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 83071.107Skamil 83081.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 83091.107Skamil flags); 83101.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 83111.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 83121.107Skamil 83131.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 83141.107Skamil child2); 83151.107Skamil 83161.107Skamil // XXX WALLSIG? 83171.107Skamil FORKEE_REQUIRE_SUCCESS 83181.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 83191.107Skamil 83201.107Skamil forkee_status_exited(status, exitval2); 83211.107Skamil 83221.107Skamil DPRINTF("Before exiting of the child process\n"); 83231.107Skamil _exit(exitval); 83241.107Skamil } 83251.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 83261.107Skamil 83271.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 83281.107Skamil TWAIT_FNAME); 83291.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 83301.107Skamil 83311.107Skamil validate_status_exited(status, exitval); 83321.107Skamil 83331.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 83341.107Skamil TWAIT_FNAME); 83351.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 83361.107Skamil} 83371.107Skamil 83381.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 83391.107SkamilATF_TC(name); \ 83401.107SkamilATF_TC_HEAD(name, tc) \ 83411.107Skamil{ \ 83421.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 83431.107Skamil "handled correctly with vfork(2)ed tracer", \ 83441.107Skamil #flags); \ 83451.107Skamil} \ 83461.107Skamil \ 83471.107SkamilATF_TC_BODY(name, tc) \ 83481.107Skamil{ \ 83491.107Skamil \ 83501.107Skamil traceme_vfork_clone_body(flags); \ 83511.107Skamil} 83521.107Skamil 83531.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 83541.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 83551.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 83561.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 83571.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 83581.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 83591.107Skamil#endif 83601.107Skamil 83611.107Skamil/// ---------------------------------------------------------------------------- 83621.107Skamil 83631.122Skamilstatic void 83641.122Skamiluser_va0_disable(int operation) 83651.122Skamil{ 83661.122Skamil pid_t child, wpid; 83671.122Skamil#if defined(TWAIT_HAVE_STATUS) 83681.122Skamil int status; 83691.122Skamil#endif 83701.122Skamil const int sigval = SIGSTOP; 83711.122Skamil int rv; 83721.122Skamil 83731.122Skamil struct ptrace_siginfo info; 83741.122Skamil 83751.122Skamil if (get_user_va0_disable() == 0) 83761.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 83771.122Skamil 83781.122Skamil memset(&info, 0, sizeof(info)); 83791.122Skamil 83801.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 83811.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 83821.122Skamil if (child == 0) { 83831.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 83841.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 83851.122Skamil 83861.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 83871.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 83881.122Skamil 83891.122Skamil /* NOTREACHED */ 83901.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 83911.122Skamil __unreachable(); 83921.122Skamil } 83931.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 83941.122Skamil 83951.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 83961.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 83971.122Skamil 83981.122Skamil validate_status_stopped(status, sigval); 83991.122Skamil 84001.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 84011.122Skamil "child\n"); 84021.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 84031.122Skamil sizeof(info)) != -1); 84041.122Skamil 84051.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 84061.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 84071.122Skamil "si_errno=%#x\n", 84081.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 84091.122Skamil info.psi_siginfo.si_errno); 84101.122Skamil 84111.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 84121.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 84131.122Skamil 84141.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 84151.122Skamil "and without signal to be sent\n"); 84161.122Skamil errno = 0; 84171.122Skamil rv = ptrace(operation, child, (void *)0, 0); 84181.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 84191.122Skamil ATF_REQUIRE_EQ(rv, -1); 84201.122Skamil 84211.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 84221.122Skamil 84231.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 84241.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 84251.122Skamil validate_status_signaled(status, SIGKILL, 0); 84261.122Skamil 84271.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 84281.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 84291.122Skamil} 84301.122Skamil 84311.122Skamil#define USER_VA0_DISABLE(test, operation) \ 84321.122SkamilATF_TC(test); \ 84331.122SkamilATF_TC_HEAD(test, tc) \ 84341.122Skamil{ \ 84351.122Skamil atf_tc_set_md_var(tc, "descr", \ 84361.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 84371.122Skamil} \ 84381.122Skamil \ 84391.122SkamilATF_TC_BODY(test, tc) \ 84401.122Skamil{ \ 84411.122Skamil \ 84421.122Skamil user_va0_disable(operation); \ 84431.122Skamil} 84441.122Skamil 84451.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 84461.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 84471.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 84481.122Skamil 84491.122Skamil/// ---------------------------------------------------------------------------- 84501.122Skamil 84511.130Smgorny/* 84521.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 84531.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 84541.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 84551.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 84561.130Smgorny * found, -1 is returned. 84571.130Smgorny */ 84581.130Smgornystatic ssize_t core_find_note(const char *core_path, 84591.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 84601.130Smgorny{ 84611.130Smgorny int core_fd; 84621.130Smgorny Elf *core_elf; 84631.130Smgorny size_t core_numhdr, i; 84641.130Smgorny ssize_t ret = -1; 84651.130Smgorny /* note: we assume note name will be null-terminated */ 84661.130Smgorny size_t name_len = strlen(note_name) + 1; 84671.130Smgorny 84681.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 84691.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 84701.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 84711.130Smgorny 84721.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 84731.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 84741.130Smgorny GElf_Phdr core_hdr; 84751.130Smgorny size_t offset; 84761.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 84771.130Smgorny if (core_hdr.p_type != PT_NOTE) 84781.130Smgorny continue; 84791.130Smgorny 84801.130Smgorny for (offset = core_hdr.p_offset; 84811.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 84821.130Smgorny Elf64_Nhdr note_hdr; 84831.130Smgorny char name_buf[64]; 84841.130Smgorny 84851.130Smgorny switch (gelf_getclass(core_elf)) { 84861.130Smgorny case ELFCLASS64: 84871.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 84881.130Smgorny sizeof(note_hdr), offset) 84891.130Smgorny == sizeof(note_hdr)); 84901.130Smgorny offset += sizeof(note_hdr); 84911.130Smgorny break; 84921.130Smgorny case ELFCLASS32: 84931.130Smgorny { 84941.130Smgorny Elf32_Nhdr tmp_hdr; 84951.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 84961.130Smgorny sizeof(tmp_hdr), offset) 84971.130Smgorny == sizeof(tmp_hdr)); 84981.130Smgorny offset += sizeof(tmp_hdr); 84991.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 85001.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 85011.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 85021.130Smgorny } 85031.130Smgorny break; 85041.130Smgorny } 85051.130Smgorny 85061.130Smgorny /* indicates end of notes */ 85071.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 85081.130Smgorny break; 85091.130Smgorny if (note_hdr.n_namesz == name_len && 85101.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 85111.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 85121.130Smgorny note_hdr.n_namesz, offset) 85131.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 85141.130Smgorny 85151.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 85161.130Smgorny note_hdr.n_type == note_type) 85171.130Smgorny ret = note_hdr.n_descsz; 85181.130Smgorny } 85191.130Smgorny 85201.130Smgorny offset += note_hdr.n_namesz; 85211.130Smgorny /* fix to alignment */ 85221.146Smgorny offset = roundup(offset, core_hdr.p_align); 85231.130Smgorny 85241.130Smgorny /* if name & type matched above */ 85251.130Smgorny if (ret != -1) { 85261.130Smgorny ssize_t read_len = MIN(buf_len, 85271.130Smgorny note_hdr.n_descsz); 85281.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 85291.130Smgorny read_len, offset) == read_len); 85301.130Smgorny break; 85311.130Smgorny } 85321.130Smgorny 85331.130Smgorny offset += note_hdr.n_descsz; 85341.146Smgorny /* fix to alignment */ 85351.146Smgorny offset = roundup(offset, core_hdr.p_align); 85361.130Smgorny } 85371.130Smgorny } 85381.130Smgorny 85391.130Smgorny elf_end(core_elf); 85401.130Smgorny close(core_fd); 85411.130Smgorny 85421.130Smgorny return ret; 85431.130Smgorny} 85441.130Smgorny 85451.130SmgornyATF_TC(core_dump_procinfo); 85461.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 85471.130Smgorny{ 85481.130Smgorny atf_tc_set_md_var(tc, "descr", 85491.130Smgorny "Trigger a core dump and verify its contents."); 85501.130Smgorny} 85511.130Smgorny 85521.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 85531.130Smgorny{ 85541.130Smgorny const int exitval = 5; 85551.130Smgorny pid_t child, wpid; 85561.130Smgorny#if defined(TWAIT_HAVE_STATUS) 85571.130Smgorny const int sigval = SIGTRAP; 85581.130Smgorny int status; 85591.130Smgorny#endif 85601.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 85611.130Smgorny int core_fd; 85621.130Smgorny struct netbsd_elfcore_procinfo procinfo; 85631.130Smgorny 85641.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 85651.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 85661.130Smgorny if (child == 0) { 85671.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 85681.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 85691.130Smgorny 85701.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 85711.130Smgorny trigger_trap(); 85721.130Smgorny 85731.130Smgorny DPRINTF("Before exiting of the child process\n"); 85741.130Smgorny _exit(exitval); 85751.130Smgorny } 85761.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 85771.130Smgorny 85781.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 85791.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 85801.130Smgorny 85811.130Smgorny validate_status_stopped(status, sigval); 85821.130Smgorny 85831.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 85841.130Smgorny close(core_fd); 85851.130Smgorny 85861.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 85871.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 85881.130Smgorny != -1); 85891.130Smgorny 85901.130Smgorny DPRINTF("Read core file\n"); 85911.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 85921.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 85931.130Smgorny sizeof(procinfo)); 85941.130Smgorny 85951.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 85961.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 85971.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 85981.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 85991.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 86001.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 86011.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 86021.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 86031.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 86041.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 86051.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 86061.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 86071.130Smgorny ATF_CHECK_EQ(procinfo.cpi_siglwp, 1); 86081.130Smgorny 86091.130Smgorny unlink(core_path); 86101.130Smgorny 86111.130Smgorny DPRINTF("Before resuming the child process where it left off and " 86121.130Smgorny "without signal to be sent\n"); 86131.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 86141.130Smgorny 86151.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 86161.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 86171.130Smgorny 86181.130Smgorny validate_status_exited(status, exitval); 86191.130Smgorny 86201.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 86211.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 86221.130Smgorny} 86231.130Smgorny 86241.130Smgorny/// ---------------------------------------------------------------------------- 86251.130Smgorny 86261.138Smgorny#if defined(TWAIT_HAVE_STATUS) 86271.138Smgorny 86281.160Smgorny#define THREAD_CONCURRENT_BREAKPOINT_NUM 50 86291.156Smgorny#define THREAD_CONCURRENT_SIGNALS_NUM 50 86301.161Smgorny#define THREAD_CONCURRENT_WATCHPOINT_NUM 50 86311.138Smgorny 86321.138Smgorny/* List of signals to use for the test */ 86331.138Smgornyconst int thread_concurrent_signals_list[] = { 86341.138Smgorny SIGIO, 86351.138Smgorny SIGXCPU, 86361.138Smgorny SIGXFSZ, 86371.138Smgorny SIGVTALRM, 86381.138Smgorny SIGPROF, 86391.138Smgorny SIGWINCH, 86401.138Smgorny SIGINFO, 86411.138Smgorny SIGUSR1, 86421.138Smgorny SIGUSR2 86431.138Smgorny}; 86441.138Smgorny 86451.157Smgornyenum thread_concurrent_signal_handling { 86461.157Smgorny /* the signal is discarded by debugger */ 86471.157Smgorny TCSH_DISCARD, 86481.157Smgorny /* the handler is set to SIG_IGN */ 86491.157Smgorny TCSH_SIG_IGN, 86501.157Smgorny /* an actual handler is used */ 86511.157Smgorny TCSH_HANDLER 86521.157Smgorny}; 86531.157Smgorny 86541.156Smgornystatic pthread_barrier_t thread_concurrent_barrier; 86551.158Smgornystatic pthread_key_t thread_concurrent_key; 86561.161Smgornystatic uint32_t thread_concurrent_watchpoint_var = 0; 86571.138Smgorny 86581.160Smgornystatic void * 86591.160Smgornythread_concurrent_breakpoint_thread(void *arg) 86601.160Smgorny{ 86611.160Smgorny static volatile int watchme = 1; 86621.160Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 86631.160Smgorny DPRINTF("Before entering breakpoint func from LWP %d\n", _lwp_self()); 86641.160Smgorny check_happy(watchme); 86651.160Smgorny return NULL; 86661.160Smgorny} 86671.160Smgorny 86681.157Smgornystatic void 86691.157Smgornythread_concurrent_sig_handler(int sig) 86701.157Smgorny{ 86711.158Smgorny void *tls_val = pthread_getspecific(thread_concurrent_key); 86721.158Smgorny DPRINTF("Before increment, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 86731.158Smgorny FORKEE_ASSERT(pthread_setspecific(thread_concurrent_key, 86741.158Smgorny (void*)((uintptr_t)tls_val + 1)) == 0); 86751.157Smgorny} 86761.157Smgorny 86771.138Smgornystatic void * 86781.138Smgornythread_concurrent_signals_thread(void *arg) 86791.138Smgorny{ 86801.138Smgorny int sigval = thread_concurrent_signals_list[ 86811.138Smgorny _lwp_self() % __arraycount(thread_concurrent_signals_list)]; 86821.158Smgorny enum thread_concurrent_signal_handling *signal_handle = arg; 86831.158Smgorny void *tls_val; 86841.158Smgorny 86851.156Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 86861.138Smgorny DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval), 86871.138Smgorny _lwp_self()); 86881.138Smgorny pthread_kill(pthread_self(), sigval); 86891.158Smgorny if (*signal_handle == TCSH_HANDLER) { 86901.158Smgorny tls_val = pthread_getspecific(thread_concurrent_key); 86911.158Smgorny DPRINTF("After raising, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 86921.158Smgorny FORKEE_ASSERT(tls_val == (void*)1); 86931.158Smgorny } 86941.138Smgorny return NULL; 86951.138Smgorny} 86961.138Smgorny 86971.161Smgornystatic void * 86981.161Smgornythread_concurrent_watchpoint_thread(void *arg) 86991.161Smgorny{ 87001.161Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 87011.161Smgorny DPRINTF("Before modifying var from LWP %d\n", _lwp_self()); 87021.161Smgorny thread_concurrent_watchpoint_var = 1; 87031.161Smgorny return NULL; 87041.161Smgorny} 87051.161Smgorny 87061.160Smgorny#if defined(__i386__) || defined(__x86_64__) 87071.160Smgornyenum thread_concurrent_sigtrap_event { 87081.160Smgorny TCSE_UNKNOWN, 87091.161Smgorny TCSE_BREAKPOINT, 87101.161Smgorny TCSE_WATCHPOINT 87111.160Smgorny}; 87121.160Smgorny 87131.160Smgornystatic void 87141.160Smgornythread_concurrent_lwp_setup(pid_t child, lwpid_t lwpid); 87151.160Smgornystatic enum thread_concurrent_sigtrap_event 87161.160Smgornythread_concurrent_handle_sigtrap(pid_t child, ptrace_siginfo_t *info); 87171.160Smgorny#endif 87181.160Smgorny 87191.156Smgornystatic void 87201.157Smgornythread_concurrent_test(enum thread_concurrent_signal_handling signal_handle, 87211.161Smgorny int breakpoint_threads, int signal_threads, int watchpoint_threads) 87221.138Smgorny{ 87231.138Smgorny const int exitval = 5; 87241.138Smgorny const int sigval = SIGSTOP; 87251.138Smgorny pid_t child, wpid; 87261.138Smgorny int status; 87271.141Skamil struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM] 87281.141Skamil = {{0, 0}}; 87291.160Smgorny struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 87301.160Smgorny = {{0, 0}}; 87311.161Smgorny struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 87321.161Smgorny = {{0, 0}}; 87331.159Smgorny ptrace_event_t event; 87341.156Smgorny int i; 87351.156Smgorny 87361.164Skamil#if defined(HAVE_DBREGS) 87371.164Skamil if (!can_we_set_dbregs()) { 87381.164Skamil atf_tc_skip("Either run this test as root or set sysctl(3) " 87391.164Skamil "security.models.extensions.user_set_dbregs to 1"); 87401.164Skamil } 87411.164Skamil#endif 87421.164Skamil 87431.164Skamil atf_tc_skip("PR kern/54960"); 87441.157Smgorny 87451.156Smgorny /* Protect against out-of-bounds array access. */ 87461.160Smgorny ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM); 87471.156Smgorny ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM); 87481.161Smgorny ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM); 87491.138Smgorny 87501.138Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 87511.138Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 87521.138Smgorny if (child == 0) { 87531.160Smgorny pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM]; 87541.156Smgorny pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM]; 87551.161Smgorny pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM]; 87561.138Smgorny 87571.138Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 87581.138Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 87591.138Smgorny 87601.138Smgorny DPRINTF("Before raising %s from child\n", strsignal(sigval)); 87611.138Smgorny FORKEE_ASSERT(raise(sigval) == 0); 87621.138Smgorny 87631.157Smgorny if (signal_handle != TCSH_DISCARD) { 87641.157Smgorny struct sigaction sa; 87651.157Smgorny unsigned int j; 87661.157Smgorny 87671.157Smgorny memset(&sa, 0, sizeof(sa)); 87681.157Smgorny if (signal_handle == TCSH_SIG_IGN) 87691.157Smgorny sa.sa_handler = SIG_IGN; 87701.157Smgorny else 87711.157Smgorny sa.sa_handler = thread_concurrent_sig_handler; 87721.157Smgorny sigemptyset(&sa.sa_mask); 87731.157Smgorny 87741.157Smgorny for (j = 0; 87751.157Smgorny j < __arraycount(thread_concurrent_signals_list); 87761.157Smgorny j++) 87771.157Smgorny FORKEE_ASSERT(sigaction( 87781.157Smgorny thread_concurrent_signals_list[j], &sa, NULL) 87791.157Smgorny != -1); 87801.157Smgorny } 87811.157Smgorny 87821.138Smgorny DPRINTF("Before starting threads from the child\n"); 87831.138Smgorny FORKEE_ASSERT(pthread_barrier_init( 87841.156Smgorny &thread_concurrent_barrier, NULL, 87851.161Smgorny breakpoint_threads + signal_threads + watchpoint_threads) 87861.161Smgorny == 0); 87871.158Smgorny FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL) 87881.158Smgorny == 0); 87891.138Smgorny 87901.156Smgorny for (i = 0; i < signal_threads; i++) { 87911.156Smgorny FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL, 87921.158Smgorny thread_concurrent_signals_thread, 87931.158Smgorny &signal_handle) == 0); 87941.138Smgorny } 87951.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 87961.160Smgorny FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL, 87971.160Smgorny thread_concurrent_breakpoint_thread, NULL) == 0); 87981.160Smgorny } 87991.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 88001.161Smgorny FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL, 88011.161Smgorny thread_concurrent_watchpoint_thread, NULL) == 0); 88021.161Smgorny } 88031.138Smgorny 88041.138Smgorny DPRINTF("Before joining threads from the child\n"); 88051.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 88061.161Smgorny FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0); 88071.161Smgorny } 88081.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 88091.160Smgorny FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0); 88101.160Smgorny } 88111.156Smgorny for (i = 0; i < signal_threads; i++) { 88121.156Smgorny FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0); 88131.138Smgorny } 88141.138Smgorny 88151.158Smgorny FORKEE_ASSERT(pthread_key_delete(thread_concurrent_key) == 0); 88161.138Smgorny FORKEE_ASSERT(pthread_barrier_destroy( 88171.156Smgorny &thread_concurrent_barrier) == 0); 88181.138Smgorny 88191.138Smgorny DPRINTF("Before exiting of the child process\n"); 88201.138Smgorny _exit(exitval); 88211.138Smgorny } 88221.138Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 88231.138Smgorny 88241.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 88251.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 88261.138Smgorny 88271.138Smgorny validate_status_stopped(status, sigval); 88281.138Smgorny 88291.159Smgorny DPRINTF("Set LWP event mask for the child process\n"); 88301.159Smgorny memset(&event, 0, sizeof(event)); 88311.159Smgorny event.pe_set_event |= PTRACE_LWP_CREATE; 88321.159Smgorny SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event)) 88331.159Smgorny != -1); 88341.159Smgorny 88351.138Smgorny DPRINTF("Before resuming the child process where it left off\n"); 88361.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 88371.138Smgorny 88381.138Smgorny DPRINTF("Before entering signal collection loop\n"); 88391.138Smgorny while (1) { 88401.138Smgorny ptrace_siginfo_t info; 88411.138Smgorny 88421.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 88431.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 88441.138Smgorny child); 88451.138Smgorny if (WIFEXITED(status)) 88461.138Smgorny break; 88471.138Smgorny /* Note: we use validate_status_stopped() to get nice error 88481.138Smgorny * message. Signal is irrelevant since it won't be reached. 88491.138Smgorny */ 88501.138Smgorny else if (!WIFSTOPPED(status)) 88511.138Smgorny validate_status_stopped(status, 0); 88521.138Smgorny 88531.138Smgorny DPRINTF("Before calling PT_GET_SIGINFO\n"); 88541.138Smgorny SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 88551.138Smgorny sizeof(info)) != -1); 88561.138Smgorny 88571.138Smgorny DPRINTF("Received signal %d from LWP %d (wait: %d)\n", 88581.138Smgorny info.psi_siginfo.si_signo, info.psi_lwpid, 88591.138Smgorny WSTOPSIG(status)); 88601.138Smgorny 88611.159Smgorny ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status), 88621.159Smgorny "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid, 88631.159Smgorny WSTOPSIG(status), info.psi_siginfo.si_signo); 88641.159Smgorny 88651.159Smgorny if (WSTOPSIG(status) != SIGTRAP) { 88661.159Smgorny int expected_sig = 88671.159Smgorny thread_concurrent_signals_list[info.psi_lwpid % 88681.159Smgorny __arraycount(thread_concurrent_signals_list)]; 88691.159Smgorny ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig, 88701.159Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 88711.159Smgorny expected_sig, WSTOPSIG(status)); 88721.138Smgorny 88731.159Smgorny *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1; 88741.160Smgorny } else if (info.psi_siginfo.si_code == TRAP_LWP) { 88751.160Smgorny#if defined(__i386__) || defined(__x86_64__) 88761.160Smgorny thread_concurrent_lwp_setup(child, info.psi_lwpid); 88771.160Smgorny#endif 88781.159Smgorny } else { 88791.160Smgorny#if defined(__i386__) || defined(__x86_64__) 88801.160Smgorny switch (thread_concurrent_handle_sigtrap(child, &info)) { 88811.160Smgorny case TCSE_UNKNOWN: 88821.160Smgorny /* already reported inside the function */ 88831.160Smgorny break; 88841.160Smgorny case TCSE_BREAKPOINT: 88851.160Smgorny *FIND_EVENT_COUNT(bp_counts, 88861.160Smgorny info.psi_lwpid) += 1; 88871.160Smgorny break; 88881.161Smgorny case TCSE_WATCHPOINT: 88891.161Smgorny *FIND_EVENT_COUNT(wp_counts, 88901.161Smgorny info.psi_lwpid) += 1; 88911.161Smgorny break; 88921.160Smgorny } 88931.160Smgorny#else 88941.160Smgorny ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n", 88951.160Smgorny info.psi_siginfo.si_code); 88961.160Smgorny#endif 88971.159Smgorny } 88981.138Smgorny 88991.138Smgorny DPRINTF("Before resuming the child process\n"); 89001.157Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 89011.159Smgorny signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP 89021.159Smgorny ? WSTOPSIG(status) : 0) != -1); 89031.138Smgorny } 89041.138Smgorny 89051.156Smgorny for (i = 0; i < signal_threads; i++) 89061.141Skamil ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1, 89071.141Skamil "signal_counts[%d].lec_count=%d; lec_lwp=%d", 89081.141Skamil i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 89091.156Smgorny for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++) 89101.156Smgorny ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0, 89111.156Smgorny "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d", 89121.156Smgorny i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 89131.138Smgorny 89141.160Smgorny for (i = 0; i < breakpoint_threads; i++) 89151.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1, 89161.160Smgorny "bp_counts[%d].lec_count=%d; lec_lwp=%d", 89171.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 89181.160Smgorny for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++) 89191.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0, 89201.160Smgorny "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d", 89211.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 89221.160Smgorny 89231.161Smgorny for (i = 0; i < watchpoint_threads; i++) 89241.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1, 89251.161Smgorny "wp_counts[%d].lec_count=%d; lec_lwp=%d", 89261.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 89271.161Smgorny for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++) 89281.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0, 89291.161Smgorny "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d", 89301.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 89311.161Smgorny 89321.138Smgorny validate_status_exited(status, exitval); 89331.138Smgorny} 89341.138Smgorny 89351.161Smgorny#define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr) \ 89361.156SmgornyATF_TC(test); \ 89371.156SmgornyATF_TC_HEAD(test, tc) \ 89381.156Smgorny{ \ 89391.156Smgorny atf_tc_set_md_var(tc, "descr", descr); \ 89401.156Smgorny} \ 89411.156Smgorny \ 89421.156SmgornyATF_TC_BODY(test, tc) \ 89431.156Smgorny{ \ 89441.161Smgorny thread_concurrent_test(sig_hdl, bps, sigs, wps); \ 89451.156Smgorny} 89461.156Smgorny 89471.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD, 89481.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 89491.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 89501.157Smgorny "correctly"); 89511.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN, 89521.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 89531.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 89541.157Smgorny "correctly and passed back to SIG_IGN handler"); 89551.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER, 89561.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 89571.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 89581.157Smgorny "correctly and passed back to a handler function"); 89591.156Smgorny 89601.163Skamil#if defined(__i386__) || defined(__x86_64__) 89611.160SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD, 89621.161Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0, 89631.161Smgorny "Verify that concurrent breakpoints are reported correctly"); 89641.161SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD, 89651.161Smgorny 0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 89661.160Smgorny "Verify that concurrent breakpoints are reported correctly"); 89671.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD, 89681.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 89691.162Smgorny "Verify that concurrent breakpoints and watchpoints are reported " 89701.162Smgorny "correctly"); 89711.162Smgorny 89721.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD, 89731.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 89741.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly"); 89751.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN, 89761.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 89771.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 89781.162Smgorny "and passed back to SIG_IGN handler"); 89791.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER, 89801.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 89811.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 89821.162Smgorny "and passed back to a handler function"); 89831.162Smgorny 89841.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD, 89851.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 89861.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly"); 89871.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN, 89881.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 89891.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 89901.162Smgorny "and passed back to SIG_IGN handler"); 89911.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER, 89921.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 89931.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 89941.162Smgorny "and passed back to a handler function"); 89951.162Smgorny 89961.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD, 89971.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 89981.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 89991.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90001.162Smgorny "correctly"); 90011.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN, 90021.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 90031.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 90041.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90051.162Smgorny "correctly and passed back to SIG_IGN handler"); 90061.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER, 90071.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 90081.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 90091.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90101.162Smgorny "correctly and passed back to a handler function"); 90111.163Skamil#endif 90121.160Smgorny 90131.138Smgorny#endif /*defined(TWAIT_HAVE_STATUS)*/ 90141.138Smgorny 90151.138Smgorny/// ---------------------------------------------------------------------------- 90161.138Smgorny 90171.1Skamil#include "t_ptrace_amd64_wait.h" 90181.1Skamil#include "t_ptrace_i386_wait.h" 90191.1Skamil#include "t_ptrace_x86_wait.h" 90201.1Skamil 90211.165Skamil/// ---------------------------------------------------------------------------- 90221.165Skamil 90231.165Skamil#else 90241.165SkamilATF_TC(dummy); 90251.165SkamilATF_TC_HEAD(dummy, tc) 90261.165Skamil{ 90271.165Skamil atf_tc_set_md_var(tc, "descr", "A dummy test"); 90281.165Skamil} 90291.165Skamil 90301.165SkamilATF_TC_BODY(dummy, tc) 90311.165Skamil{ 90321.165Skamil 90331.165Skamil // Dummy, skipped 90341.165Skamil // The ATF framework requires at least a single defined test. 90351.165Skamil} 90361.165Skamil#endif 90371.165Skamil 90381.1SkamilATF_TP_ADD_TCS(tp) 90391.1Skamil{ 90401.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 90411.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 90421.33Skamil 90431.165Skamil#ifdef ENABLE_TESTS 90441.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 90451.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 90461.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 90471.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 90481.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 90491.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 90501.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 90511.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 90521.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 90531.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 90541.33Skamil 90551.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 90561.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 90571.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 90581.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 90591.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 90601.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 90611.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 90621.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 90631.87Skamil 90641.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 90651.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 90661.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 90671.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 90681.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 90691.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 90701.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 90711.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 90721.86Skamil 90731.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 90741.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 90751.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 90761.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 90771.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 90781.59Skamil 90791.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 90801.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 90811.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 90821.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 90831.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 90841.88Skamil 90851.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 90861.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 90871.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 90881.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 90891.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 90901.88Skamil 90911.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 90921.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 90931.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 90941.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 90951.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 90961.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 90971.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 90981.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 90991.50Skamil 91001.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 91011.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 91021.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 91031.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 91041.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 91051.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 91061.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 91071.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 91081.50Skamil 91091.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 91101.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 91111.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 91121.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 91131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 91141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 91151.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 91161.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 91171.50Skamil 91181.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 91191.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 91201.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 91211.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 91221.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 91231.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 91241.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 91251.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 91261.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 91271.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 91281.1Skamil 91291.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 91301.37Skamil 91311.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 91321.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 91331.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 91341.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 91351.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 91361.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 91371.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 91381.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 91391.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 91401.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 91411.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 91421.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 91431.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 91441.40Skamil 91451.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 91461.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 91471.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 91481.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 91491.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 91501.41Skamil 91511.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 91521.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 91531.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 91541.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 91551.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 91561.92Skamil 91571.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 91581.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 91591.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 91601.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 91611.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 91621.92Skamil 91631.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 91641.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 91651.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 91661.43Skamil 91671.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 91681.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 91691.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 91701.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 91711.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 91721.59Skamil 91731.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91741.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 91751.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91761.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 91771.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91781.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 91791.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91801.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 91811.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91821.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 91831.94Skamil 91841.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91851.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 91861.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91871.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 91881.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91891.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 91901.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91911.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 91921.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 91931.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 91941.94Skamil 91951.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 91961.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 91971.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 91981.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 91991.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 92001.51Skamil 92011.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 92021.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 92031.51Skamil 92041.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 92051.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 92061.51Skamil 92071.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92081.51Skamil tracee_sees_its_original_parent_getppid); 92091.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92101.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 92111.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92121.51Skamil tracee_sees_its_original_parent_procfs_status); 92131.1Skamil 92141.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 92151.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 92161.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 92171.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 92181.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 92191.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 92201.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 92211.1Skamil 92221.31Skamil ATF_TP_ADD_TC(tp, fork1); 92231.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 92241.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 92251.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 92261.31Skamil ATF_TP_ADD_TC(tp, fork5); 92271.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 92281.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 92291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 92301.125Skamil ATF_TP_ADD_TC(tp, fork9); 92311.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 92321.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 92331.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 92341.125Skamil ATF_TP_ADD_TC(tp, fork13); 92351.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 92361.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 92371.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 92381.31Skamil 92391.31Skamil ATF_TP_ADD_TC(tp, vfork1); 92401.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 92411.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 92421.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 92431.31Skamil ATF_TP_ADD_TC(tp, vfork5); 92441.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 92451.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 92461.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 92471.125Skamil ATF_TP_ADD_TC(tp, vfork9); 92481.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 92491.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 92501.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 92511.125Skamil ATF_TP_ADD_TC(tp, vfork13); 92521.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 92531.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 92541.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 92551.1Skamil 92561.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 92571.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 92581.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 92591.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 92601.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 92611.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 92621.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 92631.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 92641.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 92651.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 92661.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 92671.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 92681.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 92691.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 92701.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 92711.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 92721.124Skamil 92731.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork1); 92741.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork2); 92751.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork3); 92761.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork4); 92771.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork5); 92781.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork6); 92791.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork7); 92801.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork8); 92811.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork9); 92821.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork10); 92831.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork11); 92841.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork12); 92851.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork13); 92861.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork14); 92871.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork15); 92881.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork16); 92891.149Skamil 92901.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork1); 92911.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork2); 92921.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork3); 92931.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork4); 92941.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork5); 92951.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork6); 92961.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork7); 92971.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork8); 92981.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork9); 92991.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork10); 93001.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork11); 93011.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork12); 93021.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork13); 93031.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork14); 93041.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork15); 93051.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork16); 93061.149Skamil 93071.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn1); 93081.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn2); 93091.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn3); 93101.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn4); 93111.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn5); 93121.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn6); 93131.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn7); 93141.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn8); 93151.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn9); 93161.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn10); 93171.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn11); 93181.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn12); 93191.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn13); 93201.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn14); 93211.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn15); 93221.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn16); 93231.149Skamil 93241.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 93251.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 93261.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 93271.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 93281.126Skamil 93291.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 93301.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 93311.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 93321.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 93331.116Skamil 93341.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn_detach_spawner); 93351.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork_detach_forker); 93361.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_detach_vforker); 93371.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_detach_vforkerdone); 93381.150Skamil 93391.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn_kill_spawner); 93401.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork_kill_forker); 93411.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_kill_vforker); 93421.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_kill_vforkerdone); 93431.150Skamil 93441.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 93451.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 93461.108Skamil 93471.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 93481.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 93491.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 93501.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 93511.54Skamil 93521.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 93531.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 93541.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 93551.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 93561.54Skamil 93571.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 93581.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 93591.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 93601.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 93611.54Skamil 93621.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 93631.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 93641.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 93651.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 93661.54Skamil 93671.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 93681.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 93691.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 93701.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 93711.54Skamil 93721.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 93731.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 93741.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 93751.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 93761.54Skamil 93771.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 93781.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 93791.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 93801.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 93811.54Skamil 93821.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 93831.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 93841.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 93851.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 93861.54Skamil 93871.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 93881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 93891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 93901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 93911.54Skamil 93921.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 93931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 93941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 93951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 93961.1Skamil 93971.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 93981.1Skamil 93991.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 94001.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 94011.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 94021.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 94031.101Skamil 94041.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 94051.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 94061.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 94071.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 94081.101Skamil 94091.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 94101.101Skamil 94111.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 94121.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 94131.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 94141.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 94151.115Skamil 94161.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 94171.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 94181.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 94191.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 94201.115Skamil 94211.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 94221.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 94231.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 94241.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 94251.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 94261.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 94271.1Skamil 94281.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x1); 94291.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x3); 94301.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x7); 94311.147Skamil 94321.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 94331.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 94341.1Skamil 94351.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 94361.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 94371.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 94381.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 94391.1Skamil 94401.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 94411.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 94421.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 94431.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 94441.2Skamil 94451.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 94461.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 94471.95Skamil 94481.1Skamil ATF_TP_ADD_TC(tp, kill1); 94491.1Skamil ATF_TP_ADD_TC(tp, kill2); 94501.75Skamil ATF_TP_ADD_TC(tp, kill3); 94511.1Skamil 94521.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 94531.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 94541.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 94551.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 94561.77Skamil 94571.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus); 94581.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus); 94591.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus); 94601.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus); 94611.143Skamil 94621.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_sigmask); 94631.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_sigmask); 94641.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_sigmask); 94651.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_sigmask); 94661.143Skamil 94671.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_name); 94681.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_name); 94691.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_name); 94701.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_name); 94711.143Skamil 94721.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_private); 94731.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_private); 94741.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_private); 94751.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_private); 94761.143Skamil 94771.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0); 94781.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1); 94791.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2); 94801.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3); 94811.143Skamil 94821.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_sigmask); 94831.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_sigmask); 94841.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_sigmask); 94851.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_sigmask); 94861.143Skamil 94871.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_name); 94881.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_name); 94891.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_name); 94901.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_name); 94911.143Skamil 94921.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_private); 94931.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_private); 94941.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_private); 94951.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_private); 94961.143Skamil 94971.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 94981.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 94991.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 95001.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 95011.1Skamil 95021.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 95031.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 95041.79Skamil 95051.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 95061.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 95071.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 95081.1Skamil 95091.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 95101.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 95111.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 95121.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 95131.1Skamil 95141.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap); 95151.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap); 95161.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap); 95171.153Skamil 95181.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 95191.84Skamil 95201.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 95211.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 95221.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 95231.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 95241.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 95251.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 95261.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 95271.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 95281.99Skamil 95291.151Skamil ATF_TP_ADD_TC(tp, threads_and_exec); 95301.151Skamil 95311.154Skamil ATF_TP_ADD_TC(tp, suspend_no_deadlock); 95321.1Skamil 95331.155Skamil ATF_TP_ADD_TC(tp, resume); 95341.1Skamil 95351.1Skamil ATF_TP_ADD_TC(tp, syscall1); 95361.1Skamil 95371.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 95381.1Skamil 95391.106Skamil ATF_TP_ADD_TC(tp, clone1); 95401.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 95411.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 95421.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 95431.106Skamil ATF_TP_ADD_TC(tp, clone5); 95441.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 95451.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 95461.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 95471.106Skamil 95481.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 95491.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 95501.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 95511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 95521.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 95531.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 95541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 95551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 95561.106Skamil 95571.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 95581.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 95591.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 95601.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 95611.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 95621.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 95631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 95641.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 95651.106Skamil 95661.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 95671.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 95681.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 95691.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 95701.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 95711.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 95721.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 95731.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 95741.106Skamil 95751.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 95761.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 95771.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 95781.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 95791.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 95801.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 95811.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 95821.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 95831.106Skamil 95841.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 95851.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 95861.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 95871.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 95881.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 95891.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 95901.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 95911.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 95921.106Skamil 95931.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 95941.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 95951.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 95961.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 95971.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 95981.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 95991.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 96001.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 96011.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 96021.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 96031.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 96041.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 96051.103Skamil 96061.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 96071.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 96081.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 96091.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 96101.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 96111.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 96121.107Skamil 96131.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 96141.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 96151.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 96161.122Skamil 96171.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 96181.130Smgorny 96191.138Smgorny#if defined(TWAIT_HAVE_STATUS) 96201.138Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals); 96211.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_sig_ign); 96221.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_handler); 96231.160Smgorny#if defined(__i386__) || defined(__x86_64__) 96241.160Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_breakpoints); 96251.161Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_watchpoints); 96261.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp); 96271.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig); 96281.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_sig_ign); 96291.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_handler); 96301.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig); 96311.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_sig_ign); 96321.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_handler); 96331.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig); 96341.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_sig_ign); 96351.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_handler); 96361.160Smgorny#endif 96371.138Smgorny#endif 96381.138Smgorny 96391.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 96401.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 96411.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 96421.1Skamil 96431.165Skamil#else 96441.165Skamil ATF_TP_ADD_TC(tp, dummy); 96451.165Skamil#endif 96461.165Skamil 96471.1Skamil return atf_no_error(); 96481.1Skamil} 9649