t_ptrace_wait.c revision 1.170
11.170Skamil/* $NetBSD: t_ptrace_wait.c,v 1.170 2020/04/14 22:37:24 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.170Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.170 2020/04/14 22:37:24 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.121Smgorny#if defined(__i386__) || defined(__x86_64__) 641.121Smgorny#include <cpuid.h> 651.121Smgorny#include <x86/cpu_extended_state.h> 661.129Smgorny#include <x86/specialreg.h> 671.121Smgorny#endif 681.121Smgorny 691.130Smgorny#include <libelf.h> 701.130Smgorny#include <gelf.h> 711.130Smgorny 721.1Skamil#include <atf-c.h> 731.1Skamil 741.165Skamil#ifdef ENABLE_TESTS 751.165Skamil 761.132Skamil/* Assumptions in the kernel code that must be kept. */ 771.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_report_event) == 781.132Skamil sizeof(((siginfo_t *)0)->si_pe_report_event), 791.132Skamil "pe_report_event and si_pe_report_event must be of the same size"); 801.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 811.132Skamil sizeof(((siginfo_t *)0)->si_pe_other_pid), 821.132Skamil "pe_other_pid and si_pe_other_pid must be of the same size"); 831.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_lwp) == 841.132Skamil sizeof(((siginfo_t *)0)->si_pe_lwp), 851.132Skamil "pe_lwp and si_pe_lwp must be of the same size"); 861.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 871.132Skamil sizeof(((struct ptrace_state *)0)->pe_lwp), 881.132Skamil "pe_other_pid and pe_lwp must be of the same size"); 891.132Skamil 901.1Skamil#include "h_macros.h" 911.1Skamil 921.1Skamil#include "t_ptrace_wait.h" 931.1Skamil#include "msg.h" 941.1Skamil 951.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 961.13Schristos strerror(errno)) 971.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 981.18Schristos "%d(%s) != %d", res, strerror(res), exp) 991.13Schristos 1001.152Skamilstatic int debug = 0; 1011.13Schristos 1021.13Schristos#define DPRINTF(a, ...) do \ 1031.123Skamil if (debug) \ 1041.142Skamil printf("%s() %d.%d %s:%d " a, \ 1051.142Skamil __func__, getpid(), _lwp_self(), __FILE__, __LINE__, ##__VA_ARGS__); \ 1061.13Schristos while (/*CONSTCOND*/0) 1071.1Skamil 1081.34Skamil/// ---------------------------------------------------------------------------- 1091.34Skamil 1101.33Skamilstatic void 1111.33Skamiltraceme_raise(int sigval) 1121.1Skamil{ 1131.1Skamil const int exitval = 5; 1141.1Skamil pid_t child, wpid; 1151.1Skamil#if defined(TWAIT_HAVE_STATUS) 1161.1Skamil int status; 1171.1Skamil#endif 1181.1Skamil 1191.133Skamil ptrace_state_t state, zero_state; 1201.133Skamil const int slen = sizeof(state); 1211.45Skamil struct ptrace_siginfo info; 1221.133Skamil memset(&zero_state, 0, sizeof(zero_state)); 1231.45Skamil memset(&info, 0, sizeof(info)); 1241.45Skamil 1251.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1261.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1271.1Skamil if (child == 0) { 1281.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1291.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1301.1Skamil 1311.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1321.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1331.1Skamil 1341.36Skamil switch (sigval) { 1351.36Skamil case SIGKILL: 1361.36Skamil /* NOTREACHED */ 1371.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1381.70Smrg __unreachable(); 1391.36Skamil default: 1401.36Skamil DPRINTF("Before exiting of the child process\n"); 1411.36Skamil _exit(exitval); 1421.36Skamil } 1431.1Skamil } 1441.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1451.1Skamil 1461.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1481.1Skamil 1491.36Skamil switch (sigval) { 1501.36Skamil case SIGKILL: 1511.36Skamil validate_status_signaled(status, sigval, 0); 1521.133Skamil SYSCALL_REQUIRE( 1531.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) == -1); 1541.133Skamil 1551.36Skamil break; 1561.36Skamil default: 1571.36Skamil validate_status_stopped(status, sigval); 1581.1Skamil 1591.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1601.61Skre "child\n"); 1611.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1621.61Skre sizeof(info)) != -1); 1631.45Skamil 1641.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1651.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1661.61Skre "si_errno=%#x\n", 1671.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1681.61Skre info.psi_siginfo.si_errno); 1691.45Skamil 1701.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1711.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1721.45Skamil 1731.133Skamil DPRINTF("Assert that PT_GET_PROCESS_STATE returns non-error"); 1741.133Skamil SYSCALL_REQUIRE( 1751.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 1761.133Skamil ATF_REQUIRE(memcmp(&state, &zero_state, slen) == 0); 1771.133Skamil 1781.36Skamil DPRINTF("Before resuming the child process where it left off " 1791.36Skamil "and without signal to be sent\n"); 1801.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1811.1Skamil 1821.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1831.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1841.61Skre child); 1851.36Skamil break; 1861.36Skamil } 1871.1Skamil 1881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1891.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1901.1Skamil} 1911.1Skamil 1921.61Skre#define TRACEME_RAISE(test, sig) \ 1931.61SkreATF_TC(test); \ 1941.61SkreATF_TC_HEAD(test, tc) \ 1951.61Skre{ \ 1961.61Skre atf_tc_set_md_var(tc, "descr", \ 1971.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1981.61Skre} \ 1991.61Skre \ 2001.61SkreATF_TC_BODY(test, tc) \ 2011.61Skre{ \ 2021.61Skre \ 2031.61Skre traceme_raise(sig); \ 2041.33Skamil} 2051.33Skamil 2061.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2071.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2081.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2091.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2101.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2111.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2121.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2131.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2141.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2151.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2161.33Skamil 2171.34Skamil/// ---------------------------------------------------------------------------- 2181.1Skamil 2191.1Skamilstatic void 2201.87Skamiltraceme_raisesignal_ignored(int sigignored) 2211.87Skamil{ 2221.87Skamil const int exitval = 5; 2231.87Skamil const int sigval = SIGSTOP; 2241.87Skamil pid_t child, wpid; 2251.87Skamil struct sigaction sa; 2261.87Skamil#if defined(TWAIT_HAVE_STATUS) 2271.87Skamil int status; 2281.87Skamil#endif 2291.87Skamil struct ptrace_siginfo info; 2301.87Skamil 2311.87Skamil memset(&info, 0, sizeof(info)); 2321.87Skamil 2331.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2341.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2351.87Skamil if (child == 0) { 2361.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2371.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2381.87Skamil 2391.87Skamil memset(&sa, 0, sizeof(sa)); 2401.87Skamil sa.sa_handler = SIG_IGN; 2411.87Skamil sigemptyset(&sa.sa_mask); 2421.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2431.87Skamil 2441.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2451.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2461.87Skamil 2471.87Skamil DPRINTF("Before raising %s from child\n", 2481.87Skamil strsignal(sigignored)); 2491.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2501.87Skamil 2511.87Skamil DPRINTF("Before exiting of the child process\n"); 2521.87Skamil _exit(exitval); 2531.87Skamil } 2541.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2551.87Skamil 2561.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2571.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2581.87Skamil 2591.87Skamil validate_status_stopped(status, sigval); 2601.87Skamil 2611.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2621.87Skamil SYSCALL_REQUIRE( 2631.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2641.87Skamil 2651.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2661.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2671.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2681.87Skamil info.psi_siginfo.si_errno); 2691.87Skamil 2701.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2711.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2721.87Skamil 2731.87Skamil DPRINTF("Before resuming the child process where it left off and " 2741.87Skamil "without signal to be sent\n"); 2751.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 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, sigignored); 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, sigignored); 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_exited(status, exitval); 3021.87Skamil 3031.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3041.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3051.87Skamil} 3061.87Skamil 3071.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3081.87SkamilATF_TC(test); \ 3091.87SkamilATF_TC_HEAD(test, tc) \ 3101.87Skamil{ \ 3111.87Skamil atf_tc_set_md_var(tc, "descr", \ 3121.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3131.87Skamil "does not stop tracer from catching this raised signal"); \ 3141.87Skamil} \ 3151.87Skamil \ 3161.87SkamilATF_TC_BODY(test, tc) \ 3171.87Skamil{ \ 3181.87Skamil \ 3191.87Skamil traceme_raisesignal_ignored(sig); \ 3201.87Skamil} 3211.87Skamil 3221.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3231.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3241.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3251.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3261.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3271.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3281.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3291.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3301.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3311.87Skamil 3321.87Skamil/// ---------------------------------------------------------------------------- 3331.87Skamil 3341.87Skamilstatic void 3351.86Skamiltraceme_raisesignal_masked(int sigmasked) 3361.86Skamil{ 3371.86Skamil const int exitval = 5; 3381.86Skamil const int sigval = SIGSTOP; 3391.86Skamil pid_t child, wpid; 3401.86Skamil#if defined(TWAIT_HAVE_STATUS) 3411.86Skamil int status; 3421.86Skamil#endif 3431.86Skamil sigset_t intmask; 3441.86Skamil struct ptrace_siginfo info; 3451.86Skamil 3461.86Skamil memset(&info, 0, sizeof(info)); 3471.86Skamil 3481.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3491.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3501.86Skamil if (child == 0) { 3511.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3521.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3531.86Skamil 3541.86Skamil sigemptyset(&intmask); 3551.86Skamil sigaddset(&intmask, sigmasked); 3561.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3571.86Skamil 3581.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3591.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3601.86Skamil 3611.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3621.86Skamil strsignal(sigmasked)); 3631.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3641.86Skamil 3651.86Skamil DPRINTF("Before exiting of the child process\n"); 3661.86Skamil _exit(exitval); 3671.86Skamil } 3681.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3691.86Skamil 3701.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3711.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3721.86Skamil 3731.86Skamil validate_status_stopped(status, sigval); 3741.86Skamil 3751.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3761.86Skamil SYSCALL_REQUIRE( 3771.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3781.86Skamil 3791.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3801.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3811.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3821.86Skamil info.psi_siginfo.si_errno); 3831.86Skamil 3841.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3851.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3861.86Skamil 3871.86Skamil DPRINTF("Before resuming the child process where it left off and " 3881.86Skamil "without signal to be sent\n"); 3891.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 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_exited(status, exitval); 3951.86Skamil 3961.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3971.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3981.86Skamil} 3991.86Skamil 4001.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 4011.86SkamilATF_TC(test); \ 4021.86SkamilATF_TC_HEAD(test, tc) \ 4031.86Skamil{ \ 4041.86Skamil atf_tc_set_md_var(tc, "descr", \ 4051.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4061.86Skamil "stops tracer from catching this raised signal"); \ 4071.86Skamil} \ 4081.86Skamil \ 4091.86SkamilATF_TC_BODY(test, tc) \ 4101.86Skamil{ \ 4111.86Skamil \ 4121.86Skamil traceme_raisesignal_masked(sig); \ 4131.86Skamil} 4141.86Skamil 4151.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4161.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4171.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4181.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4191.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4201.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4211.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4221.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4231.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4241.86Skamil 4251.86Skamil/// ---------------------------------------------------------------------------- 4261.86Skamil 4271.86Skamilstatic void 4281.59Skamiltraceme_crash(int sig) 4291.59Skamil{ 4301.59Skamil pid_t child, wpid; 4311.59Skamil#if defined(TWAIT_HAVE_STATUS) 4321.59Skamil int status; 4331.59Skamil#endif 4341.59Skamil struct ptrace_siginfo info; 4351.61Skre 4361.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4371.71Skamil if (sig == SIGILL) 4381.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4391.71Skamil#endif 4401.71Skamil 4411.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4421.114Skamil atf_tc_skip("FP exceptions are not supported"); 4431.114Skamil 4441.59Skamil memset(&info, 0, sizeof(info)); 4451.59Skamil 4461.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4471.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4481.59Skamil if (child == 0) { 4491.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4501.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4511.59Skamil 4521.59Skamil DPRINTF("Before executing a trap\n"); 4531.59Skamil switch (sig) { 4541.59Skamil case SIGTRAP: 4551.59Skamil trigger_trap(); 4561.59Skamil break; 4571.59Skamil case SIGSEGV: 4581.59Skamil trigger_segv(); 4591.59Skamil break; 4601.59Skamil case SIGILL: 4611.59Skamil trigger_ill(); 4621.59Skamil break; 4631.59Skamil case SIGFPE: 4641.59Skamil trigger_fpe(); 4651.59Skamil break; 4661.59Skamil case SIGBUS: 4671.59Skamil trigger_bus(); 4681.59Skamil break; 4691.59Skamil default: 4701.59Skamil /* NOTREACHED */ 4711.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4721.59Skamil } 4731.59Skamil 4741.59Skamil /* NOTREACHED */ 4751.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4761.59Skamil } 4771.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4781.59Skamil 4791.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4801.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4811.59Skamil 4821.59Skamil validate_status_stopped(status, sig); 4831.59Skamil 4841.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4851.61Skre SYSCALL_REQUIRE( 4861.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4871.59Skamil 4881.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4891.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4901.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4911.61Skre info.psi_siginfo.si_errno); 4921.59Skamil 4931.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4941.59Skamil switch (sig) { 4951.59Skamil case SIGTRAP: 4961.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4971.59Skamil break; 4981.59Skamil case SIGSEGV: 4991.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 5001.59Skamil break; 5011.71Skamil case SIGILL: 5021.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 5031.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5041.71Skamil break; 5051.59Skamil case SIGFPE: 5061.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5071.59Skamil break; 5081.59Skamil case SIGBUS: 5091.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5101.59Skamil break; 5111.59Skamil } 5121.59Skamil 5131.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5141.59Skamil 5151.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5161.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5171.59Skamil 5181.59Skamil validate_status_signaled(status, SIGKILL, 0); 5191.59Skamil 5201.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5211.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5221.59Skamil} 5231.59Skamil 5241.61Skre#define TRACEME_CRASH(test, sig) \ 5251.61SkreATF_TC(test); \ 5261.61SkreATF_TC_HEAD(test, tc) \ 5271.61Skre{ \ 5281.61Skre atf_tc_set_md_var(tc, "descr", \ 5291.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5301.61Skre} \ 5311.61Skre \ 5321.61SkreATF_TC_BODY(test, tc) \ 5331.61Skre{ \ 5341.61Skre \ 5351.61Skre traceme_crash(sig); \ 5361.59Skamil} 5371.59Skamil 5381.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5391.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5401.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5411.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5421.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5431.59Skamil 5441.59Skamil/// ---------------------------------------------------------------------------- 5451.59Skamil 5461.59Skamilstatic void 5471.88Skamiltraceme_signalmasked_crash(int sig) 5481.88Skamil{ 5491.89Skamil const int sigval = SIGSTOP; 5501.88Skamil pid_t child, wpid; 5511.88Skamil#if defined(TWAIT_HAVE_STATUS) 5521.88Skamil int status; 5531.88Skamil#endif 5541.88Skamil struct ptrace_siginfo info; 5551.88Skamil sigset_t intmask; 5561.89Skamil struct kinfo_proc2 kp; 5571.89Skamil size_t len = sizeof(kp); 5581.89Skamil 5591.89Skamil int name[6]; 5601.89Skamil const size_t namelen = __arraycount(name); 5611.89Skamil ki_sigset_t kp_sigmask; 5621.88Skamil 5631.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5641.88Skamil if (sig == SIGILL) 5651.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5661.88Skamil#endif 5671.88Skamil 5681.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5691.114Skamil atf_tc_skip("FP exceptions are not supported"); 5701.114Skamil 5711.88Skamil memset(&info, 0, sizeof(info)); 5721.88Skamil 5731.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5741.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5751.88Skamil if (child == 0) { 5761.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5771.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5781.88Skamil 5791.88Skamil sigemptyset(&intmask); 5801.88Skamil sigaddset(&intmask, sig); 5811.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5821.88Skamil 5831.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5841.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5851.89Skamil 5861.88Skamil DPRINTF("Before executing a trap\n"); 5871.88Skamil switch (sig) { 5881.88Skamil case SIGTRAP: 5891.88Skamil trigger_trap(); 5901.88Skamil break; 5911.88Skamil case SIGSEGV: 5921.88Skamil trigger_segv(); 5931.88Skamil break; 5941.88Skamil case SIGILL: 5951.88Skamil trigger_ill(); 5961.88Skamil break; 5971.88Skamil case SIGFPE: 5981.88Skamil trigger_fpe(); 5991.88Skamil break; 6001.88Skamil case SIGBUS: 6011.88Skamil trigger_bus(); 6021.88Skamil break; 6031.88Skamil default: 6041.88Skamil /* NOTREACHED */ 6051.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6061.88Skamil } 6071.88Skamil 6081.88Skamil /* NOTREACHED */ 6091.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6101.88Skamil } 6111.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6121.88Skamil 6131.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6141.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6151.88Skamil 6161.89Skamil validate_status_stopped(status, sigval); 6171.89Skamil 6181.89Skamil name[0] = CTL_KERN, 6191.89Skamil name[1] = KERN_PROC2, 6201.89Skamil name[2] = KERN_PROC_PID; 6211.89Skamil name[3] = child; 6221.89Skamil name[4] = sizeof(kp); 6231.89Skamil name[5] = 1; 6241.89Skamil 6251.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6261.89Skamil 6271.89Skamil kp_sigmask = kp.p_sigmask; 6281.89Skamil 6291.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6301.89Skamil SYSCALL_REQUIRE( 6311.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6321.89Skamil 6331.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6341.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6351.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6361.89Skamil info.psi_siginfo.si_errno); 6371.89Skamil 6381.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6391.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6401.89Skamil 6411.89Skamil DPRINTF("Before resuming the child process where it left off and " 6421.89Skamil "without signal to be sent\n"); 6431.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6441.89Skamil 6451.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6461.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6471.89Skamil 6481.88Skamil validate_status_stopped(status, sig); 6491.88Skamil 6501.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6511.88Skamil SYSCALL_REQUIRE( 6521.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6531.88Skamil 6541.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6551.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6561.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6571.88Skamil info.psi_siginfo.si_errno); 6581.88Skamil 6591.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6601.89Skamil 6611.89Skamil DPRINTF("kp_sigmask=" 6621.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6631.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6641.89Skamil kp_sigmask.__bits[3]); 6651.89Skamil 6661.89Skamil DPRINTF("kp.p_sigmask=" 6671.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6681.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6691.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6701.89Skamil 6711.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6721.89Skamil 6731.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6741.88Skamil switch (sig) { 6751.88Skamil case SIGTRAP: 6761.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6771.88Skamil break; 6781.88Skamil case SIGSEGV: 6791.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6801.88Skamil break; 6811.88Skamil case SIGILL: 6821.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6831.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6841.88Skamil break; 6851.88Skamil case SIGFPE: 6861.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6871.88Skamil break; 6881.88Skamil case SIGBUS: 6891.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6901.88Skamil break; 6911.88Skamil } 6921.88Skamil 6931.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6941.88Skamil 6951.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6961.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6971.88Skamil 6981.88Skamil validate_status_signaled(status, SIGKILL, 0); 6991.88Skamil 7001.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7011.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 7021.88Skamil} 7031.88Skamil 7041.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7051.88SkamilATF_TC(test); \ 7061.88SkamilATF_TC_HEAD(test, tc) \ 7071.88Skamil{ \ 7081.88Skamil atf_tc_set_md_var(tc, "descr", \ 7091.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7101.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7111.88Skamil} \ 7121.88Skamil \ 7131.88SkamilATF_TC_BODY(test, tc) \ 7141.88Skamil{ \ 7151.88Skamil \ 7161.88Skamil traceme_signalmasked_crash(sig); \ 7171.88Skamil} 7181.88Skamil 7191.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7201.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7211.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7221.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7231.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7241.88Skamil 7251.88Skamil/// ---------------------------------------------------------------------------- 7261.88Skamil 7271.88Skamilstatic void 7281.88Skamiltraceme_signalignored_crash(int sig) 7291.88Skamil{ 7301.90Skamil const int sigval = SIGSTOP; 7311.88Skamil pid_t child, wpid; 7321.88Skamil#if defined(TWAIT_HAVE_STATUS) 7331.88Skamil int status; 7341.88Skamil#endif 7351.88Skamil struct sigaction sa; 7361.88Skamil struct ptrace_siginfo info; 7371.90Skamil struct kinfo_proc2 kp; 7381.90Skamil size_t len = sizeof(kp); 7391.90Skamil 7401.90Skamil int name[6]; 7411.90Skamil const size_t namelen = __arraycount(name); 7421.90Skamil ki_sigset_t kp_sigignore; 7431.88Skamil 7441.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7451.88Skamil if (sig == SIGILL) 7461.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7471.88Skamil#endif 7481.88Skamil 7491.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7501.114Skamil atf_tc_skip("FP exceptions are not supported"); 7511.114Skamil 7521.88Skamil memset(&info, 0, sizeof(info)); 7531.88Skamil 7541.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7551.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7561.88Skamil if (child == 0) { 7571.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7581.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7591.88Skamil 7601.88Skamil memset(&sa, 0, sizeof(sa)); 7611.88Skamil sa.sa_handler = SIG_IGN; 7621.88Skamil sigemptyset(&sa.sa_mask); 7631.88Skamil 7641.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7651.88Skamil 7661.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7671.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7681.90Skamil 7691.88Skamil DPRINTF("Before executing a trap\n"); 7701.88Skamil switch (sig) { 7711.88Skamil case SIGTRAP: 7721.88Skamil trigger_trap(); 7731.88Skamil break; 7741.88Skamil case SIGSEGV: 7751.88Skamil trigger_segv(); 7761.88Skamil break; 7771.88Skamil case SIGILL: 7781.88Skamil trigger_ill(); 7791.88Skamil break; 7801.88Skamil case SIGFPE: 7811.88Skamil trigger_fpe(); 7821.88Skamil break; 7831.88Skamil case SIGBUS: 7841.88Skamil trigger_bus(); 7851.88Skamil break; 7861.88Skamil default: 7871.88Skamil /* NOTREACHED */ 7881.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7891.88Skamil } 7901.88Skamil 7911.88Skamil /* NOTREACHED */ 7921.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7931.88Skamil } 7941.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7951.88Skamil 7961.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7971.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7981.88Skamil 7991.90Skamil validate_status_stopped(status, sigval); 8001.90Skamil 8011.90Skamil name[0] = CTL_KERN, 8021.90Skamil name[1] = KERN_PROC2, 8031.90Skamil name[2] = KERN_PROC_PID; 8041.90Skamil name[3] = child; 8051.90Skamil name[4] = sizeof(kp); 8061.90Skamil name[5] = 1; 8071.90Skamil 8081.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8091.90Skamil 8101.90Skamil kp_sigignore = kp.p_sigignore; 8111.90Skamil 8121.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8131.90Skamil SYSCALL_REQUIRE( 8141.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8151.90Skamil 8161.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8171.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8181.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8191.90Skamil info.psi_siginfo.si_errno); 8201.90Skamil 8211.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8221.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8231.90Skamil 8241.90Skamil DPRINTF("Before resuming the child process where it left off and " 8251.90Skamil "without signal to be sent\n"); 8261.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8271.90Skamil 8281.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8291.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8301.90Skamil 8311.88Skamil validate_status_stopped(status, sig); 8321.88Skamil 8331.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8341.88Skamil SYSCALL_REQUIRE( 8351.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8361.88Skamil 8371.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8381.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8391.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8401.88Skamil info.psi_siginfo.si_errno); 8411.88Skamil 8421.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8431.90Skamil 8441.90Skamil DPRINTF("kp_sigignore=" 8451.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8461.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8471.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8481.90Skamil 8491.90Skamil DPRINTF("kp.p_sigignore=" 8501.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8511.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8521.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8531.90Skamil 8541.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8551.90Skamil 8561.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8571.88Skamil switch (sig) { 8581.88Skamil case SIGTRAP: 8591.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8601.88Skamil break; 8611.88Skamil case SIGSEGV: 8621.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8631.88Skamil break; 8641.88Skamil case SIGILL: 8651.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8661.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8671.88Skamil break; 8681.88Skamil case SIGFPE: 8691.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8701.88Skamil break; 8711.88Skamil case SIGBUS: 8721.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8731.88Skamil break; 8741.88Skamil } 8751.88Skamil 8761.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8771.88Skamil 8781.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8791.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8801.88Skamil 8811.88Skamil validate_status_signaled(status, SIGKILL, 0); 8821.88Skamil 8831.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8841.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8851.88Skamil} 8861.88Skamil 8871.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8881.88SkamilATF_TC(test); \ 8891.88SkamilATF_TC_HEAD(test, tc) \ 8901.88Skamil{ \ 8911.88Skamil atf_tc_set_md_var(tc, "descr", \ 8921.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8931.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8941.88Skamil} \ 8951.88Skamil \ 8961.88SkamilATF_TC_BODY(test, tc) \ 8971.88Skamil{ \ 8981.88Skamil \ 8991.88Skamil traceme_signalignored_crash(sig); \ 9001.88Skamil} 9011.88Skamil 9021.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 9031.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9041.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9051.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9061.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9071.88Skamil 9081.88Skamil/// ---------------------------------------------------------------------------- 9091.88Skamil 9101.88Skamilstatic void 9111.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9121.1Skamil{ 9131.1Skamil const int exitval = 5; 9141.34Skamil const int sigval = SIGSTOP; 9151.1Skamil pid_t child, wpid; 9161.1Skamil struct sigaction sa; 9171.1Skamil#if defined(TWAIT_HAVE_STATUS) 9181.1Skamil int status; 9191.1Skamil#endif 9201.61Skre struct ptrace_siginfo info; 9211.1Skamil 9221.45Skamil memset(&info, 0, sizeof(info)); 9231.45Skamil 9241.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9251.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9261.1Skamil if (child == 0) { 9271.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9281.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9291.1Skamil 9301.34Skamil sa.sa_handler = sah; 9311.1Skamil sa.sa_flags = SA_SIGINFO; 9321.1Skamil sigemptyset(&sa.sa_mask); 9331.1Skamil 9341.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9351.1Skamil 9361.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9371.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9381.1Skamil 9391.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9401.1Skamil 9411.13Schristos DPRINTF("Before exiting of the child process\n"); 9421.1Skamil _exit(exitval); 9431.1Skamil } 9441.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9451.1Skamil 9461.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9481.1Skamil 9491.1Skamil validate_status_stopped(status, sigval); 9501.1Skamil 9511.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9521.61Skre SYSCALL_REQUIRE( 9531.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9541.45Skamil 9551.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9561.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9571.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9581.45Skamil info.psi_siginfo.si_errno); 9591.45Skamil 9601.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9611.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9621.45Skamil 9631.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9641.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9651.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 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_exited(status, exitval); 9711.1Skamil 9721.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9731.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9741.1Skamil} 9751.1Skamil 9761.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9771.61SkreATF_TC(test); \ 9781.61SkreATF_TC_HEAD(test, tc) \ 9791.61Skre{ \ 9801.61Skre atf_tc_set_md_var(tc, "descr", \ 9811.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9821.61Skre "handled correctly and caught by a signal handler"); \ 9831.61Skre} \ 9841.61Skre \ 9851.61Skrestatic int test##_caught = 0; \ 9861.61Skre \ 9871.61Skrestatic void \ 9881.61Skretest##_sighandler(int arg) \ 9891.61Skre{ \ 9901.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9911.61Skre \ 9921.61Skre ++ test##_caught; \ 9931.61Skre} \ 9941.61Skre \ 9951.61SkreATF_TC_BODY(test, tc) \ 9961.61Skre{ \ 9971.61Skre \ 9981.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9991.34Skamil} 10001.34Skamil 10011.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 10021.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 10031.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10041.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10051.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10061.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10071.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10081.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10091.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10101.34Skamil 10111.34Skamil/// ---------------------------------------------------------------------------- 10121.34Skamil 10131.35Skamilstatic void 10141.50Skamiltraceme_sendsignal_masked(int sigsent) 10151.50Skamil{ 10161.50Skamil const int exitval = 5; 10171.50Skamil const int sigval = SIGSTOP; 10181.50Skamil pid_t child, wpid; 10191.50Skamil sigset_t set; 10201.50Skamil#if defined(TWAIT_HAVE_STATUS) 10211.50Skamil int status; 10221.50Skamil#endif 10231.61Skre struct ptrace_siginfo info; 10241.50Skamil 10251.50Skamil memset(&info, 0, sizeof(info)); 10261.50Skamil 10271.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10281.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10291.50Skamil if (child == 0) { 10301.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10311.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10321.50Skamil 10331.50Skamil sigemptyset(&set); 10341.50Skamil sigaddset(&set, sigsent); 10351.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10361.50Skamil 10371.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10381.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10391.50Skamil 10401.50Skamil _exit(exitval); 10411.50Skamil } 10421.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10431.50Skamil 10441.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10451.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10461.50Skamil 10471.50Skamil validate_status_stopped(status, sigval); 10481.50Skamil 10491.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10501.61Skre SYSCALL_REQUIRE( 10511.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10521.50Skamil 10531.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10541.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10551.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10561.50Skamil info.psi_siginfo.si_errno); 10571.50Skamil 10581.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10591.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10601.50Skamil 10611.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10621.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10631.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 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_exited(status, exitval); 10691.50Skamil 10701.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10711.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10721.50Skamil} 10731.50Skamil 10741.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10751.61SkreATF_TC(test); \ 10761.61SkreATF_TC_HEAD(test, tc) \ 10771.61Skre{ \ 10781.61Skre atf_tc_set_md_var(tc, "descr", \ 10791.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10801.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10811.61Skre} \ 10821.61Skre \ 10831.61SkreATF_TC_BODY(test, tc) \ 10841.61Skre{ \ 10851.61Skre \ 10861.61Skre traceme_sendsignal_masked(sig); \ 10871.50Skamil} 10881.50Skamil 10891.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10901.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10911.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10921.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10931.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10941.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10951.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10961.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10971.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10981.50Skamil 10991.50Skamil/// ---------------------------------------------------------------------------- 11001.50Skamil 11011.50Skamilstatic void 11021.50Skamiltraceme_sendsignal_ignored(int sigsent) 11031.50Skamil{ 11041.50Skamil const int exitval = 5; 11051.50Skamil const int sigval = SIGSTOP; 11061.50Skamil pid_t child, wpid; 11071.50Skamil struct sigaction sa; 11081.50Skamil#if defined(TWAIT_HAVE_STATUS) 11091.50Skamil int status; 11101.50Skamil#endif 11111.61Skre struct ptrace_siginfo info; 11121.50Skamil 11131.50Skamil memset(&info, 0, sizeof(info)); 11141.50Skamil 11151.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11161.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11171.50Skamil if (child == 0) { 11181.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11191.61Skre 11201.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11211.50Skamil 11221.50Skamil memset(&sa, 0, sizeof(sa)); 11231.50Skamil sa.sa_handler = SIG_IGN; 11241.50Skamil sigemptyset(&sa.sa_mask); 11251.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11261.50Skamil 11271.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11281.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11291.50Skamil 11301.50Skamil _exit(exitval); 11311.50Skamil } 11321.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11331.50Skamil 11341.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11351.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11361.50Skamil 11371.50Skamil validate_status_stopped(status, sigval); 11381.50Skamil 11391.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11401.61Skre SYSCALL_REQUIRE( 11411.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11421.50Skamil 11431.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11441.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11451.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11461.50Skamil info.psi_siginfo.si_errno); 11471.50Skamil 11481.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11491.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11501.50Skamil 11511.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11521.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11531.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 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_exited(status, exitval); 11591.50Skamil 11601.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11611.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11621.50Skamil} 11631.50Skamil 11641.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11651.61SkreATF_TC(test); \ 11661.61SkreATF_TC_HEAD(test, tc) \ 11671.61Skre{ \ 11681.61Skre atf_tc_set_md_var(tc, "descr", \ 11691.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11701.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11711.61Skre} \ 11721.61Skre \ 11731.61SkreATF_TC_BODY(test, tc) \ 11741.61Skre{ \ 11751.61Skre \ 11761.61Skre traceme_sendsignal_ignored(sig); \ 11771.50Skamil} 11781.50Skamil 11791.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11801.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11811.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11821.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11831.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11841.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11851.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11861.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11871.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11881.50Skamil 11891.50Skamil/// ---------------------------------------------------------------------------- 11901.50Skamil 11911.50Skamilstatic void 11921.50Skamiltraceme_sendsignal_simple(int sigsent) 11931.1Skamil{ 11941.35Skamil const int sigval = SIGSTOP; 11951.35Skamil int exitval = 0; 11961.1Skamil pid_t child, wpid; 11971.1Skamil#if defined(TWAIT_HAVE_STATUS) 11981.1Skamil int status; 11991.85Skamil int expect_core; 12001.85Skamil 12011.85Skamil switch (sigsent) { 12021.85Skamil case SIGABRT: 12031.85Skamil case SIGTRAP: 12041.85Skamil case SIGBUS: 12051.85Skamil case SIGILL: 12061.85Skamil case SIGFPE: 12071.85Skamil case SIGSEGV: 12081.85Skamil expect_core = 1; 12091.85Skamil break; 12101.85Skamil default: 12111.85Skamil expect_core = 0; 12121.85Skamil break; 12131.85Skamil } 12141.1Skamil#endif 12151.61Skre struct ptrace_siginfo info; 12161.1Skamil 12171.45Skamil memset(&info, 0, sizeof(info)); 12181.45Skamil 12191.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12201.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12211.1Skamil if (child == 0) { 12221.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12231.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12241.1Skamil 12251.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12261.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12271.1Skamil 12281.35Skamil switch (sigsent) { 12291.35Skamil case SIGCONT: 12301.48Skamil case SIGSTOP: 12311.35Skamil _exit(exitval); 12321.35Skamil default: 12331.35Skamil /* NOTREACHED */ 12341.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12351.35Skamil } 12361.1Skamil } 12371.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12381.1Skamil 12391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12401.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12411.1Skamil 12421.1Skamil validate_status_stopped(status, sigval); 12431.1Skamil 12441.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12451.61Skre SYSCALL_REQUIRE( 12461.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12471.45Skamil 12481.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12491.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12501.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12511.45Skamil info.psi_siginfo.si_errno); 12521.45Skamil 12531.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12541.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12551.45Skamil 12561.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12571.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12581.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12591.1Skamil 12601.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12611.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12621.1Skamil 12631.35Skamil switch (sigsent) { 12641.48Skamil case SIGSTOP: 12651.48Skamil validate_status_stopped(status, sigsent); 12661.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12671.61Skre "child\n"); 12681.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12691.61Skre sizeof(info)) != -1); 12701.48Skamil 12711.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12721.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12731.61Skre "si_errno=%#x\n", 12741.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12751.61Skre info.psi_siginfo.si_errno); 12761.48Skamil 12771.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12781.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12791.48Skamil 12801.48Skamil DPRINTF("Before resuming the child process where it left off " 12811.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12821.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12831.48Skamil 12841.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12851.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12861.61Skre child); 12871.48Skamil /* FALLTHROUGH */ 12881.35Skamil case SIGCONT: 12891.35Skamil validate_status_exited(status, exitval); 12901.35Skamil break; 12911.35Skamil default: 12921.35Skamil validate_status_signaled(status, sigsent, expect_core); 12931.35Skamil break; 12941.35Skamil } 12951.1Skamil 12961.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12971.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12981.1Skamil} 12991.1Skamil 13001.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 13011.61SkreATF_TC(test); \ 13021.61SkreATF_TC_HEAD(test, tc) \ 13031.61Skre{ \ 13041.61Skre atf_tc_set_md_var(tc, "descr", \ 13051.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13061.61Skre "handled correctly in a child without a signal handler"); \ 13071.61Skre} \ 13081.61Skre \ 13091.61SkreATF_TC_BODY(test, tc) \ 13101.61Skre{ \ 13111.61Skre \ 13121.61Skre traceme_sendsignal_simple(sig); \ 13131.35Skamil} 13141.35Skamil 13151.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13161.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13171.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13181.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13191.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13201.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13211.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13221.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13231.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13241.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13251.35Skamil 13261.35Skamil/// ---------------------------------------------------------------------------- 13271.35Skamil 13281.37SkamilATF_TC(traceme_pid1_parent); 13291.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13301.37Skamil{ 13311.37Skamil atf_tc_set_md_var(tc, "descr", 13321.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13331.37Skamil} 13341.37Skamil 13351.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13361.37Skamil{ 13371.37Skamil struct msg_fds parent_child; 13381.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13391.37Skamil pid_t child1, child2, wpid; 13401.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13411.37Skamil#if defined(TWAIT_HAVE_STATUS) 13421.37Skamil int status; 13431.37Skamil#endif 13441.37Skamil 13451.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13461.37Skamil 13471.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13481.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13491.37Skamil if (child1 == 0) { 13501.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13511.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13521.37Skamil if (child2 != 0) { 13531.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13541.61Skre getpid(), child2); 13551.37Skamil _exit(exitval_child1); 13561.37Skamil } 13571.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13581.37Skamil 13591.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13601.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13611.37Skamil 13621.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13631.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13641.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13651.37Skamil 13661.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13671.37Skamil 13681.37Skamil _exit(exitval_child2); 13691.37Skamil } 13701.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13711.37Skamil 13721.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13731.61Skre TWAIT_REQUIRE_SUCCESS( 13741.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13751.37Skamil 13761.37Skamil validate_status_exited(status, exitval_child1); 13771.37Skamil 13781.37Skamil DPRINTF("Notify that child1 is dead\n"); 13791.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13801.37Skamil 13811.37Skamil DPRINTF("Wait for exiting of child2\n"); 13821.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13831.37Skamil} 13841.37Skamil 13851.37Skamil/// ---------------------------------------------------------------------------- 13861.37Skamil 13871.40Skamilstatic void 13881.40Skamiltraceme_vfork_raise(int sigval) 13891.40Skamil{ 13901.46Skamil const int exitval = 5, exitval_watcher = 10; 13911.46Skamil pid_t child, parent, watcher, wpid; 13921.46Skamil int rv; 13931.40Skamil#if defined(TWAIT_HAVE_STATUS) 13941.40Skamil int status; 13951.85Skamil 13961.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13971.85Skamil volatile int expect_core; 13981.85Skamil 13991.85Skamil switch (sigval) { 14001.85Skamil case SIGABRT: 14011.85Skamil case SIGTRAP: 14021.85Skamil case SIGBUS: 14031.85Skamil case SIGILL: 14041.85Skamil case SIGFPE: 14051.85Skamil case SIGSEGV: 14061.85Skamil expect_core = 1; 14071.85Skamil break; 14081.85Skamil default: 14091.85Skamil expect_core = 0; 14101.85Skamil break; 14111.85Skamil } 14121.40Skamil#endif 14131.40Skamil 14141.46Skamil /* 14151.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14161.46Skamil * the SIGKILL signal to it. 14171.46Skamil * 14181.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14191.46Skamil * simpler to reparent this process to initproc and forget about it. 14201.46Skamil */ 14211.46Skamil if (sigval == SIGSTOP) { 14221.46Skamil parent = getpid(); 14231.46Skamil 14241.46Skamil watcher = fork(); 14251.46Skamil ATF_REQUIRE(watcher != 1); 14261.46Skamil if (watcher == 0) { 14271.46Skamil /* Double fork(2) trick to reparent to initproc */ 14281.46Skamil watcher = fork(); 14291.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14301.46Skamil if (watcher != 0) 14311.46Skamil _exit(exitval_watcher); 14321.46Skamil 14331.46Skamil child = await_stopped_child(parent); 14341.46Skamil 14351.46Skamil errno = 0; 14361.46Skamil rv = kill(child, SIGKILL); 14371.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14381.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14391.46Skamil 14401.46Skamil /* This exit value will be collected by initproc */ 14411.46Skamil _exit(0); 14421.46Skamil } 14431.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14441.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14451.61Skre watcher); 14461.46Skamil 14471.46Skamil validate_status_exited(status, exitval_watcher); 14481.46Skamil 14491.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14501.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14511.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14521.46Skamil } 14531.46Skamil 14541.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14551.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14561.40Skamil if (child == 0) { 14571.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14581.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14591.40Skamil 14601.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14611.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14621.40Skamil 14631.40Skamil switch (sigval) { 14641.46Skamil case SIGSTOP: 14651.40Skamil case SIGKILL: 14661.40Skamil case SIGABRT: 14671.40Skamil case SIGHUP: 14681.85Skamil case SIGTRAP: 14691.85Skamil case SIGBUS: 14701.85Skamil case SIGILL: 14711.85Skamil case SIGFPE: 14721.85Skamil case SIGSEGV: 14731.40Skamil /* NOTREACHED */ 14741.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14751.70Smrg __unreachable(); 14761.40Skamil default: 14771.40Skamil DPRINTF("Before exiting of the child process\n"); 14781.40Skamil _exit(exitval); 14791.40Skamil } 14801.40Skamil } 14811.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14821.40Skamil 14831.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14841.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14851.40Skamil 14861.40Skamil switch (sigval) { 14871.40Skamil case SIGKILL: 14881.40Skamil case SIGABRT: 14891.40Skamil case SIGHUP: 14901.85Skamil case SIGTRAP: 14911.85Skamil case SIGBUS: 14921.85Skamil case SIGILL: 14931.85Skamil case SIGFPE: 14941.85Skamil case SIGSEGV: 14951.40Skamil validate_status_signaled(status, sigval, expect_core); 14961.40Skamil break; 14971.40Skamil case SIGSTOP: 14981.46Skamil validate_status_signaled(status, SIGKILL, 0); 14991.46Skamil break; 15001.40Skamil case SIGCONT: 15011.47Skamil case SIGTSTP: 15021.47Skamil case SIGTTIN: 15031.47Skamil case SIGTTOU: 15041.40Skamil validate_status_exited(status, exitval); 15051.40Skamil break; 15061.40Skamil default: 15071.40Skamil /* NOTREACHED */ 15081.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15091.40Skamil break; 15101.40Skamil } 15111.40Skamil 15121.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15131.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15141.40Skamil} 15151.40Skamil 15161.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15171.61SkreATF_TC(test); \ 15181.61SkreATF_TC_HEAD(test, tc) \ 15191.61Skre{ \ 15201.61Skre atf_tc_set_md_var(tc, "descr", \ 15211.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15221.61Skre "vfork(2)ed child"); \ 15231.61Skre} \ 15241.61Skre \ 15251.61SkreATF_TC_BODY(test, tc) \ 15261.61Skre{ \ 15271.61Skre \ 15281.61Skre traceme_vfork_raise(sig); \ 15291.40Skamil} 15301.40Skamil 15311.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15321.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15331.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15341.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15351.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15361.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15371.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15381.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15391.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15401.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15411.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15421.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15431.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15441.40Skamil 15451.40Skamil/// ---------------------------------------------------------------------------- 15461.40Skamil 15471.52Skamilstatic void 15481.52Skamiltraceme_vfork_crash(int sig) 15491.41Skamil{ 15501.41Skamil pid_t child, wpid; 15511.41Skamil#if defined(TWAIT_HAVE_STATUS) 15521.41Skamil int status; 15531.41Skamil#endif 15541.41Skamil 15551.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15561.71Skamil if (sig == SIGILL) 15571.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15581.71Skamil#endif 15591.71Skamil 15601.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15611.114Skamil atf_tc_skip("FP exceptions are not supported"); 15621.114Skamil 15631.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15641.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15651.41Skamil if (child == 0) { 15661.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15671.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15681.41Skamil 15691.52Skamil DPRINTF("Before executing a trap\n"); 15701.52Skamil switch (sig) { 15711.52Skamil case SIGTRAP: 15721.52Skamil trigger_trap(); 15731.52Skamil break; 15741.52Skamil case SIGSEGV: 15751.52Skamil trigger_segv(); 15761.52Skamil break; 15771.52Skamil case SIGILL: 15781.52Skamil trigger_ill(); 15791.52Skamil break; 15801.52Skamil case SIGFPE: 15811.52Skamil trigger_fpe(); 15821.52Skamil break; 15831.52Skamil case SIGBUS: 15841.52Skamil trigger_bus(); 15851.52Skamil break; 15861.52Skamil default: 15871.52Skamil /* NOTREACHED */ 15881.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15891.52Skamil } 15901.41Skamil 15911.41Skamil /* NOTREACHED */ 15921.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15931.41Skamil } 15941.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15951.41Skamil 15961.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15971.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15981.41Skamil 15991.52Skamil validate_status_signaled(status, sig, 1); 16001.41Skamil 16011.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16021.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16031.41Skamil} 16041.41Skamil 16051.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16061.61SkreATF_TC(test); \ 16071.61SkreATF_TC_HEAD(test, tc) \ 16081.61Skre{ \ 16091.61Skre atf_tc_set_md_var(tc, "descr", \ 16101.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16111.61Skre "vfork(2)ed child"); \ 16121.61Skre} \ 16131.61Skre \ 16141.61SkreATF_TC_BODY(test, tc) \ 16151.61Skre{ \ 16161.61Skre \ 16171.61Skre traceme_vfork_crash(sig); \ 16181.52Skamil} 16191.52Skamil 16201.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16211.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16221.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16231.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16241.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16251.52Skamil 16261.41Skamil/// ---------------------------------------------------------------------------- 16271.41Skamil 16281.92Skamilstatic void 16291.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16301.92Skamil{ 16311.92Skamil pid_t child, wpid; 16321.92Skamil#if defined(TWAIT_HAVE_STATUS) 16331.92Skamil int status; 16341.92Skamil#endif 16351.92Skamil sigset_t intmask; 16361.92Skamil 16371.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16381.92Skamil if (sig == SIGILL) 16391.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16401.92Skamil#endif 16411.92Skamil 16421.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16431.114Skamil atf_tc_skip("FP exceptions are not supported"); 16441.114Skamil 16451.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16461.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16471.92Skamil if (child == 0) { 16481.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16491.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16501.92Skamil 16511.92Skamil sigemptyset(&intmask); 16521.92Skamil sigaddset(&intmask, sig); 16531.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16541.92Skamil 16551.92Skamil DPRINTF("Before executing a trap\n"); 16561.92Skamil switch (sig) { 16571.92Skamil case SIGTRAP: 16581.92Skamil trigger_trap(); 16591.92Skamil break; 16601.92Skamil case SIGSEGV: 16611.92Skamil trigger_segv(); 16621.92Skamil break; 16631.92Skamil case SIGILL: 16641.92Skamil trigger_ill(); 16651.92Skamil break; 16661.92Skamil case SIGFPE: 16671.92Skamil trigger_fpe(); 16681.92Skamil break; 16691.92Skamil case SIGBUS: 16701.92Skamil trigger_bus(); 16711.92Skamil break; 16721.92Skamil default: 16731.92Skamil /* NOTREACHED */ 16741.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16751.92Skamil } 16761.92Skamil 16771.92Skamil /* NOTREACHED */ 16781.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16791.92Skamil } 16801.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16811.92Skamil 16821.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16831.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16841.92Skamil 16851.92Skamil validate_status_signaled(status, sig, 1); 16861.92Skamil 16871.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16881.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16891.92Skamil} 16901.92Skamil 16911.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16921.92SkamilATF_TC(test); \ 16931.92SkamilATF_TC_HEAD(test, tc) \ 16941.92Skamil{ \ 16951.92Skamil atf_tc_set_md_var(tc, "descr", \ 16961.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16971.92Skamil "vfork(2)ed child with a masked signal"); \ 16981.92Skamil} \ 16991.92Skamil \ 17001.92SkamilATF_TC_BODY(test, tc) \ 17011.92Skamil{ \ 17021.92Skamil \ 17031.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17041.92Skamil} 17051.92Skamil 17061.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17071.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17081.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17091.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17101.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17111.92Skamil 17121.92Skamil/// ---------------------------------------------------------------------------- 17131.92Skamil 17141.92Skamilstatic void 17151.92Skamiltraceme_vfork_signalignored_crash(int sig) 17161.92Skamil{ 17171.92Skamil pid_t child, wpid; 17181.92Skamil#if defined(TWAIT_HAVE_STATUS) 17191.92Skamil int status; 17201.92Skamil#endif 17211.92Skamil struct sigaction sa; 17221.92Skamil 17231.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17241.92Skamil if (sig == SIGILL) 17251.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17261.92Skamil#endif 17271.92Skamil 17281.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17291.114Skamil atf_tc_skip("FP exceptions are not supported"); 17301.114Skamil 17311.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17321.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17331.92Skamil if (child == 0) { 17341.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17351.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17361.92Skamil 17371.92Skamil memset(&sa, 0, sizeof(sa)); 17381.92Skamil sa.sa_handler = SIG_IGN; 17391.92Skamil sigemptyset(&sa.sa_mask); 17401.92Skamil 17411.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17421.92Skamil 17431.92Skamil DPRINTF("Before executing a trap\n"); 17441.92Skamil switch (sig) { 17451.92Skamil case SIGTRAP: 17461.92Skamil trigger_trap(); 17471.92Skamil break; 17481.92Skamil case SIGSEGV: 17491.92Skamil trigger_segv(); 17501.92Skamil break; 17511.92Skamil case SIGILL: 17521.92Skamil trigger_ill(); 17531.92Skamil break; 17541.92Skamil case SIGFPE: 17551.92Skamil trigger_fpe(); 17561.92Skamil break; 17571.92Skamil case SIGBUS: 17581.92Skamil trigger_bus(); 17591.92Skamil break; 17601.92Skamil default: 17611.92Skamil /* NOTREACHED */ 17621.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17631.92Skamil } 17641.92Skamil 17651.92Skamil /* NOTREACHED */ 17661.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17671.92Skamil } 17681.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17691.92Skamil 17701.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17711.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17721.92Skamil 17731.92Skamil validate_status_signaled(status, sig, 1); 17741.92Skamil 17751.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17761.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17771.92Skamil} 17781.92Skamil 17791.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17801.92SkamilATF_TC(test); \ 17811.92SkamilATF_TC_HEAD(test, tc) \ 17821.92Skamil{ \ 17831.92Skamil atf_tc_set_md_var(tc, "descr", \ 17841.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17851.92Skamil "vfork(2)ed child with ignored signal"); \ 17861.92Skamil} \ 17871.92Skamil \ 17881.92SkamilATF_TC_BODY(test, tc) \ 17891.92Skamil{ \ 17901.92Skamil \ 17911.92Skamil traceme_vfork_signalignored_crash(sig); \ 17921.92Skamil} 17931.92Skamil 17941.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17951.92Skamil SIGTRAP) 17961.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17971.92Skamil SIGSEGV) 17981.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17991.92Skamil SIGILL) 18001.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 18011.92Skamil SIGFPE) 18021.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 18031.92Skamil SIGBUS) 18041.92Skamil 18051.92Skamil/// ---------------------------------------------------------------------------- 18061.92Skamil 18071.96Skamilstatic void 18081.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18091.43Skamil{ 18101.43Skamil const int sigval = SIGTRAP; 18111.43Skamil pid_t child, wpid; 18121.43Skamil#if defined(TWAIT_HAVE_STATUS) 18131.43Skamil int status; 18141.43Skamil#endif 18151.96Skamil struct sigaction sa; 18161.61Skre struct ptrace_siginfo info; 18171.96Skamil sigset_t intmask; 18181.96Skamil struct kinfo_proc2 kp; 18191.96Skamil size_t len = sizeof(kp); 18201.96Skamil 18211.96Skamil int name[6]; 18221.96Skamil const size_t namelen = __arraycount(name); 18231.96Skamil ki_sigset_t kp_sigmask; 18241.96Skamil ki_sigset_t kp_sigignore; 18251.43Skamil 18261.43Skamil memset(&info, 0, sizeof(info)); 18271.43Skamil 18281.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18291.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18301.43Skamil if (child == 0) { 18311.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18321.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18331.43Skamil 18341.96Skamil if (masked) { 18351.96Skamil sigemptyset(&intmask); 18361.96Skamil sigaddset(&intmask, sigval); 18371.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18381.96Skamil } 18391.96Skamil 18401.96Skamil if (ignored) { 18411.96Skamil memset(&sa, 0, sizeof(sa)); 18421.96Skamil sa.sa_handler = SIG_IGN; 18431.96Skamil sigemptyset(&sa.sa_mask); 18441.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18451.96Skamil } 18461.96Skamil 18471.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18481.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18491.43Skamil 18501.43Skamil /* NOTREACHED */ 18511.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18521.43Skamil } 18531.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18541.43Skamil 18551.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18561.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18571.43Skamil 18581.43Skamil validate_status_stopped(status, sigval); 18591.43Skamil 18601.96Skamil name[0] = CTL_KERN, 18611.96Skamil name[1] = KERN_PROC2, 18621.96Skamil name[2] = KERN_PROC_PID; 18631.96Skamil name[3] = getpid(); 18641.96Skamil name[4] = sizeof(kp); 18651.96Skamil name[5] = 1; 18661.96Skamil 18671.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18681.96Skamil 18691.96Skamil if (masked) 18701.96Skamil kp_sigmask = kp.p_sigmask; 18711.96Skamil 18721.96Skamil if (ignored) 18731.96Skamil kp_sigignore = kp.p_sigignore; 18741.96Skamil 18751.96Skamil name[3] = getpid(); 18761.96Skamil 18771.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18781.96Skamil 18791.96Skamil if (masked) { 18801.96Skamil DPRINTF("kp_sigmask=" 18811.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18821.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18831.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18841.96Skamil 18851.96Skamil DPRINTF("kp.p_sigmask=" 18861.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18871.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18881.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18891.96Skamil 18901.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18911.96Skamil sizeof(kp_sigmask))); 18921.96Skamil } 18931.96Skamil 18941.96Skamil if (ignored) { 18951.96Skamil DPRINTF("kp_sigignore=" 18961.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18971.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18981.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18991.96Skamil 19001.96Skamil DPRINTF("kp.p_sigignore=" 19011.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19021.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 19031.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19041.96Skamil 19051.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19061.96Skamil sizeof(kp_sigignore))); 19071.96Skamil } 19081.96Skamil 19091.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19101.61Skre SYSCALL_REQUIRE( 19111.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19121.43Skamil 19131.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19141.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19151.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19161.43Skamil info.psi_siginfo.si_errno); 19171.43Skamil 19181.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19191.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19201.43Skamil 19211.43Skamil DPRINTF("Before resuming the child process where it left off and " 19221.43Skamil "without signal to be sent\n"); 19231.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19241.43Skamil 19251.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19261.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19271.43Skamil 19281.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19291.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19301.43Skamil} 19311.43Skamil 19321.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19331.96SkamilATF_TC(test); \ 19341.96SkamilATF_TC_HEAD(test, tc) \ 19351.96Skamil{ \ 19361.96Skamil atf_tc_set_md_var(tc, "descr", \ 19371.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19381.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19391.96Skamil masked ? " with ignored signal" : ""); \ 19401.96Skamil} \ 19411.96Skamil \ 19421.96SkamilATF_TC_BODY(test, tc) \ 19431.96Skamil{ \ 19441.96Skamil \ 19451.96Skamil traceme_vfork_exec(masked, ignored); \ 19461.96Skamil} 19471.96Skamil 19481.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19491.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19501.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19511.96Skamil 19521.43Skamil/// ---------------------------------------------------------------------------- 19531.43Skamil 19541.1Skamil#if defined(TWAIT_HAVE_PID) 19551.51Skamilstatic void 19561.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19571.59Skamil{ 19581.94Skamil const int sigval = SIGSTOP; 19591.59Skamil struct msg_fds parent_tracee, parent_tracer; 19601.59Skamil const int exitval = 10; 19611.59Skamil pid_t tracee, tracer, wpid; 19621.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19631.59Skamil#if defined(TWAIT_HAVE_STATUS) 19641.59Skamil int status; 19651.59Skamil#endif 19661.94Skamil struct sigaction sa; 19671.59Skamil struct ptrace_siginfo info; 19681.94Skamil sigset_t intmask; 19691.94Skamil struct kinfo_proc2 kp; 19701.94Skamil size_t len = sizeof(kp); 19711.94Skamil 19721.94Skamil int name[6]; 19731.94Skamil const size_t namelen = __arraycount(name); 19741.94Skamil ki_sigset_t kp_sigmask; 19751.94Skamil ki_sigset_t kp_sigignore; 19761.61Skre 19771.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19781.71Skamil if (sig == SIGILL) 19791.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19801.71Skamil#endif 19811.71Skamil 19821.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19831.114Skamil atf_tc_skip("FP exceptions are not supported"); 19841.114Skamil 19851.59Skamil memset(&info, 0, sizeof(info)); 19861.59Skamil 19871.59Skamil DPRINTF("Spawn tracee\n"); 19881.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19891.59Skamil tracee = atf_utils_fork(); 19901.59Skamil if (tracee == 0) { 19911.59Skamil // Wait for parent to let us crash 19921.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19931.61Skre 19941.94Skamil if (masked) { 19951.94Skamil sigemptyset(&intmask); 19961.94Skamil sigaddset(&intmask, sig); 19971.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19981.94Skamil } 19991.94Skamil 20001.94Skamil if (ignored) { 20011.94Skamil memset(&sa, 0, sizeof(sa)); 20021.94Skamil sa.sa_handler = SIG_IGN; 20031.94Skamil sigemptyset(&sa.sa_mask); 20041.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20051.94Skamil } 20061.94Skamil 20071.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20081.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20091.94Skamil 20101.59Skamil DPRINTF("Before executing a trap\n"); 20111.59Skamil switch (sig) { 20121.59Skamil case SIGTRAP: 20131.59Skamil trigger_trap(); 20141.59Skamil break; 20151.59Skamil case SIGSEGV: 20161.59Skamil trigger_segv(); 20171.59Skamil break; 20181.59Skamil case SIGILL: 20191.59Skamil trigger_ill(); 20201.59Skamil break; 20211.59Skamil case SIGFPE: 20221.59Skamil trigger_fpe(); 20231.59Skamil break; 20241.59Skamil case SIGBUS: 20251.59Skamil trigger_bus(); 20261.59Skamil break; 20271.59Skamil default: 20281.59Skamil /* NOTREACHED */ 20291.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20301.59Skamil } 20311.59Skamil 20321.59Skamil /* NOTREACHED */ 20331.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20341.59Skamil } 20351.59Skamil 20361.59Skamil DPRINTF("Spawn debugger\n"); 20371.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20381.59Skamil tracer = atf_utils_fork(); 20391.59Skamil if (tracer == 0) { 20401.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20411.59Skamil tracer = atf_utils_fork(); 20421.59Skamil if (tracer != 0) 20431.61Skre _exit(exitval); 20441.59Skamil 20451.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20461.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20471.59Skamil 20481.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20491.59Skamil FORKEE_REQUIRE_SUCCESS( 20501.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20511.59Skamil 20521.59Skamil forkee_status_stopped(status, SIGSTOP); 20531.59Skamil 20541.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20551.94Skamil "traced process\n"); 20561.94Skamil SYSCALL_REQUIRE( 20571.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20581.94Skamil 20591.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20601.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20611.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20621.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20631.94Skamil 20641.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20651.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20661.94Skamil 20671.59Skamil /* Resume tracee with PT_CONTINUE */ 20681.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20691.59Skamil 20701.59Skamil /* Inform parent that tracer has attached to tracee */ 20711.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20721.59Skamil 20731.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20741.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20751.59Skamil 20761.59Skamil /* Wait for tracee and assert that it exited */ 20771.59Skamil FORKEE_REQUIRE_SUCCESS( 20781.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20791.59Skamil 20801.94Skamil forkee_status_stopped(status, sigval); 20811.94Skamil 20821.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20831.94Skamil "traced process\n"); 20841.94Skamil SYSCALL_REQUIRE( 20851.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20861.94Skamil 20871.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20881.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20891.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20901.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20911.94Skamil 20921.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20931.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20941.94Skamil 20951.94Skamil name[0] = CTL_KERN, 20961.94Skamil name[1] = KERN_PROC2, 20971.94Skamil name[2] = KERN_PROC_PID; 20981.94Skamil name[3] = tracee; 20991.94Skamil name[4] = sizeof(kp); 21001.94Skamil name[5] = 1; 21011.94Skamil 21021.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21031.94Skamil 21041.94Skamil if (masked) 21051.94Skamil kp_sigmask = kp.p_sigmask; 21061.94Skamil 21071.94Skamil if (ignored) 21081.94Skamil kp_sigignore = kp.p_sigignore; 21091.94Skamil 21101.94Skamil /* Resume tracee with PT_CONTINUE */ 21111.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21121.94Skamil 21131.94Skamil /* Wait for tracee and assert that it exited */ 21141.94Skamil FORKEE_REQUIRE_SUCCESS( 21151.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21161.94Skamil 21171.93Skamil forkee_status_stopped(status, sig); 21181.59Skamil 21191.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21201.61Skre "traced process\n"); 21211.61Skre SYSCALL_REQUIRE( 21221.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21231.59Skamil 21241.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21251.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21261.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21271.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21281.59Skamil 21291.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21301.94Skamil 21311.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21321.94Skamil 21331.94Skamil if (masked) { 21341.94Skamil DPRINTF("kp_sigmask=" 21351.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21361.94Skamil PRIx32 "\n", 21371.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21381.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21391.94Skamil 21401.94Skamil DPRINTF("kp.p_sigmask=" 21411.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21421.94Skamil PRIx32 "\n", 21431.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21441.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21451.94Skamil 21461.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21471.94Skamil sizeof(kp_sigmask))); 21481.94Skamil } 21491.94Skamil 21501.94Skamil if (ignored) { 21511.94Skamil DPRINTF("kp_sigignore=" 21521.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21531.94Skamil PRIx32 "\n", 21541.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21551.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21561.94Skamil 21571.94Skamil DPRINTF("kp.p_sigignore=" 21581.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21591.94Skamil PRIx32 "\n", 21601.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21611.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21621.94Skamil 21631.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21641.94Skamil sizeof(kp_sigignore))); 21651.94Skamil } 21661.94Skamil 21671.59Skamil switch (sig) { 21681.59Skamil case SIGTRAP: 21691.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21701.59Skamil break; 21711.59Skamil case SIGSEGV: 21721.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21731.59Skamil break; 21741.71Skamil case SIGILL: 21751.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21761.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21771.71Skamil break; 21781.59Skamil case SIGFPE: 21791.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21801.59Skamil break; 21811.59Skamil case SIGBUS: 21821.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21831.59Skamil break; 21841.59Skamil } 21851.59Skamil 21861.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21871.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21881.93Skamil FORKEE_REQUIRE_SUCCESS( 21891.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21901.59Skamil 21911.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21921.59Skamil 21931.71Skamil /* Inform parent that tracer is exiting normally */ 21941.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21951.71Skamil 21961.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21971.59Skamil _exit(0 /* collect by initproc */); 21981.59Skamil } 21991.59Skamil 22001.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 22011.59Skamil "calling %s()\n", TWAIT_FNAME); 22021.59Skamil TWAIT_REQUIRE_SUCCESS( 22031.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22041.59Skamil 22051.59Skamil validate_status_exited(status, exitval); 22061.59Skamil 22071.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22081.59Skamil TWAIT_FNAME); 22091.59Skamil TWAIT_REQUIRE_SUCCESS( 22101.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22111.59Skamil 22121.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22131.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22141.59Skamil 22151.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22161.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22171.59Skamil 22181.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22191.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22201.59Skamil 22211.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22221.59Skamil TWAIT_FNAME); 22231.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22241.59Skamil 22251.59Skamil validate_status_signaled(status, SIGKILL, 0); 22261.59Skamil 22271.71Skamil DPRINTF("Await normal exit of tracer\n"); 22281.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22291.71Skamil 22301.59Skamil msg_close(&parent_tracer); 22311.59Skamil msg_close(&parent_tracee); 22321.59Skamil} 22331.59Skamil 22341.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22351.61SkreATF_TC(test); \ 22361.61SkreATF_TC_HEAD(test, tc) \ 22371.61Skre{ \ 22381.61Skre atf_tc_set_md_var(tc, "descr", \ 22391.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22401.94Skamil "the debuggee"); \ 22411.61Skre} \ 22421.61Skre \ 22431.61SkreATF_TC_BODY(test, tc) \ 22441.61Skre{ \ 22451.61Skre \ 22461.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22471.59Skamil} 22481.59Skamil 22491.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22501.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22511.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22521.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22531.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22541.94Skamil 22551.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22561.94SkamilATF_TC(test); \ 22571.94SkamilATF_TC_HEAD(test, tc) \ 22581.94Skamil{ \ 22591.94Skamil atf_tc_set_md_var(tc, "descr", \ 22601.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22611.94Skamil "the debuggee with masked signal"); \ 22621.94Skamil} \ 22631.94Skamil \ 22641.94SkamilATF_TC_BODY(test, tc) \ 22651.94Skamil{ \ 22661.94Skamil \ 22671.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22681.94Skamil} 22691.94Skamil 22701.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22711.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22721.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22731.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22741.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22751.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22761.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22771.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22781.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22791.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22801.94Skamil 22811.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22821.94SkamilATF_TC(test); \ 22831.94SkamilATF_TC_HEAD(test, tc) \ 22841.94Skamil{ \ 22851.94Skamil atf_tc_set_md_var(tc, "descr", \ 22861.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22871.94Skamil "the debuggee with signal ignored"); \ 22881.94Skamil} \ 22891.94Skamil \ 22901.94SkamilATF_TC_BODY(test, tc) \ 22911.94Skamil{ \ 22921.94Skamil \ 22931.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22941.94Skamil} 22951.94Skamil 22961.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22971.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22981.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22991.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 23001.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23011.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 23021.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23031.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23041.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23051.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23061.59Skamil#endif 23071.59Skamil 23081.59Skamil/// ---------------------------------------------------------------------------- 23091.59Skamil 23101.59Skamil#if defined(TWAIT_HAVE_PID) 23111.59Skamilstatic void 23121.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23131.67Skamil bool stopped) 23141.1Skamil{ 23151.51Skamil /* 23161.51Skamil * notimeout - disable timeout in await zombie function 23171.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23181.67Skamil * stopped - attach to a stopped process 23191.51Skamil */ 23201.1Skamil 23211.1Skamil struct msg_fds parent_tracee, parent_tracer; 23221.1Skamil const int exitval_tracee = 5; 23231.1Skamil const int exitval_tracer = 10; 23241.1Skamil pid_t tracee, tracer, wpid; 23251.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23261.1Skamil#if defined(TWAIT_HAVE_STATUS) 23271.1Skamil int status; 23281.1Skamil#endif 23291.1Skamil 23301.67Skamil /* 23311.67Skamil * Only a subset of options are supported. 23321.67Skamil */ 23331.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23341.67Skamil (!notimeout && unrelated && !stopped) || 23351.67Skamil (notimeout && !unrelated && !stopped) || 23361.67Skamil (!notimeout && unrelated && stopped)); 23371.67Skamil 23381.13Schristos DPRINTF("Spawn tracee\n"); 23391.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23401.1Skamil tracee = atf_utils_fork(); 23411.1Skamil if (tracee == 0) { 23421.67Skamil if (stopped) { 23431.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23441.67Skamil raise(SIGSTOP); 23451.67Skamil } 23461.67Skamil 23471.1Skamil // Wait for parent to let us exit 23481.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23491.1Skamil _exit(exitval_tracee); 23501.1Skamil } 23511.1Skamil 23521.13Schristos DPRINTF("Spawn debugger\n"); 23531.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23541.1Skamil tracer = atf_utils_fork(); 23551.1Skamil if (tracer == 0) { 23561.51Skamil if(unrelated) { 23571.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23581.51Skamil tracer = atf_utils_fork(); 23591.51Skamil if (tracer != 0) 23601.51Skamil _exit(exitval_tracer); 23611.51Skamil } 23621.51Skamil 23631.67Skamil if (stopped) { 23641.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23651.67Skamil await_stopped(tracee); 23661.67Skamil } 23671.67Skamil 23681.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23691.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23701.1Skamil 23711.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23721.1Skamil FORKEE_REQUIRE_SUCCESS( 23731.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23741.1Skamil 23751.1Skamil forkee_status_stopped(status, SIGSTOP); 23761.1Skamil 23771.1Skamil /* Resume tracee with PT_CONTINUE */ 23781.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23791.1Skamil 23801.1Skamil /* Inform parent that tracer has attached to tracee */ 23811.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23821.1Skamil 23831.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23841.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23851.1Skamil 23861.1Skamil /* Wait for tracee and assert that it exited */ 23871.1Skamil FORKEE_REQUIRE_SUCCESS( 23881.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23891.1Skamil 23901.1Skamil forkee_status_exited(status, exitval_tracee); 23911.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23921.1Skamil 23931.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23941.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23951.51Skamil } 23961.51Skamil 23971.51Skamil if (unrelated) { 23981.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23991.51Skamil "calling %s()\n", TWAIT_FNAME); 24001.51Skamil TWAIT_REQUIRE_SUCCESS( 24011.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 24021.51Skamil 24031.51Skamil validate_status_exited(status, exitval_tracer); 24041.51Skamil 24051.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24061.51Skamil TWAIT_FNAME); 24071.51Skamil TWAIT_REQUIRE_SUCCESS( 24081.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24091.1Skamil } 24101.1Skamil 24111.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24121.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24131.1Skamil 24141.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24151.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24161.1Skamil 24171.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24181.51Skamil if (notimeout) 24191.26Skamil await_zombie_raw(tracee, 0); 24201.26Skamil else 24211.26Skamil await_zombie(tracee); 24221.1Skamil 24231.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24241.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24251.1Skamil TWAIT_FNAME); 24261.1Skamil TWAIT_REQUIRE_SUCCESS( 24271.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24281.1Skamil 24291.51Skamil if (unrelated) { 24301.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24311.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24321.51Skamil } else { 24331.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24341.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24351.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24361.59Skamil "%s()\n", TWAIT_FNAME); 24371.51Skamil 24381.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24391.59Skamil "tracee\n"); 24401.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24411.51Skamil tracer); 24421.1Skamil 24431.51Skamil validate_status_exited(status, exitval_tracer); 24441.51Skamil } 24451.1Skamil 24461.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24471.1Skamil TWAIT_FNAME); 24481.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24491.1Skamil 24501.1Skamil validate_status_exited(status, exitval_tracee); 24511.1Skamil 24521.1Skamil msg_close(&parent_tracer); 24531.1Skamil msg_close(&parent_tracee); 24541.1Skamil} 24551.26Skamil 24561.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24571.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24581.51Skamil{ 24591.51Skamil atf_tc_set_md_var(tc, "descr", 24601.51Skamil "Assert that tracer sees process termination before the parent"); 24611.51Skamil} 24621.51Skamil 24631.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24641.26Skamil{ 24651.26Skamil 24661.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24671.26Skamil} 24681.26Skamil 24691.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24701.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24711.1Skamil{ 24721.164Skamil atf_tc_set_md_var(tc, "timeout", "15"); 24731.1Skamil atf_tc_set_md_var(tc, "descr", 24741.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24751.51Skamil "process and no other error is reported"); 24761.1Skamil} 24771.1Skamil 24781.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24791.1Skamil{ 24801.51Skamil time_t start, end; 24811.51Skamil double diff; 24821.51Skamil unsigned long N = 0; 24831.1Skamil 24841.51Skamil /* 24851.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24861.51Skamil * This test body isn't specific to this race, however it's just good 24871.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24881.51Skamil */ 24891.1Skamil 24901.51Skamil start = time(NULL); 24911.51Skamil while (true) { 24921.51Skamil DPRINTF("Step: %lu\n", N); 24931.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24941.67Skamil false); 24951.51Skamil end = time(NULL); 24961.51Skamil diff = difftime(end, start); 24971.51Skamil if (diff >= 5.0) 24981.51Skamil break; 24991.51Skamil ++N; 25001.1Skamil } 25011.51Skamil DPRINTF("Iterations: %lu\n", N); 25021.51Skamil} 25031.1Skamil 25041.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25051.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25061.51Skamil{ 25071.51Skamil atf_tc_set_md_var(tc, "descr", 25081.51Skamil "Assert that tracer sees process termination before the parent"); 25091.51Skamil} 25101.1Skamil 25111.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25121.51Skamil{ 25131.1Skamil 25141.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25151.67Skamil} 25161.67Skamil 25171.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25181.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25191.67Skamil{ 25201.67Skamil atf_tc_set_md_var(tc, "descr", 25211.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25221.67Skamil} 25231.67Skamil 25241.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25251.67Skamil{ 25261.67Skamil 25271.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25281.1Skamil} 25291.1Skamil#endif 25301.1Skamil 25311.51Skamil/// ---------------------------------------------------------------------------- 25321.51Skamil 25331.66Skamilstatic void 25341.66Skamilparent_attach_to_its_child(bool stopped) 25351.1Skamil{ 25361.1Skamil struct msg_fds parent_tracee; 25371.1Skamil const int exitval_tracee = 5; 25381.1Skamil pid_t tracee, wpid; 25391.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25401.1Skamil#if defined(TWAIT_HAVE_STATUS) 25411.1Skamil int status; 25421.1Skamil#endif 25431.1Skamil 25441.13Schristos DPRINTF("Spawn tracee\n"); 25451.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25461.1Skamil tracee = atf_utils_fork(); 25471.1Skamil if (tracee == 0) { 25481.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25491.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25501.1Skamil 25511.66Skamil if (stopped) { 25521.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25531.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25541.66Skamil } 25551.66Skamil 25561.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25571.1Skamil /* Wait for message from the parent */ 25581.1Skamil _exit(exitval_tracee); 25591.1Skamil } 25601.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25611.57Skamil 25621.66Skamil if (stopped) { 25631.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25641.66Skamil await_stopped(tracee); 25651.66Skamil } 25661.66Skamil 25671.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25681.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25691.1Skamil 25701.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25711.1Skamil TWAIT_FNAME); 25721.1Skamil TWAIT_REQUIRE_SUCCESS( 25731.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25741.1Skamil 25751.1Skamil validate_status_stopped(status, SIGSTOP); 25761.1Skamil 25771.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25781.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25791.1Skamil 25801.13Schristos DPRINTF("Let the tracee exit now\n"); 25811.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25821.1Skamil 25831.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25841.1Skamil TWAIT_REQUIRE_SUCCESS( 25851.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25861.1Skamil 25871.1Skamil validate_status_exited(status, exitval_tracee); 25881.1Skamil 25891.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25901.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25911.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25921.1Skamil 25931.1Skamil msg_close(&parent_tracee); 25941.1Skamil} 25951.1Skamil 25961.66SkamilATF_TC(parent_attach_to_its_child); 25971.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25981.66Skamil{ 25991.66Skamil atf_tc_set_md_var(tc, "descr", 26001.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 26011.66Skamil} 26021.66Skamil 26031.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26041.66Skamil{ 26051.66Skamil 26061.66Skamil parent_attach_to_its_child(false); 26071.66Skamil} 26081.66Skamil 26091.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26101.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26111.66Skamil{ 26121.66Skamil atf_tc_set_md_var(tc, "descr", 26131.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26141.66Skamil} 26151.66Skamil 26161.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26171.66Skamil{ 26181.66Skamil 26191.66Skamil parent_attach_to_its_child(true); 26201.66Skamil} 26211.66Skamil 26221.51Skamil/// ---------------------------------------------------------------------------- 26231.51Skamil 26241.65Skamilstatic void 26251.65Skamilchild_attach_to_its_parent(bool stopped) 26261.1Skamil{ 26271.1Skamil struct msg_fds parent_tracee; 26281.1Skamil const int exitval_tracer = 5; 26291.1Skamil pid_t tracer, wpid; 26301.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26311.1Skamil#if defined(TWAIT_HAVE_STATUS) 26321.1Skamil int status; 26331.1Skamil#endif 26341.1Skamil 26351.13Schristos DPRINTF("Spawn tracer\n"); 26361.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26371.1Skamil tracer = atf_utils_fork(); 26381.1Skamil if (tracer == 0) { 26391.1Skamil /* Wait for message from the parent */ 26401.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26411.1Skamil 26421.65Skamil if (stopped) { 26431.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26441.65Skamil getppid()); 26451.65Skamil await_stopped(getppid()); 26461.65Skamil } 26471.65Skamil 26481.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26491.1Skamil getppid()); 26501.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26511.1Skamil 26521.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26531.1Skamil TWAIT_FNAME); 26541.1Skamil FORKEE_REQUIRE_SUCCESS( 26551.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26561.1Skamil 26571.1Skamil forkee_status_stopped(status, SIGSTOP); 26581.1Skamil 26591.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26601.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26611.1Skamil != -1); 26621.1Skamil 26631.1Skamil /* Tell parent we are ready */ 26641.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26651.1Skamil 26661.1Skamil _exit(exitval_tracer); 26671.1Skamil } 26681.1Skamil 26691.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26701.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26711.65Skamil 26721.65Skamil if (stopped) { 26731.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26741.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26751.65Skamil } 26761.65Skamil 26771.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26781.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26791.1Skamil 26801.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26811.1Skamil TWAIT_REQUIRE_SUCCESS( 26821.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26831.1Skamil 26841.1Skamil validate_status_exited(status, exitval_tracer); 26851.1Skamil 26861.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26871.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26881.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26891.1Skamil 26901.1Skamil msg_close(&parent_tracee); 26911.1Skamil} 26921.1Skamil 26931.65SkamilATF_TC(child_attach_to_its_parent); 26941.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26951.65Skamil{ 26961.65Skamil atf_tc_set_md_var(tc, "descr", 26971.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26981.65Skamil} 26991.65Skamil 27001.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 27011.65Skamil{ 27021.65Skamil 27031.65Skamil child_attach_to_its_parent(false); 27041.65Skamil} 27051.65Skamil 27061.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27071.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27081.65Skamil{ 27091.65Skamil atf_tc_set_md_var(tc, "descr", 27101.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27111.65Skamil} 27121.65Skamil 27131.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27141.65Skamil{ 27151.65Skamil /* 27161.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27171.65Skamil * this causes a pipe (established from atf-run) to be broken. 27181.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27191.65Skamil * 27201.65Skamil * As a workaround spawn this test as a subprocess. 27211.65Skamil */ 27221.65Skamil 27231.65Skamil const int exitval = 15; 27241.65Skamil pid_t child, wpid; 27251.65Skamil#if defined(TWAIT_HAVE_STATUS) 27261.65Skamil int status; 27271.65Skamil#endif 27281.65Skamil 27291.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27301.65Skamil if (child == 0) { 27311.65Skamil child_attach_to_its_parent(true); 27321.65Skamil _exit(exitval); 27331.65Skamil } else { 27341.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27351.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27361.65Skamil 27371.65Skamil validate_status_exited(status, exitval); 27381.65Skamil 27391.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27401.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27411.65Skamil } 27421.65Skamil} 27431.65Skamil 27441.51Skamil/// ---------------------------------------------------------------------------- 27451.51Skamil 27461.1Skamil#if defined(TWAIT_HAVE_PID) 27471.1Skamil 27481.51Skamilenum tracee_sees_its_original_parent_type { 27491.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27501.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27511.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27521.51Skamil}; 27531.51Skamil 27541.51Skamilstatic void 27551.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27561.1Skamil{ 27571.1Skamil struct msg_fds parent_tracer, parent_tracee; 27581.1Skamil const int exitval_tracee = 5; 27591.1Skamil const int exitval_tracer = 10; 27601.1Skamil pid_t parent, tracee, tracer, wpid; 27611.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27621.1Skamil#if defined(TWAIT_HAVE_STATUS) 27631.1Skamil int status; 27641.1Skamil#endif 27651.51Skamil /* sysctl(3) - kinfo_proc2 */ 27661.51Skamil int name[CTL_MAXNAME]; 27671.51Skamil struct kinfo_proc2 kp; 27681.51Skamil size_t len = sizeof(kp); 27691.51Skamil unsigned int namelen; 27701.51Skamil 27711.51Skamil /* procfs - status */ 27721.51Skamil FILE *fp; 27731.51Skamil struct stat st; 27741.51Skamil const char *fname = "/proc/curproc/status"; 27751.51Skamil char s_executable[MAXPATHLEN]; 27761.51Skamil int s_pid, s_ppid; 27771.51Skamil int rv; 27781.51Skamil 27791.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27801.61Skre SYSCALL_REQUIRE( 27811.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27821.61Skre if (rv != 0) 27831.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27841.51Skamil } 27851.1Skamil 27861.13Schristos DPRINTF("Spawn tracee\n"); 27871.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27881.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27891.1Skamil tracee = atf_utils_fork(); 27901.1Skamil if (tracee == 0) { 27911.1Skamil parent = getppid(); 27921.1Skamil 27931.1Skamil /* Emit message to the parent */ 27941.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27951.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27961.1Skamil 27971.51Skamil switch (type) { 27981.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27991.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 28001.51Skamil break; 28011.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 28021.51Skamil namelen = 0; 28031.51Skamil name[namelen++] = CTL_KERN; 28041.51Skamil name[namelen++] = KERN_PROC2; 28051.51Skamil name[namelen++] = KERN_PROC_PID; 28061.51Skamil name[namelen++] = getpid(); 28071.51Skamil name[namelen++] = len; 28081.51Skamil name[namelen++] = 1; 28091.51Skamil 28101.61Skre FORKEE_ASSERT_EQ( 28111.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28121.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28131.51Skamil break; 28141.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28151.51Skamil /* 28161.51Skamil * Format: 28171.51Skamil * EXECUTABLE PID PPID ... 28181.51Skamil */ 28191.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28201.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28211.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28221.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28231.51Skamil break; 28241.51Skamil } 28251.1Skamil 28261.1Skamil _exit(exitval_tracee); 28271.1Skamil } 28281.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28291.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28301.1Skamil 28311.13Schristos DPRINTF("Spawn debugger\n"); 28321.1Skamil tracer = atf_utils_fork(); 28331.1Skamil if (tracer == 0) { 28341.1Skamil /* No IPC to communicate with the child */ 28351.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28361.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28371.1Skamil 28381.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28391.1Skamil FORKEE_REQUIRE_SUCCESS( 28401.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28411.1Skamil 28421.1Skamil forkee_status_stopped(status, SIGSTOP); 28431.1Skamil 28441.1Skamil /* Resume tracee with PT_CONTINUE */ 28451.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28461.1Skamil 28471.1Skamil /* Inform parent that tracer has attached to tracee */ 28481.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28491.1Skamil 28501.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28511.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28521.1Skamil 28531.1Skamil /* Wait for tracee and assert that it exited */ 28541.1Skamil FORKEE_REQUIRE_SUCCESS( 28551.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28561.1Skamil 28571.1Skamil forkee_status_exited(status, exitval_tracee); 28581.1Skamil 28591.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28601.1Skamil _exit(exitval_tracer); 28611.1Skamil } 28621.1Skamil 28631.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28641.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28651.1Skamil 28661.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28671.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28681.1Skamil 28691.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28701.1Skamil await_zombie(tracee); 28711.1Skamil 28721.13Schristos DPRINTF("Assert that there is no status about tracee - " 28731.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28741.1Skamil TWAIT_REQUIRE_SUCCESS( 28751.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28761.1Skamil 28771.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28781.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28791.1Skamil 28801.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28821.1Skamil tracer); 28831.1Skamil 28841.1Skamil validate_status_exited(status, exitval_tracer); 28851.1Skamil 28861.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28871.1Skamil TWAIT_FNAME); 28881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28891.1Skamil tracee); 28901.1Skamil 28911.1Skamil validate_status_exited(status, exitval_tracee); 28921.1Skamil 28931.1Skamil msg_close(&parent_tracer); 28941.1Skamil msg_close(&parent_tracee); 28951.1Skamil} 28961.1Skamil 28971.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28981.61SkreATF_TC(test); \ 28991.61SkreATF_TC_HEAD(test, tc) \ 29001.61Skre{ \ 29011.61Skre atf_tc_set_md_var(tc, "descr", \ 29021.61Skre "Assert that tracee sees its original parent when being traced " \ 29031.61Skre "(check " descr ")"); \ 29041.61Skre} \ 29051.61Skre \ 29061.61SkreATF_TC_BODY(test, tc) \ 29071.61Skre{ \ 29081.61Skre \ 29091.61Skre tracee_sees_its_original_parent(type); \ 29101.1Skamil} 29111.1Skamil 29121.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29131.51Skamil tracee_sees_its_original_parent_getppid, 29141.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29151.51Skamil "getppid(2)"); 29161.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29171.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29181.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29191.51Skamil "sysctl(3) and kinfo_proc2"); 29201.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29211.51Skamil tracee_sees_its_original_parent_procfs_status, 29221.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29231.51Skamil "the status file in procfs"); 29241.1Skamil#endif 29251.1Skamil 29261.51Skamil/// ---------------------------------------------------------------------------- 29271.1Skamil 29281.53Skamilstatic void 29291.53Skamileventmask_preserved(int event) 29301.1Skamil{ 29311.1Skamil const int exitval = 5; 29321.1Skamil const int sigval = SIGSTOP; 29331.1Skamil pid_t child, wpid; 29341.1Skamil#if defined(TWAIT_HAVE_STATUS) 29351.1Skamil int status; 29361.1Skamil#endif 29371.1Skamil ptrace_event_t set_event, get_event; 29381.1Skamil const int len = sizeof(ptrace_event_t); 29391.1Skamil 29401.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29411.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29421.1Skamil if (child == 0) { 29431.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29441.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29451.1Skamil 29461.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29471.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29481.1Skamil 29491.13Schristos DPRINTF("Before exiting of the child process\n"); 29501.1Skamil _exit(exitval); 29511.1Skamil } 29521.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29531.1Skamil 29541.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29551.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29561.1Skamil 29571.1Skamil validate_status_stopped(status, sigval); 29581.1Skamil 29591.53Skamil set_event.pe_set_event = event; 29601.61Skre SYSCALL_REQUIRE( 29611.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29621.61Skre SYSCALL_REQUIRE( 29631.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29641.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29651.125Skamil get_event.pe_set_event); 29661.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29671.1Skamil 29681.13Schristos DPRINTF("Before resuming the child process where it left off and " 29691.1Skamil "without signal to be sent\n"); 29701.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29711.1Skamil 29721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29741.1Skamil 29751.1Skamil validate_status_exited(status, exitval); 29761.1Skamil 29771.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29781.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29791.1Skamil} 29801.1Skamil 29811.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29821.61SkreATF_TC(test); \ 29831.61SkreATF_TC_HEAD(test, tc) \ 29841.61Skre{ \ 29851.61Skre atf_tc_set_md_var(tc, "descr", \ 29861.61Skre "Verify that eventmask " #event " is preserved"); \ 29871.61Skre} \ 29881.61Skre \ 29891.61SkreATF_TC_BODY(test, tc) \ 29901.61Skre{ \ 29911.61Skre \ 29921.61Skre eventmask_preserved(event); \ 29931.1Skamil} 29941.1Skamil 29951.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29961.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29971.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29981.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29991.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 30001.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 30011.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 30021.1Skamil 30031.53Skamil/// ---------------------------------------------------------------------------- 30041.1Skamil 30051.28Skamilstatic void 30061.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 30071.105Skamil bool trackvforkdone) 30081.1Skamil{ 30091.1Skamil const int exitval = 5; 30101.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30111.1Skamil const int sigval = SIGSTOP; 30121.31Skamil pid_t child, child2 = 0, wpid; 30131.1Skamil#if defined(TWAIT_HAVE_STATUS) 30141.1Skamil int status; 30151.1Skamil#endif 30161.1Skamil ptrace_state_t state; 30171.1Skamil const int slen = sizeof(state); 30181.1Skamil ptrace_event_t event; 30191.1Skamil const int elen = sizeof(event); 30201.1Skamil 30211.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30221.124Skamil 30231.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30241.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30251.1Skamil if (child == 0) { 30261.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30271.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30281.1Skamil 30291.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30301.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30311.1Skamil 30321.125Skamil if (strcmp(fn, "spawn") == 0) { 30331.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30341.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30351.125Skamil } else { 30361.125Skamil if (strcmp(fn, "fork") == 0) { 30371.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30381.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30391.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30401.125Skamil } 30411.1Skamil 30421.124Skamil if (child2 == 0) 30431.124Skamil _exit(exitval2); 30441.124Skamil } 30451.1Skamil FORKEE_REQUIRE_SUCCESS 30461.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30471.1Skamil 30481.1Skamil forkee_status_exited(status, exitval2); 30491.1Skamil 30501.13Schristos DPRINTF("Before exiting of the child process\n"); 30511.1Skamil _exit(exitval); 30521.1Skamil } 30531.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30541.1Skamil 30551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30571.1Skamil 30581.1Skamil validate_status_stopped(status, sigval); 30591.1Skamil 30601.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30611.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30621.61Skre trackfork ? "|PTRACE_FORK" : "", 30631.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30641.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30651.30Skamil event.pe_set_event = 0; 30661.125Skamil if (trackspawn) 30671.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30681.30Skamil if (trackfork) 30691.30Skamil event.pe_set_event |= PTRACE_FORK; 30701.30Skamil if (trackvfork) 30711.30Skamil event.pe_set_event |= PTRACE_VFORK; 30721.30Skamil if (trackvforkdone) 30731.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30741.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30751.1Skamil 30761.13Schristos DPRINTF("Before resuming the child process where it left off and " 30771.1Skamil "without signal to be sent\n"); 30781.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30791.1Skamil 30801.29Skamil#if defined(TWAIT_HAVE_PID) 30811.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 30821.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 30831.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 30841.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30851.61Skre child); 30861.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30871.61Skre child); 30881.1Skamil 30891.29Skamil validate_status_stopped(status, SIGTRAP); 30901.1Skamil 30911.61Skre SYSCALL_REQUIRE( 30921.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30931.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 30941.125Skamil ATF_REQUIRE_EQ( 30951.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 30961.125Skamil PTRACE_POSIX_SPAWN); 30971.125Skamil } 30981.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 30991.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31001.30Skamil PTRACE_FORK); 31011.30Skamil } 31021.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31031.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31041.30Skamil PTRACE_VFORK); 31051.30Skamil } 31061.29Skamil 31071.29Skamil child2 = state.pe_other_pid; 31081.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31091.29Skamil 31101.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31111.61Skre "%d\n", TWAIT_FNAME, child2, child); 31121.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31131.29Skamil child2); 31141.1Skamil 31151.29Skamil validate_status_stopped(status, SIGTRAP); 31161.1Skamil 31171.61Skre SYSCALL_REQUIRE( 31181.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31191.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31201.125Skamil ATF_REQUIRE_EQ( 31211.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31221.125Skamil PTRACE_POSIX_SPAWN); 31231.125Skamil } 31241.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31251.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31261.30Skamil PTRACE_FORK); 31271.30Skamil } 31281.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31291.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31301.30Skamil PTRACE_VFORK); 31311.30Skamil } 31321.30Skamil 31331.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31341.29Skamil 31351.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31361.29Skamil "and without signal to be sent\n"); 31371.61Skre SYSCALL_REQUIRE( 31381.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31391.29Skamil 31401.29Skamil DPRINTF("Before resuming the child process where it left off " 31411.61Skre "and without signal to be sent\n"); 31421.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31431.30Skamil } 31441.30Skamil#endif 31451.30Skamil 31461.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31471.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31481.61Skre child); 31491.61Skre TWAIT_REQUIRE_SUCCESS( 31501.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31511.30Skamil 31521.30Skamil validate_status_stopped(status, SIGTRAP); 31531.30Skamil 31541.61Skre SYSCALL_REQUIRE( 31551.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31561.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31571.30Skamil 31581.30Skamil child2 = state.pe_other_pid; 31591.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31601.61Skre child2); 31611.30Skamil 31621.30Skamil DPRINTF("Before resuming the child process where it left off " 31631.61Skre "and without signal to be sent\n"); 31641.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31651.30Skamil } 31661.29Skamil 31671.30Skamil#if defined(TWAIT_HAVE_PID) 31681.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31691.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31701.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31711.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31721.61Skre "\n", TWAIT_FNAME); 31731.61Skre TWAIT_REQUIRE_SUCCESS( 31741.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31751.29Skamil 31761.29Skamil validate_status_exited(status, exitval2); 31771.29Skamil 31781.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31791.61Skre "process\n", TWAIT_FNAME); 31801.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31811.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31821.29Skamil } 31831.29Skamil#endif 31841.1Skamil 31851.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31861.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31881.1Skamil 31891.1Skamil validate_status_stopped(status, SIGCHLD); 31901.1Skamil 31911.13Schristos DPRINTF("Before resuming the child process where it left off and " 31921.1Skamil "without signal to be sent\n"); 31931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31941.1Skamil 31951.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31961.1Skamil TWAIT_FNAME); 31971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31981.1Skamil 31991.1Skamil validate_status_exited(status, exitval); 32001.1Skamil 32011.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 32021.1Skamil TWAIT_FNAME); 32031.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32041.1Skamil} 32051.28Skamil 32061.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 32071.61SkreATF_TC(name); \ 32081.61SkreATF_TC_HEAD(name, tc) \ 32091.61Skre{ \ 32101.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32111.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32121.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32131.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32141.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32151.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32161.61Skre} \ 32171.61Skre \ 32181.61SkreATF_TC_BODY(name, tc) \ 32191.61Skre{ \ 32201.61Skre \ 32211.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32221.32Skamil} 32231.32Skamil 32241.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32251.31Skamil#if defined(TWAIT_HAVE_PID) 32261.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32271.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32281.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32291.31Skamil#endif 32301.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32311.31Skamil#if defined(TWAIT_HAVE_PID) 32321.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32331.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32341.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32351.125Skamil#endif 32361.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32371.125Skamil#if defined(TWAIT_HAVE_PID) 32381.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32391.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32401.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32411.125Skamil#endif 32421.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32431.125Skamil#if defined(TWAIT_HAVE_PID) 32441.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32451.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32461.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32471.31Skamil#endif 32481.1Skamil 32491.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32501.31Skamil#if defined(TWAIT_HAVE_PID) 32511.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32521.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32531.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32541.31Skamil#endif 32551.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32561.31Skamil#if defined(TWAIT_HAVE_PID) 32571.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32581.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32591.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32601.31Skamil#endif 32611.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32621.125Skamil#if defined(TWAIT_HAVE_PID) 32631.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32641.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32651.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32661.110Skamil#endif 32671.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32681.124Skamil#if defined(TWAIT_HAVE_PID) 32691.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32701.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32711.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32721.124Skamil#endif 32731.125Skamil 32741.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32751.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32761.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32771.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32781.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32791.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32801.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32811.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 32821.124Skamil#if defined(TWAIT_HAVE_PID) 32831.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 32841.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 32851.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 32861.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 32871.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 32881.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 32891.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 32901.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 32911.124Skamil#endif 32921.124Skamil 32931.54Skamil/// ---------------------------------------------------------------------------- 32941.31Skamil 32951.116Skamil#if defined(TWAIT_HAVE_PID) 32961.116Skamilstatic void 32971.149Skamilunrelated_tracer_fork_body(const char *fn, bool trackspawn, bool trackfork, 32981.149Skamil bool trackvfork, bool trackvforkdone) 32991.149Skamil{ 33001.149Skamil const int sigval = SIGSTOP; 33011.149Skamil struct msg_fds parent_tracee, parent_tracer; 33021.149Skamil const int exitval = 10; 33031.149Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 33041.149Skamil pid_t tracee, tracer, wpid; 33051.149Skamil pid_t tracee2 = 0; 33061.149Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 33071.149Skamil#if defined(TWAIT_HAVE_STATUS) 33081.149Skamil int status; 33091.149Skamil#endif 33101.149Skamil 33111.149Skamil struct ptrace_siginfo info; 33121.149Skamil ptrace_state_t state; 33131.149Skamil const int slen = sizeof(state); 33141.149Skamil ptrace_event_t event; 33151.149Skamil const int elen = sizeof(event); 33161.149Skamil 33171.149Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33181.149Skamil 33191.149Skamil DPRINTF("Spawn tracee\n"); 33201.149Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 33211.149Skamil tracee = atf_utils_fork(); 33221.149Skamil if (tracee == 0) { 33231.149Skamil // Wait for parent to let us crash 33241.149Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 33251.149Skamil 33261.149Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33271.149Skamil FORKEE_ASSERT(raise(sigval) == 0); 33281.149Skamil 33291.149Skamil if (strcmp(fn, "spawn") == 0) { 33301.149Skamil FORKEE_ASSERT_EQ(posix_spawn(&tracee2, 33311.149Skamil arg[0], NULL, NULL, arg, NULL), 0); 33321.149Skamil } else { 33331.149Skamil if (strcmp(fn, "fork") == 0) { 33341.149Skamil FORKEE_ASSERT((tracee2 = fork()) != -1); 33351.149Skamil } else if (strcmp(fn, "vfork") == 0) { 33361.149Skamil FORKEE_ASSERT((tracee2 = vfork()) != -1); 33371.149Skamil } 33381.149Skamil 33391.149Skamil if (tracee2 == 0) 33401.149Skamil _exit(exitval2); 33411.149Skamil } 33421.149Skamil FORKEE_REQUIRE_SUCCESS 33431.149Skamil (wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 33441.149Skamil 33451.149Skamil forkee_status_exited(status, exitval2); 33461.149Skamil 33471.149Skamil DPRINTF("Before exiting of the child process\n"); 33481.149Skamil _exit(exitval); 33491.149Skamil } 33501.149Skamil 33511.149Skamil DPRINTF("Spawn debugger\n"); 33521.149Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 33531.149Skamil tracer = atf_utils_fork(); 33541.149Skamil if (tracer == 0) { 33551.149Skamil /* Fork again and drop parent to reattach to PID 1 */ 33561.149Skamil tracer = atf_utils_fork(); 33571.149Skamil if (tracer != 0) 33581.149Skamil _exit(exitval); 33591.149Skamil 33601.149Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 33611.149Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 33621.149Skamil 33631.149Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 33641.149Skamil FORKEE_REQUIRE_SUCCESS( 33651.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 33661.149Skamil 33671.149Skamil forkee_status_stopped(status, SIGSTOP); 33681.149Skamil 33691.149Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 33701.149Skamil "traced process\n"); 33711.149Skamil SYSCALL_REQUIRE( 33721.149Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 33731.149Skamil 33741.149Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 33751.149Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 33761.149Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 33771.149Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 33781.149Skamil 33791.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 33801.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 33811.149Skamil 33821.149Skamil /* Resume tracee with PT_CONTINUE */ 33831.149Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 33841.149Skamil 33851.149Skamil /* Inform parent that tracer has attached to tracee */ 33861.149Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 33871.149Skamil 33881.149Skamil /* Wait for parent to tell use that tracee should have exited */ 33891.149Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 33901.149Skamil 33911.149Skamil /* Wait for tracee and assert that it exited */ 33921.149Skamil FORKEE_REQUIRE_SUCCESS( 33931.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 33941.149Skamil 33951.149Skamil forkee_status_stopped(status, sigval); 33961.149Skamil 33971.149Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 33981.149Skamil "traced process\n"); 33991.149Skamil SYSCALL_REQUIRE( 34001.149Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 34011.149Skamil 34021.149Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 34031.149Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 34041.149Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 34051.149Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 34061.149Skamil 34071.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 34081.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 34091.149Skamil 34101.149Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 34111.149Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 34121.149Skamil trackfork ? "|PTRACE_FORK" : "", 34131.149Skamil trackvfork ? "|PTRACE_VFORK" : "", 34141.149Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", tracee); 34151.149Skamil event.pe_set_event = 0; 34161.149Skamil if (trackspawn) 34171.149Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 34181.149Skamil if (trackfork) 34191.149Skamil event.pe_set_event |= PTRACE_FORK; 34201.149Skamil if (trackvfork) 34211.149Skamil event.pe_set_event |= PTRACE_VFORK; 34221.149Skamil if (trackvforkdone) 34231.149Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 34241.149Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, tracee, &event, elen) 34251.149Skamil != -1); 34261.149Skamil 34271.149Skamil DPRINTF("Before resuming the child process where it left off " 34281.149Skamil "and without signal to be sent\n"); 34291.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 34301.149Skamil 34311.149Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 34321.149Skamil (trackfork && strcmp(fn, "fork") == 0) || 34331.149Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 34341.149Skamil DPRINTF("Before calling %s() for the tracee %d\n", TWAIT_FNAME, 34351.149Skamil tracee); 34361.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), 34371.149Skamil tracee); 34381.149Skamil 34391.149Skamil validate_status_stopped(status, SIGTRAP); 34401.149Skamil 34411.149Skamil SYSCALL_REQUIRE( 34421.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 34431.149Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 34441.149Skamil ATF_REQUIRE_EQ( 34451.149Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 34461.149Skamil PTRACE_POSIX_SPAWN); 34471.149Skamil } 34481.149Skamil if (trackfork && strcmp(fn, "fork") == 0) { 34491.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 34501.149Skamil PTRACE_FORK); 34511.149Skamil } 34521.149Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 34531.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 34541.149Skamil PTRACE_VFORK); 34551.149Skamil } 34561.149Skamil 34571.149Skamil tracee2 = state.pe_other_pid; 34581.149Skamil DPRINTF("Reported ptrace event with forkee %d\n", tracee2); 34591.149Skamil 34601.149Skamil DPRINTF("Before calling %s() for the forkee %d of the tracee " 34611.149Skamil "%d\n", TWAIT_FNAME, tracee2, tracee); 34621.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), 34631.149Skamil tracee2); 34641.149Skamil 34651.149Skamil validate_status_stopped(status, SIGTRAP); 34661.149Skamil 34671.149Skamil SYSCALL_REQUIRE( 34681.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee2, &state, slen) != -1); 34691.149Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 34701.149Skamil ATF_REQUIRE_EQ( 34711.149Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 34721.149Skamil PTRACE_POSIX_SPAWN); 34731.149Skamil } 34741.149Skamil if (trackfork && strcmp(fn, "fork") == 0) { 34751.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 34761.149Skamil PTRACE_FORK); 34771.149Skamil } 34781.149Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 34791.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 34801.149Skamil PTRACE_VFORK); 34811.149Skamil } 34821.149Skamil 34831.149Skamil ATF_REQUIRE_EQ(state.pe_other_pid, tracee); 34841.149Skamil 34851.149Skamil DPRINTF("Before resuming the forkee process where it left off " 34861.149Skamil "and without signal to be sent\n"); 34871.149Skamil SYSCALL_REQUIRE( 34881.149Skamil ptrace(PT_CONTINUE, tracee2, (void *)1, 0) != -1); 34891.149Skamil 34901.149Skamil DPRINTF("Before resuming the tracee process where it left off " 34911.149Skamil "and without signal to be sent\n"); 34921.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 34931.149Skamil } 34941.149Skamil 34951.149Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 34961.149Skamil DPRINTF("Before calling %s() for the tracee %d\n", TWAIT_FNAME, 34971.149Skamil tracee); 34981.149Skamil TWAIT_REQUIRE_SUCCESS( 34991.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35001.149Skamil 35011.149Skamil validate_status_stopped(status, SIGTRAP); 35021.149Skamil 35031.149Skamil SYSCALL_REQUIRE( 35041.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 35051.149Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 35061.149Skamil 35071.149Skamil tracee2 = state.pe_other_pid; 35081.149Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 35091.149Skamil tracee2); 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 35171.149Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 35181.149Skamil (trackfork && strcmp(fn, "fork") == 0) || 35191.149Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 35201.149Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 35211.149Skamil "\n", TWAIT_FNAME); 35221.149Skamil TWAIT_REQUIRE_SUCCESS( 35231.149Skamil wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 35241.149Skamil 35251.149Skamil validate_status_exited(status, exitval2); 35261.149Skamil 35271.149Skamil DPRINTF("Before calling %s() for the forkee - expected no " 35281.149Skamil "process\n", TWAIT_FNAME); 35291.149Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 35301.149Skamil wpid = TWAIT_GENERIC(tracee2, &status, 0)); 35311.149Skamil } 35321.149Skamil 35331.149Skamil DPRINTF("Before calling %s() for the tracee - expected stopped " 35341.149Skamil "SIGCHLD\n", TWAIT_FNAME); 35351.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35361.149Skamil 35371.149Skamil validate_status_stopped(status, SIGCHLD); 35381.149Skamil 35391.149Skamil DPRINTF("Before resuming the tracee process where it left off and " 35401.149Skamil "without signal to be sent\n"); 35411.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 35421.149Skamil 35431.149Skamil DPRINTF("Before calling %s() for the tracee - expected exited\n", 35441.149Skamil TWAIT_FNAME); 35451.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35461.149Skamil 35471.149Skamil validate_status_exited(status, exitval); 35481.149Skamil 35491.149Skamil /* Inform parent that tracer is exiting normally */ 35501.149Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 35511.149Skamil 35521.149Skamil DPRINTF("Before exiting of the tracer process\n"); 35531.149Skamil _exit(0 /* collect by initproc */); 35541.149Skamil } 35551.149Skamil 35561.149Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 35571.149Skamil "calling %s()\n", TWAIT_FNAME); 35581.149Skamil TWAIT_REQUIRE_SUCCESS( 35591.149Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 35601.149Skamil 35611.149Skamil validate_status_exited(status, exitval); 35621.149Skamil 35631.149Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 35641.149Skamil TWAIT_FNAME); 35651.149Skamil TWAIT_REQUIRE_SUCCESS( 35661.149Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 35671.149Skamil 35681.149Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 35691.149Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 35701.149Skamil 35711.149Skamil DPRINTF("Resume the tracee and let it crash\n"); 35721.149Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 35731.149Skamil 35741.149Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 35751.149Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 35761.149Skamil 35771.149Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 35781.149Skamil TWAIT_FNAME); 35791.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35801.149Skamil 35811.149Skamil validate_status_exited(status, exitval); 35821.149Skamil 35831.149Skamil DPRINTF("Await normal exit of tracer\n"); 35841.149Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 35851.149Skamil 35861.149Skamil msg_close(&parent_tracer); 35871.149Skamil msg_close(&parent_tracee); 35881.149Skamil} 35891.149Skamil 35901.149Skamil#define UNRELATED_TRACER_FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone)\ 35911.149SkamilATF_TC(name); \ 35921.149SkamilATF_TC_HEAD(name, tc) \ 35931.149Skamil{ \ 35941.149Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 35951.149Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 35961.149Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 35971.149Skamil tfork ? "|PTRACE_FORK" : "", \ 35981.149Skamil tvfork ? "|PTRACE_VFORK" : "", \ 35991.149Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 36001.149Skamil} \ 36011.149Skamil \ 36021.149SkamilATF_TC_BODY(name, tc) \ 36031.149Skamil{ \ 36041.149Skamil \ 36051.149Skamil unrelated_tracer_fork_body(fun, tspawn, tfork, tvfork, \ 36061.149Skamil tvforkdone); \ 36071.149Skamil} 36081.149Skamil 36091.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork1, "fork", false, false, false, false) 36101.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork2, "fork", false, true, false, false) 36111.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork3, "fork", false, false, true, false) 36121.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork4, "fork", false, true, true, false) 36131.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork5, "fork", false, false, false, true) 36141.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork6, "fork", false, true, false, true) 36151.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork7, "fork", false, false, true, true) 36161.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork8, "fork", false, true, true, true) 36171.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork9, "fork", true, false, false, false) 36181.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork10, "fork", true, true, false, false) 36191.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork11, "fork", true, false, true, false) 36201.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork12, "fork", true, true, true, false) 36211.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork13, "fork", true, false, false, true) 36221.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork14, "fork", true, true, false, true) 36231.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork15, "fork", true, false, true, true) 36241.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork16, "fork", true, true, true, true) 36251.149Skamil 36261.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork1, "vfork", false, false, false, false) 36271.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork2, "vfork", false, true, false, false) 36281.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork3, "vfork", false, false, true, false) 36291.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork4, "vfork", false, true, true, false) 36301.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork5, "vfork", false, false, false, true) 36311.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork6, "vfork", false, true, false, true) 36321.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork7, "vfork", false, false, true, true) 36331.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork8, "vfork", false, true, true, true) 36341.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork9, "vfork", true, false, false, false) 36351.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork10, "vfork", true, true, false, false) 36361.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork11, "vfork", true, false, true, false) 36371.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork12, "vfork", true, true, true, false) 36381.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork13, "vfork", true, false, false, true) 36391.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork14, "vfork", true, true, false, true) 36401.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork15, "vfork", true, false, true, true) 36411.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork16, "vfork", true, true, true, true) 36421.149Skamil 36431.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn1, "spawn", false, false, false, false) 36441.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn2, "spawn", false, true, false, false) 36451.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn3, "spawn", false, false, true, false) 36461.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn4, "spawn", false, true, true, false) 36471.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn5, "spawn", false, false, false, true) 36481.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn6, "spawn", false, true, false, true) 36491.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn7, "spawn", false, false, true, true) 36501.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn8, "spawn", false, true, true, true) 36511.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn9, "spawn", true, false, false, false) 36521.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn10, "spawn", true, true, false, false) 36531.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn11, "spawn", true, false, true, false) 36541.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn12, "spawn", true, true, true, false) 36551.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn13, "spawn", true, false, false, true) 36561.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn14, "spawn", true, true, false, true) 36571.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn15, "spawn", true, false, true, true) 36581.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn16, "spawn", true, true, true, true) 36591.149Skamil#endif 36601.149Skamil 36611.149Skamil/// ---------------------------------------------------------------------------- 36621.149Skamil 36631.149Skamil#if defined(TWAIT_HAVE_PID) 36641.149Skamilstatic void 36651.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 36661.116Skamil{ 36671.116Skamil const int exitval = 5; 36681.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 36691.116Skamil const int sigval = SIGSTOP; 36701.116Skamil pid_t child, child2 = 0, wpid; 36711.116Skamil#if defined(TWAIT_HAVE_STATUS) 36721.116Skamil int status; 36731.116Skamil#endif 36741.116Skamil ptrace_state_t state; 36751.116Skamil const int slen = sizeof(state); 36761.116Skamil ptrace_event_t event; 36771.116Skamil const int elen = sizeof(event); 36781.116Skamil 36791.116Skamil int op; 36801.116Skamil 36811.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 36821.116Skamil 36831.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 36841.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 36851.116Skamil if (child == 0) { 36861.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36871.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36881.116Skamil 36891.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 36901.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 36911.116Skamil 36921.126Skamil if (strcmp(fn, "spawn") == 0) { 36931.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 36941.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 36951.126Skamil } else { 36961.126Skamil if (strcmp(fn, "fork") == 0) { 36971.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 36981.126Skamil } else { 36991.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 37001.126Skamil } 37011.116Skamil 37021.126Skamil if (child2 == 0) 37031.126Skamil _exit(exitval2); 37041.126Skamil } 37051.116Skamil 37061.116Skamil FORKEE_REQUIRE_SUCCESS 37071.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 37081.116Skamil 37091.116Skamil forkee_status_exited(status, exitval2); 37101.116Skamil 37111.116Skamil DPRINTF("Before exiting of the child process\n"); 37121.116Skamil _exit(exitval); 37131.116Skamil } 37141.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37151.116Skamil 37161.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37171.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37181.116Skamil 37191.116Skamil validate_status_stopped(status, sigval); 37201.116Skamil 37211.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 37221.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 37231.126Skamil | PTRACE_VFORK_DONE; 37241.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 37251.116Skamil 37261.116Skamil DPRINTF("Before resuming the child process where it left off and " 37271.116Skamil "without signal to be sent\n"); 37281.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 37291.116Skamil 37301.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 37311.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37321.116Skamil 37331.116Skamil validate_status_stopped(status, SIGTRAP); 37341.116Skamil 37351.116Skamil SYSCALL_REQUIRE( 37361.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 37371.126Skamil 37381.126Skamil if (strcmp(fn, "spawn") == 0) 37391.126Skamil op = PTRACE_POSIX_SPAWN; 37401.126Skamil else if (strcmp(fn, "fork") == 0) 37411.126Skamil op = PTRACE_FORK; 37421.126Skamil else 37431.126Skamil op = PTRACE_VFORK; 37441.126Skamil 37451.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 37461.116Skamil 37471.116Skamil child2 = state.pe_other_pid; 37481.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 37491.116Skamil 37501.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 37511.126Skamil strcmp(fn, "vfork") == 0) 37521.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 37531.116Skamil else 37541.116Skamil op = PT_CONTINUE; 37551.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 37561.116Skamil 37571.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 37581.116Skamil TWAIT_FNAME, child2, child); 37591.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 37601.116Skamil 37611.116Skamil validate_status_stopped(status, SIGTRAP); 37621.116Skamil 37631.116Skamil SYSCALL_REQUIRE( 37641.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 37651.126Skamil if (strcmp(fn, "spawn") == 0) 37661.126Skamil op = PTRACE_POSIX_SPAWN; 37671.126Skamil else if (strcmp(fn, "fork") == 0) 37681.126Skamil op = PTRACE_FORK; 37691.126Skamil else 37701.126Skamil op = PTRACE_VFORK; 37711.126Skamil 37721.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 37731.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 37741.116Skamil 37751.116Skamil DPRINTF("Before resuming the forkee process where it left off " 37761.116Skamil "and without signal to be sent\n"); 37771.116Skamil SYSCALL_REQUIRE( 37781.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 37791.116Skamil 37801.126Skamil if (strcmp(fn, "vforkdone") == 0) { 37811.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 37821.116Skamil child); 37831.116Skamil TWAIT_REQUIRE_SUCCESS( 37841.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 37851.116Skamil 37861.116Skamil validate_status_stopped(status, SIGTRAP); 37871.116Skamil 37881.116Skamil SYSCALL_REQUIRE( 37891.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 37901.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 37911.116Skamil 37921.116Skamil child2 = state.pe_other_pid; 37931.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 37941.116Skamil child2); 37951.116Skamil 37961.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 37971.116Skamil DPRINTF("Before resuming the child process where it left off " 37981.116Skamil "and without signal to be sent\n"); 37991.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 38001.116Skamil } 38011.116Skamil 38021.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 38031.116Skamil TWAIT_FNAME); 38041.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 38051.116Skamil 38061.116Skamil validate_status_exited(status, exitval2); 38071.116Skamil 38081.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 38091.116Skamil TWAIT_FNAME); 38101.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 38111.116Skamil 38121.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 38131.116Skamil TWAIT_FNAME); 38141.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38151.116Skamil 38161.116Skamil if (kill_process) { 38171.116Skamil validate_status_signaled(status, SIGKILL, 0); 38181.116Skamil } else { 38191.116Skamil validate_status_exited(status, exitval); 38201.116Skamil } 38211.116Skamil 38221.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 38231.116Skamil TWAIT_FNAME); 38241.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 38251.116Skamil} 38261.116Skamil 38271.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 38281.116SkamilATF_TC(name); \ 38291.116SkamilATF_TC_HEAD(name, tc) \ 38301.116Skamil{ \ 38311.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 38321.126Skamil kprocess ? "killed" : "detached"); \ 38331.116Skamil} \ 38341.116Skamil \ 38351.116SkamilATF_TC_BODY(name, tc) \ 38361.116Skamil{ \ 38371.116Skamil \ 38381.126Skamil fork_detach_forker_body(event, kprocess); \ 38391.116Skamil} 38401.116Skamil 38411.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 38421.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 38431.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 38441.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 38451.126Skamil 38461.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 38471.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 38481.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 38491.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 38501.116Skamil#endif 38511.116Skamil 38521.116Skamil/// ---------------------------------------------------------------------------- 38531.116Skamil 38541.150Skamil#if defined(TWAIT_HAVE_PID) 38551.150Skamilstatic void 38561.150Skamilunrelated_tracer_fork_detach_forker_body(const char *fn, bool kill_process) 38571.150Skamil{ 38581.150Skamil const int sigval = SIGSTOP; 38591.150Skamil struct msg_fds parent_tracee, parent_tracer; 38601.150Skamil const int exitval = 10; 38611.150Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 38621.150Skamil pid_t tracee, tracer, wpid; 38631.150Skamil pid_t tracee2 = 0; 38641.150Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 38651.150Skamil#if defined(TWAIT_HAVE_STATUS) 38661.150Skamil int status; 38671.150Skamil#endif 38681.150Skamil int op; 38691.150Skamil 38701.150Skamil struct ptrace_siginfo info; 38711.150Skamil ptrace_state_t state; 38721.150Skamil const int slen = sizeof(state); 38731.150Skamil ptrace_event_t event; 38741.150Skamil const int elen = sizeof(event); 38751.150Skamil 38761.150Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 38771.150Skamil 38781.150Skamil DPRINTF("Spawn tracee\n"); 38791.150Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 38801.150Skamil tracee = atf_utils_fork(); 38811.150Skamil if (tracee == 0) { 38821.150Skamil // Wait for parent to let us crash 38831.150Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 38841.150Skamil 38851.150Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 38861.150Skamil FORKEE_ASSERT(raise(sigval) == 0); 38871.150Skamil 38881.150Skamil if (strcmp(fn, "spawn") == 0) { 38891.150Skamil FORKEE_ASSERT_EQ(posix_spawn(&tracee2, 38901.150Skamil arg[0], NULL, NULL, arg, NULL), 0); 38911.150Skamil } else { 38921.150Skamil if (strcmp(fn, "fork") == 0) { 38931.150Skamil FORKEE_ASSERT((tracee2 = fork()) != -1); 38941.150Skamil } else { 38951.150Skamil FORKEE_ASSERT((tracee2 = vfork()) != -1); 38961.150Skamil } 38971.150Skamil 38981.150Skamil if (tracee2 == 0) 38991.150Skamil _exit(exitval2); 39001.150Skamil } 39011.150Skamil 39021.150Skamil FORKEE_REQUIRE_SUCCESS 39031.150Skamil (wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 39041.150Skamil 39051.150Skamil forkee_status_exited(status, exitval2); 39061.150Skamil 39071.150Skamil DPRINTF("Before exiting of the child process\n"); 39081.150Skamil _exit(exitval); 39091.150Skamil } 39101.150Skamil 39111.150Skamil DPRINTF("Spawn debugger\n"); 39121.150Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 39131.150Skamil tracer = atf_utils_fork(); 39141.150Skamil if (tracer == 0) { 39151.150Skamil /* Fork again and drop parent to reattach to PID 1 */ 39161.150Skamil tracer = atf_utils_fork(); 39171.150Skamil if (tracer != 0) 39181.150Skamil _exit(exitval); 39191.150Skamil 39201.150Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 39211.150Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 39221.150Skamil 39231.150Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 39241.150Skamil FORKEE_REQUIRE_SUCCESS( 39251.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 39261.150Skamil 39271.150Skamil forkee_status_stopped(status, SIGSTOP); 39281.150Skamil 39291.150Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 39301.150Skamil "traced process\n"); 39311.150Skamil SYSCALL_REQUIRE( 39321.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 39331.150Skamil 39341.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39351.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39361.150Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 39371.150Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 39381.150Skamil 39391.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 39401.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 39411.150Skamil 39421.150Skamil /* Resume tracee with PT_CONTINUE */ 39431.150Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 39441.150Skamil 39451.150Skamil /* Inform parent that tracer has attached to tracee */ 39461.150Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 39471.150Skamil 39481.150Skamil /* Wait for parent to tell use that tracee should have exited */ 39491.150Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 39501.150Skamil 39511.150Skamil /* Wait for tracee and assert that it exited */ 39521.150Skamil FORKEE_REQUIRE_SUCCESS( 39531.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 39541.150Skamil 39551.150Skamil forkee_status_stopped(status, sigval); 39561.150Skamil 39571.150Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 39581.150Skamil "traced process\n"); 39591.150Skamil SYSCALL_REQUIRE( 39601.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 39611.150Skamil 39621.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39631.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39641.150Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 39651.150Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 39661.150Skamil 39671.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 39681.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 39691.150Skamil 39701.150Skamil DPRINTF("Set EVENT_MASK for the child %d\n", tracee); 39711.150Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 39721.150Skamil | PTRACE_VFORK_DONE; 39731.150Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, tracee, &event, elen) != -1); 39741.150Skamil 39751.150Skamil DPRINTF("Before resuming the child process where it left off and " 39761.150Skamil "without signal to be sent\n"); 39771.150Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 39781.150Skamil 39791.150Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, tracee); 39801.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 39811.150Skamil 39821.150Skamil validate_status_stopped(status, SIGTRAP); 39831.150Skamil 39841.150Skamil SYSCALL_REQUIRE( 39851.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 39861.150Skamil 39871.150Skamil if (strcmp(fn, "spawn") == 0) 39881.150Skamil op = PTRACE_POSIX_SPAWN; 39891.150Skamil else if (strcmp(fn, "fork") == 0) 39901.150Skamil op = PTRACE_FORK; 39911.150Skamil else 39921.150Skamil op = PTRACE_VFORK; 39931.150Skamil 39941.150Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 39951.150Skamil 39961.150Skamil tracee2 = state.pe_other_pid; 39971.150Skamil DPRINTF("Reported ptrace event with forkee %d\n", tracee2); 39981.150Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 39991.150Skamil strcmp(fn, "vfork") == 0) 40001.150Skamil op = kill_process ? PT_KILL : PT_DETACH; 40011.150Skamil else 40021.150Skamil op = PT_CONTINUE; 40031.150Skamil SYSCALL_REQUIRE(ptrace(op, tracee, (void *)1, 0) != -1); 40041.150Skamil 40051.150Skamil DPRINTF("Before calling %s() for the forkee %d of the tracee %d\n", 40061.150Skamil TWAIT_FNAME, tracee2, tracee); 40071.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 40081.150Skamil 40091.150Skamil validate_status_stopped(status, SIGTRAP); 40101.150Skamil 40111.150Skamil SYSCALL_REQUIRE( 40121.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee2, &state, slen) != -1); 40131.150Skamil if (strcmp(fn, "spawn") == 0) 40141.150Skamil op = PTRACE_POSIX_SPAWN; 40151.150Skamil else if (strcmp(fn, "fork") == 0) 40161.150Skamil op = PTRACE_FORK; 40171.150Skamil else 40181.150Skamil op = PTRACE_VFORK; 40191.150Skamil 40201.150Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 40211.150Skamil ATF_REQUIRE_EQ(state.pe_other_pid, tracee); 40221.150Skamil 40231.150Skamil DPRINTF("Before resuming the forkee process where it left off " 40241.150Skamil "and without signal to be sent\n"); 40251.150Skamil SYSCALL_REQUIRE( 40261.150Skamil ptrace(PT_CONTINUE, tracee2, (void *)1, 0) != -1); 40271.150Skamil 40281.150Skamil if (strcmp(fn, "vforkdone") == 0) { 40291.150Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 40301.150Skamil tracee); 40311.150Skamil TWAIT_REQUIRE_SUCCESS( 40321.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40331.150Skamil 40341.150Skamil validate_status_stopped(status, SIGTRAP); 40351.150Skamil 40361.150Skamil SYSCALL_REQUIRE( 40371.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 40381.150Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 40391.150Skamil 40401.150Skamil tracee2 = state.pe_other_pid; 40411.150Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 40421.150Skamil tracee2); 40431.150Skamil 40441.150Skamil op = kill_process ? PT_KILL : PT_DETACH; 40451.150Skamil DPRINTF("Before resuming the child process where it left off " 40461.150Skamil "and without signal to be sent\n"); 40471.150Skamil SYSCALL_REQUIRE(ptrace(op, tracee, (void *)1, 0) != -1); 40481.150Skamil } 40491.150Skamil 40501.150Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 40511.150Skamil TWAIT_FNAME); 40521.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 40531.150Skamil 40541.150Skamil validate_status_exited(status, exitval2); 40551.150Skamil 40561.150Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 40571.150Skamil TWAIT_FNAME); 40581.150Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(tracee2, &status, 0)); 40591.150Skamil 40601.150Skamil if (kill_process) { 40611.150Skamil DPRINTF("Before calling %s() for the forkee - expected signaled\n", 40621.150Skamil TWAIT_FNAME); 40631.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40641.150Skamil 40651.150Skamil validate_status_signaled(status, SIGKILL, 0); 40661.150Skamil } 40671.150Skamil 40681.150Skamil /* Inform parent that tracer is exiting normally */ 40691.150Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 40701.150Skamil 40711.150Skamil DPRINTF("Before exiting of the tracer process\n"); 40721.150Skamil _exit(0 /* collect by initproc */); 40731.150Skamil } 40741.150Skamil 40751.150Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 40761.150Skamil "calling %s()\n", TWAIT_FNAME); 40771.150Skamil TWAIT_REQUIRE_SUCCESS( 40781.150Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 40791.150Skamil 40801.150Skamil validate_status_exited(status, exitval); 40811.150Skamil 40821.150Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 40831.150Skamil TWAIT_FNAME); 40841.150Skamil TWAIT_REQUIRE_SUCCESS( 40851.150Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 40861.150Skamil 40871.150Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 40881.150Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 40891.150Skamil 40901.150Skamil DPRINTF("Resume the tracee and let it crash\n"); 40911.150Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 40921.150Skamil 40931.150Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 40941.150Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 40951.150Skamil 40961.150Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 40971.150Skamil TWAIT_FNAME); 40981.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40991.150Skamil 41001.150Skamil if (kill_process) { 41011.150Skamil validate_status_signaled(status, SIGKILL, 0); 41021.150Skamil } else { 41031.150Skamil validate_status_exited(status, exitval); 41041.150Skamil } 41051.150Skamil 41061.150Skamil DPRINTF("Await normal exit of tracer\n"); 41071.150Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 41081.150Skamil 41091.150Skamil msg_close(&parent_tracer); 41101.150Skamil msg_close(&parent_tracee); 41111.150Skamil} 41121.150Skamil 41131.150Skamil#define UNRELATED_TRACER_FORK_DETACH_FORKER(name,event,kprocess) \ 41141.150SkamilATF_TC(name); \ 41151.150SkamilATF_TC_HEAD(name, tc) \ 41161.150Skamil{ \ 41171.150Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 41181.150Skamil kprocess ? "killed" : "detached"); \ 41191.150Skamil} \ 41201.150Skamil \ 41211.150SkamilATF_TC_BODY(name, tc) \ 41221.150Skamil{ \ 41231.150Skamil \ 41241.150Skamil unrelated_tracer_fork_detach_forker_body(event, kprocess); \ 41251.150Skamil} 41261.150Skamil 41271.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_posix_spawn_detach_spawner, "spawn", false) 41281.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_fork_detach_forker, "fork", false) 41291.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_detach_vforker, "vfork", false) 41301.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_detach_vforkerdone, "vforkdone", false) 41311.150Skamil 41321.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_posix_spawn_kill_spawner, "spawn", true) 41331.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_fork_kill_forker, "fork", true) 41341.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_kill_vforker, "vfork", true) 41351.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_kill_vforkerdone, "vforkdone", true) 41361.150Skamil#endif 41371.150Skamil 41381.150Skamil/// ---------------------------------------------------------------------------- 41391.150Skamil 41401.108Skamilstatic void 41411.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 41421.108Skamil{ 41431.108Skamil const int exitval = 5; 41441.108Skamil const int exitval2 = 15; 41451.108Skamil pid_t child, child2 = 0, wpid; 41461.108Skamil#if defined(TWAIT_HAVE_STATUS) 41471.108Skamil int status; 41481.108Skamil#endif 41491.108Skamil 41501.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 41511.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 41521.108Skamil if (child == 0) { 41531.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41541.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41551.108Skamil 41561.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 41571.108Skamil 41581.108Skamil if (child2 == 0) 41591.108Skamil _exit(exitval2); 41601.108Skamil 41611.108Skamil FORKEE_REQUIRE_SUCCESS 41621.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 41631.108Skamil 41641.108Skamil forkee_status_exited(status, exitval2); 41651.108Skamil 41661.108Skamil DPRINTF("Before exiting of the child process\n"); 41671.108Skamil _exit(exitval); 41681.108Skamil } 41691.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41701.108Skamil 41711.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 41721.108Skamil TWAIT_FNAME); 41731.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41741.108Skamil 41751.108Skamil validate_status_exited(status, exitval); 41761.108Skamil 41771.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 41781.108Skamil TWAIT_FNAME); 41791.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41801.108Skamil} 41811.108Skamil 41821.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 41831.108SkamilATF_TC(name); \ 41841.108SkamilATF_TC_HEAD(name, tc) \ 41851.108Skamil{ \ 41861.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 41871.108Skamil "called from vfork(2)ed child"); \ 41881.108Skamil} \ 41891.108Skamil \ 41901.108SkamilATF_TC_BODY(name, tc) \ 41911.108Skamil{ \ 41921.108Skamil \ 41931.108Skamil traceme_vfork_fork_body(fun); \ 41941.108Skamil} 41951.108Skamil 41961.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 41971.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 41981.108Skamil 41991.108Skamil/// ---------------------------------------------------------------------------- 42001.108Skamil 42011.54Skamilenum bytes_transfer_type { 42021.54Skamil BYTES_TRANSFER_DATA, 42031.54Skamil BYTES_TRANSFER_DATAIO, 42041.54Skamil BYTES_TRANSFER_TEXT, 42051.54Skamil BYTES_TRANSFER_TEXTIO, 42061.54Skamil BYTES_TRANSFER_AUXV 42071.54Skamil}; 42081.31Skamil 42091.54Skamilstatic int __used 42101.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 42111.54Skamil{ 42121.54Skamil int e, f, g, h; 42131.1Skamil 42141.54Skamil a *= 4; 42151.54Skamil b += 3; 42161.54Skamil c -= 2; 42171.54Skamil d /= 1; 42181.1Skamil 42191.54Skamil e = strtol("10", NULL, 10); 42201.54Skamil f = strtol("20", NULL, 10); 42211.54Skamil g = strtol("30", NULL, 10); 42221.54Skamil h = strtol("40", NULL, 10); 42231.1Skamil 42241.54Skamil return (a + b * c - d) + (e * f - g / h); 42251.1Skamil} 42261.1Skamil 42271.54Skamilstatic void 42281.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 42291.1Skamil{ 42301.1Skamil const int exitval = 5; 42311.1Skamil const int sigval = SIGSTOP; 42321.1Skamil pid_t child, wpid; 42331.54Skamil bool skip = false; 42341.1Skamil 42351.54Skamil int lookup_me = 0; 42361.54Skamil uint8_t lookup_me8 = 0; 42371.54Skamil uint16_t lookup_me16 = 0; 42381.54Skamil uint32_t lookup_me32 = 0; 42391.54Skamil uint64_t lookup_me64 = 0; 42401.1Skamil 42411.54Skamil int magic = 0x13579246; 42421.54Skamil uint8_t magic8 = 0xab; 42431.54Skamil uint16_t magic16 = 0x1234; 42441.54Skamil uint32_t magic32 = 0x98765432; 42451.54Skamil uint64_t magic64 = 0xabcdef0123456789; 42461.1Skamil 42471.54Skamil struct ptrace_io_desc io; 42481.1Skamil#if defined(TWAIT_HAVE_STATUS) 42491.1Skamil int status; 42501.1Skamil#endif 42511.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 42521.60Skre AuxInfo ai[513], *aip; 42531.55Schristos 42541.55Schristos ATF_REQUIRE(size < sizeof(ai)); 42551.1Skamil 42561.54Skamil /* Prepare variables for .TEXT transfers */ 42571.54Skamil switch (type) { 42581.54Skamil case BYTES_TRANSFER_TEXT: 42591.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 42601.54Skamil break; 42611.54Skamil case BYTES_TRANSFER_TEXTIO: 42621.54Skamil switch (size) { 42631.54Skamil case 8: 42641.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 42651.54Skamil break; 42661.54Skamil case 16: 42671.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 42681.54Skamil break; 42691.54Skamil case 32: 42701.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 42711.54Skamil break; 42721.54Skamil case 64: 42731.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 42741.54Skamil break; 42751.54Skamil } 42761.54Skamil break; 42771.54Skamil default: 42781.54Skamil break; 42791.54Skamil } 42801.1Skamil 42811.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 42821.54Skamil switch (type) { 42831.54Skamil case BYTES_TRANSFER_TEXTIO: 42841.54Skamil case BYTES_TRANSFER_DATAIO: 42851.54Skamil io.piod_op = operation; 42861.54Skamil switch (size) { 42871.54Skamil case 8: 42881.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 42891.54Skamil (void *)bytes_transfer_dummy : 42901.54Skamil &lookup_me8; 42911.54Skamil io.piod_addr = &lookup_me8; 42921.54Skamil io.piod_len = sizeof(lookup_me8); 42931.54Skamil break; 42941.54Skamil case 16: 42951.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 42961.54Skamil (void *)bytes_transfer_dummy : 42971.54Skamil &lookup_me16; 42981.54Skamil io.piod_addr = &lookup_me16; 42991.54Skamil io.piod_len = sizeof(lookup_me16); 43001.54Skamil break; 43011.54Skamil case 32: 43021.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 43031.54Skamil (void *)bytes_transfer_dummy : 43041.54Skamil &lookup_me32; 43051.54Skamil io.piod_addr = &lookup_me32; 43061.54Skamil io.piod_len = sizeof(lookup_me32); 43071.54Skamil break; 43081.54Skamil case 64: 43091.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 43101.54Skamil (void *)bytes_transfer_dummy : 43111.54Skamil &lookup_me64; 43121.54Skamil io.piod_addr = &lookup_me64; 43131.54Skamil io.piod_len = sizeof(lookup_me64); 43141.54Skamil break; 43151.54Skamil default: 43161.54Skamil break; 43171.54Skamil } 43181.54Skamil break; 43191.54Skamil case BYTES_TRANSFER_AUXV: 43201.54Skamil io.piod_op = operation; 43211.54Skamil io.piod_offs = 0; 43221.54Skamil io.piod_addr = ai; 43231.54Skamil io.piod_len = size; 43241.54Skamil break; 43251.54Skamil default: 43261.54Skamil break; 43271.1Skamil } 43281.1Skamil 43291.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43301.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43311.1Skamil if (child == 0) { 43321.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43331.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 43341.1Skamil 43351.54Skamil switch (type) { 43361.54Skamil case BYTES_TRANSFER_DATA: 43371.54Skamil switch (operation) { 43381.54Skamil case PT_READ_D: 43391.54Skamil case PT_READ_I: 43401.54Skamil lookup_me = magic; 43411.54Skamil break; 43421.54Skamil default: 43431.54Skamil break; 43441.54Skamil } 43451.54Skamil break; 43461.54Skamil case BYTES_TRANSFER_DATAIO: 43471.54Skamil switch (operation) { 43481.54Skamil case PIOD_READ_D: 43491.54Skamil case PIOD_READ_I: 43501.54Skamil switch (size) { 43511.54Skamil case 8: 43521.54Skamil lookup_me8 = magic8; 43531.54Skamil break; 43541.54Skamil case 16: 43551.54Skamil lookup_me16 = magic16; 43561.54Skamil break; 43571.54Skamil case 32: 43581.54Skamil lookup_me32 = magic32; 43591.54Skamil break; 43601.54Skamil case 64: 43611.54Skamil lookup_me64 = magic64; 43621.54Skamil break; 43631.54Skamil default: 43641.54Skamil break; 43651.54Skamil } 43661.54Skamil break; 43671.54Skamil default: 43681.54Skamil break; 43691.54Skamil } 43701.54Skamil default: 43711.54Skamil break; 43721.54Skamil } 43731.54Skamil 43741.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 43751.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 43761.1Skamil 43771.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 43781.54Skamil switch (type) { 43791.54Skamil case BYTES_TRANSFER_DATA: 43801.54Skamil switch (operation) { 43811.54Skamil case PT_WRITE_D: 43821.54Skamil case PT_WRITE_I: 43831.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 43841.54Skamil break; 43851.54Skamil default: 43861.54Skamil break; 43871.54Skamil } 43881.54Skamil break; 43891.54Skamil case BYTES_TRANSFER_DATAIO: 43901.54Skamil switch (operation) { 43911.54Skamil case PIOD_WRITE_D: 43921.54Skamil case PIOD_WRITE_I: 43931.54Skamil switch (size) { 43941.54Skamil case 8: 43951.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 43961.54Skamil break; 43971.54Skamil case 16: 43981.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 43991.54Skamil break; 44001.54Skamil case 32: 44011.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 44021.54Skamil break; 44031.54Skamil case 64: 44041.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 44051.54Skamil break; 44061.54Skamil default: 44071.54Skamil break; 44081.54Skamil } 44091.54Skamil break; 44101.54Skamil default: 44111.54Skamil break; 44121.54Skamil } 44131.54Skamil break; 44141.54Skamil case BYTES_TRANSFER_TEXT: 44151.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 44161.54Skamil sizeof(magic)) == 0); 44171.54Skamil break; 44181.54Skamil case BYTES_TRANSFER_TEXTIO: 44191.54Skamil switch (size) { 44201.54Skamil case 8: 44211.54Skamil FORKEE_ASSERT(memcmp(&magic8, 44221.54Skamil bytes_transfer_dummy, 44231.54Skamil sizeof(magic8)) == 0); 44241.54Skamil break; 44251.54Skamil case 16: 44261.54Skamil FORKEE_ASSERT(memcmp(&magic16, 44271.54Skamil bytes_transfer_dummy, 44281.54Skamil sizeof(magic16)) == 0); 44291.54Skamil break; 44301.54Skamil case 32: 44311.54Skamil FORKEE_ASSERT(memcmp(&magic32, 44321.54Skamil bytes_transfer_dummy, 44331.54Skamil sizeof(magic32)) == 0); 44341.54Skamil break; 44351.54Skamil case 64: 44361.54Skamil FORKEE_ASSERT(memcmp(&magic64, 44371.54Skamil bytes_transfer_dummy, 44381.54Skamil sizeof(magic64)) == 0); 44391.54Skamil break; 44401.54Skamil } 44411.54Skamil break; 44421.54Skamil default: 44431.54Skamil break; 44441.54Skamil } 44451.54Skamil 44461.13Schristos DPRINTF("Before exiting of the child process\n"); 44471.1Skamil _exit(exitval); 44481.1Skamil } 44491.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44501.1Skamil 44511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44531.1Skamil 44541.1Skamil validate_status_stopped(status, sigval); 44551.1Skamil 44561.54Skamil /* Check PaX MPROTECT */ 44571.54Skamil if (!can_we_write_to_text(child)) { 44581.54Skamil switch (type) { 44591.54Skamil case BYTES_TRANSFER_TEXTIO: 44601.54Skamil switch (operation) { 44611.54Skamil case PIOD_WRITE_D: 44621.54Skamil case PIOD_WRITE_I: 44631.54Skamil skip = true; 44641.54Skamil break; 44651.54Skamil default: 44661.54Skamil break; 44671.54Skamil } 44681.54Skamil break; 44691.54Skamil case BYTES_TRANSFER_TEXT: 44701.54Skamil switch (operation) { 44711.54Skamil case PT_WRITE_D: 44721.54Skamil case PT_WRITE_I: 44731.54Skamil skip = true; 44741.54Skamil break; 44751.54Skamil default: 44761.54Skamil break; 44771.54Skamil } 44781.54Skamil break; 44791.54Skamil default: 44801.54Skamil break; 44811.54Skamil } 44821.54Skamil } 44831.1Skamil 44841.54Skamil /* Bailout cleanly killing the child process */ 44851.54Skamil if (skip) { 44861.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 44871.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44881.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 44891.54Skamil child); 44901.1Skamil 44911.54Skamil validate_status_signaled(status, SIGKILL, 0); 44921.1Skamil 44931.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 44941.54Skamil } 44951.1Skamil 44961.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 44971.54Skamil "parent=%d\n", child, getpid()); 44981.1Skamil 44991.54Skamil switch (type) { 45001.54Skamil case BYTES_TRANSFER_TEXTIO: 45011.54Skamil case BYTES_TRANSFER_DATAIO: 45021.54Skamil case BYTES_TRANSFER_AUXV: 45031.54Skamil switch (operation) { 45041.54Skamil case PIOD_WRITE_D: 45051.54Skamil case PIOD_WRITE_I: 45061.54Skamil switch (size) { 45071.54Skamil case 8: 45081.54Skamil lookup_me8 = magic8; 45091.54Skamil break; 45101.54Skamil case 16: 45111.54Skamil lookup_me16 = magic16; 45121.54Skamil break; 45131.54Skamil case 32: 45141.54Skamil lookup_me32 = magic32; 45151.54Skamil break; 45161.54Skamil case 64: 45171.54Skamil lookup_me64 = magic64; 45181.54Skamil break; 45191.54Skamil default: 45201.54Skamil break; 45211.54Skamil } 45221.54Skamil break; 45231.54Skamil default: 45241.54Skamil break; 45251.54Skamil } 45261.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 45271.54Skamil switch (operation) { 45281.54Skamil case PIOD_READ_D: 45291.54Skamil case PIOD_READ_I: 45301.54Skamil switch (size) { 45311.54Skamil case 8: 45321.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 45331.54Skamil break; 45341.54Skamil case 16: 45351.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 45361.54Skamil break; 45371.54Skamil case 32: 45381.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 45391.54Skamil break; 45401.54Skamil case 64: 45411.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 45421.54Skamil break; 45431.54Skamil default: 45441.54Skamil break; 45451.54Skamil } 45461.54Skamil break; 45471.54Skamil case PIOD_READ_AUXV: 45481.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 45491.54Skamil io.piod_len); 45501.54Skamil ATF_REQUIRE(io.piod_len > 0); 45511.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 45521.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 45531.54Skamil (long long int)aip->a_type, 45541.54Skamil (long long int)aip->a_v); 45551.54Skamil break; 45561.54Skamil default: 45571.54Skamil break; 45581.54Skamil } 45591.54Skamil break; 45601.54Skamil case BYTES_TRANSFER_TEXT: 45611.54Skamil switch (operation) { 45621.54Skamil case PT_READ_D: 45631.54Skamil case PT_READ_I: 45641.54Skamil errno = 0; 45651.54Skamil lookup_me = ptrace(operation, child, 45661.54Skamil bytes_transfer_dummy, 0); 45671.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 45681.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 45691.54Skamil break; 45701.54Skamil case PT_WRITE_D: 45711.54Skamil case PT_WRITE_I: 45721.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 45731.54Skamil bytes_transfer_dummy, magic) 45741.54Skamil != -1); 45751.54Skamil break; 45761.54Skamil default: 45771.54Skamil break; 45781.54Skamil } 45791.54Skamil break; 45801.54Skamil case BYTES_TRANSFER_DATA: 45811.54Skamil switch (operation) { 45821.54Skamil case PT_READ_D: 45831.54Skamil case PT_READ_I: 45841.54Skamil errno = 0; 45851.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 45861.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 45871.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 45881.54Skamil break; 45891.54Skamil case PT_WRITE_D: 45901.54Skamil case PT_WRITE_I: 45911.54Skamil lookup_me = magic; 45921.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 45931.54Skamil magic) != -1); 45941.54Skamil break; 45951.54Skamil default: 45961.54Skamil break; 45971.54Skamil } 45981.54Skamil break; 45991.54Skamil default: 46001.54Skamil break; 46011.54Skamil } 46021.1Skamil 46031.13Schristos DPRINTF("Before resuming the child process where it left off and " 46041.1Skamil "without signal to be sent\n"); 46051.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46061.1Skamil 46071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46091.1Skamil 46101.1Skamil validate_status_exited(status, exitval); 46111.1Skamil 46121.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46131.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46141.1Skamil} 46151.1Skamil 46161.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 46171.61SkreATF_TC(test); \ 46181.61SkreATF_TC_HEAD(test, tc) \ 46191.61Skre{ \ 46201.61Skre atf_tc_set_md_var(tc, "descr", \ 46211.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 46221.61Skre " of type " #type); \ 46231.61Skre} \ 46241.61Skre \ 46251.61SkreATF_TC_BODY(test, tc) \ 46261.61Skre{ \ 46271.61Skre \ 46281.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 46291.1Skamil} 46301.1Skamil 46311.54Skamil// DATA 46321.1Skamil 46331.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 46341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 46351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 46361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 46371.54Skamil 46381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 46391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 46401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 46411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 46421.54Skamil 46431.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 46441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 46451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 46461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 46471.54Skamil 46481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 46491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 46501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 46511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 46521.54Skamil 46531.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 46541.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 46551.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 46561.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 46571.54Skamil 46581.54Skamil// TEXT 46591.54Skamil 46601.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 46611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 46621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 46631.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 46641.54Skamil 46651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 46661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 46671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 46681.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 46691.54Skamil 46701.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 46711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 46721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 46731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 46741.54Skamil 46751.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 46761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 46771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 46781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 46791.54Skamil 46801.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 46811.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 46821.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 46831.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 46841.1Skamil 46851.54Skamil// AUXV 46861.1Skamil 46871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 46881.1Skamil 46891.54Skamil/// ---------------------------------------------------------------------------- 46901.1Skamil 46911.101Skamilstatic void 46921.101Skamilbytes_transfer_alignment(const char *operation) 46931.101Skamil{ 46941.101Skamil const int exitval = 5; 46951.101Skamil const int sigval = SIGSTOP; 46961.101Skamil pid_t child, wpid; 46971.101Skamil#if defined(TWAIT_HAVE_STATUS) 46981.101Skamil int status; 46991.101Skamil#endif 47001.101Skamil char *buffer; 47011.101Skamil int vector; 47021.101Skamil size_t len; 47031.101Skamil size_t i; 47041.101Skamil int op; 47051.101Skamil 47061.101Skamil struct ptrace_io_desc io; 47071.101Skamil struct ptrace_siginfo info; 47081.101Skamil 47091.101Skamil memset(&io, 0, sizeof(io)); 47101.101Skamil memset(&info, 0, sizeof(info)); 47111.101Skamil 47121.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 47131.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 47141.101Skamil buffer = malloc(len); 47151.101Skamil ATF_REQUIRE(buffer != NULL); 47161.101Skamil 47171.101Skamil /* Initialize the buffer with random data */ 47181.101Skamil for (i = 0; i < len; i++) 47191.101Skamil buffer[i] = i & 0xff; 47201.101Skamil 47211.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 47221.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 47231.101Skamil if (child == 0) { 47241.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47251.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47261.101Skamil 47271.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47281.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 47291.101Skamil 47301.101Skamil DPRINTF("Before exiting of the child process\n"); 47311.101Skamil _exit(exitval); 47321.101Skamil } 47331.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47341.101Skamil 47351.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47361.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47371.101Skamil 47381.101Skamil validate_status_stopped(status, sigval); 47391.101Skamil 47401.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 47411.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 47421.101Skamil != -1); 47431.101Skamil 47441.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47451.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 47461.101Skamil "si_errno=%#x\n", 47471.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47481.101Skamil info.psi_siginfo.si_errno); 47491.101Skamil 47501.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 47511.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 47521.101Skamil 47531.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 47541.101Skamil strcmp(operation, "PT_READ_D") == 0) { 47551.101Skamil if (strcmp(operation, "PT_READ_I")) 47561.101Skamil op = PT_READ_I; 47571.101Skamil else 47581.101Skamil op = PT_READ_D; 47591.101Skamil 47601.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 47611.101Skamil errno = 0; 47621.101Skamil vector = ptrace(op, child, buffer + i, 0); 47631.101Skamil ATF_REQUIRE_EQ(errno, 0); 47641.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 47651.101Skamil } 47661.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 47671.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 47681.101Skamil if (strcmp(operation, "PT_WRITE_I")) 47691.101Skamil op = PT_WRITE_I; 47701.101Skamil else 47711.101Skamil op = PT_WRITE_D; 47721.101Skamil 47731.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 47741.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 47751.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 47761.101Skamil != -1); 47771.101Skamil } 47781.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 47791.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 47801.101Skamil if (strcmp(operation, "PIOD_READ_I")) 47811.101Skamil op = PIOD_READ_I; 47821.101Skamil else 47831.101Skamil op = PIOD_READ_D; 47841.101Skamil 47851.101Skamil io.piod_op = op; 47861.101Skamil io.piod_addr = &vector; 47871.101Skamil io.piod_len = sizeof(int); 47881.101Skamil 47891.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 47901.101Skamil io.piod_offs = buffer + i; 47911.101Skamil 47921.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 47931.101Skamil != -1); 47941.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 47951.101Skamil } 47961.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 47971.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 47981.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 47991.101Skamil op = PIOD_WRITE_I; 48001.101Skamil else 48011.101Skamil op = PIOD_WRITE_D; 48021.101Skamil 48031.101Skamil io.piod_op = op; 48041.101Skamil io.piod_addr = &vector; 48051.101Skamil io.piod_len = sizeof(int); 48061.101Skamil 48071.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 48081.101Skamil io.piod_offs = buffer + i; 48091.101Skamil 48101.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 48111.101Skamil != -1); 48121.101Skamil } 48131.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 48141.101Skamil io.piod_op = PIOD_READ_AUXV; 48151.101Skamil io.piod_addr = &vector; 48161.101Skamil io.piod_len = sizeof(int); 48171.101Skamil 48181.101Skamil errno = 0; 48191.101Skamil i = 0; 48201.101Skamil /* Read the whole AUXV vector, it has no clear length */ 48211.120Skamil while (io.piod_len > 0) { 48221.101Skamil io.piod_offs = (void *)(intptr_t)i; 48231.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 48241.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 48251.101Skamil ++i; 48261.101Skamil } 48271.101Skamil } 48281.101Skamil 48291.101Skamil DPRINTF("Before resuming the child process where it left off " 48301.101Skamil "and without signal to be sent\n"); 48311.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48321.101Skamil 48331.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48341.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 48351.101Skamil child); 48361.101Skamil 48371.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48381.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48391.101Skamil} 48401.101Skamil 48411.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 48421.101SkamilATF_TC(test); \ 48431.101SkamilATF_TC_HEAD(test, tc) \ 48441.101Skamil{ \ 48451.101Skamil atf_tc_set_md_var(tc, "descr", \ 48461.101Skamil "Verify bytes transfer for potentially misaligned " \ 48471.101Skamil "operation " operation); \ 48481.101Skamil} \ 48491.101Skamil \ 48501.101SkamilATF_TC_BODY(test, tc) \ 48511.101Skamil{ \ 48521.101Skamil \ 48531.101Skamil bytes_transfer_alignment(operation); \ 48541.101Skamil} 48551.101Skamil 48561.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 48571.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 48581.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 48591.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 48601.101Skamil 48611.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 48621.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 48631.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 48641.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 48651.101Skamil 48661.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 48671.101Skamil 48681.101Skamil/// ---------------------------------------------------------------------------- 48691.101Skamil 48701.115Skamilstatic void 48711.115Skamilbytes_transfer_eof(const char *operation) 48721.115Skamil{ 48731.115Skamil const int exitval = 5; 48741.115Skamil const int sigval = SIGSTOP; 48751.115Skamil pid_t child, wpid; 48761.115Skamil#if defined(TWAIT_HAVE_STATUS) 48771.115Skamil int status; 48781.115Skamil#endif 48791.115Skamil FILE *fp; 48801.115Skamil char *p; 48811.115Skamil int vector; 48821.115Skamil int op; 48831.115Skamil 48841.115Skamil struct ptrace_io_desc io; 48851.115Skamil struct ptrace_siginfo info; 48861.115Skamil 48871.115Skamil memset(&io, 0, sizeof(io)); 48881.115Skamil memset(&info, 0, sizeof(info)); 48891.115Skamil 48901.115Skamil vector = 0; 48911.115Skamil 48921.115Skamil fp = tmpfile(); 48931.115Skamil ATF_REQUIRE(fp != NULL); 48941.115Skamil 48951.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 48961.115Skamil ATF_REQUIRE(p != MAP_FAILED); 48971.115Skamil 48981.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 48991.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 49001.115Skamil if (child == 0) { 49011.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 49021.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 49031.115Skamil 49041.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49051.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 49061.115Skamil 49071.115Skamil DPRINTF("Before exiting of the child process\n"); 49081.115Skamil _exit(exitval); 49091.115Skamil } 49101.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 49111.115Skamil 49121.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49131.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49141.115Skamil 49151.115Skamil validate_status_stopped(status, sigval); 49161.115Skamil 49171.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 49181.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 49191.115Skamil != -1); 49201.115Skamil 49211.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49221.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49231.115Skamil "si_errno=%#x\n", 49241.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49251.115Skamil info.psi_siginfo.si_errno); 49261.115Skamil 49271.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 49281.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 49291.115Skamil 49301.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 49311.115Skamil strcmp(operation, "PT_READ_D") == 0) { 49321.115Skamil if (strcmp(operation, "PT_READ_I")) 49331.115Skamil op = PT_READ_I; 49341.115Skamil else 49351.115Skamil op = PT_READ_D; 49361.115Skamil 49371.115Skamil errno = 0; 49381.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 49391.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49401.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 49411.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 49421.115Skamil if (strcmp(operation, "PT_WRITE_I")) 49431.115Skamil op = PT_WRITE_I; 49441.115Skamil else 49451.115Skamil op = PT_WRITE_D; 49461.115Skamil 49471.115Skamil errno = 0; 49481.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 49491.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49501.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 49511.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 49521.115Skamil if (strcmp(operation, "PIOD_READ_I")) 49531.115Skamil op = PIOD_READ_I; 49541.115Skamil else 49551.115Skamil op = PIOD_READ_D; 49561.115Skamil 49571.115Skamil io.piod_op = op; 49581.115Skamil io.piod_addr = &vector; 49591.115Skamil io.piod_len = sizeof(int); 49601.115Skamil io.piod_offs = p; 49611.115Skamil 49621.115Skamil errno = 0; 49631.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 49641.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49651.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 49661.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 49671.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 49681.115Skamil op = PIOD_WRITE_I; 49691.115Skamil else 49701.115Skamil op = PIOD_WRITE_D; 49711.115Skamil 49721.115Skamil io.piod_op = op; 49731.115Skamil io.piod_addr = &vector; 49741.115Skamil io.piod_len = sizeof(int); 49751.115Skamil io.piod_offs = p; 49761.115Skamil 49771.115Skamil errno = 0; 49781.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 49791.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49801.115Skamil } 49811.115Skamil 49821.115Skamil DPRINTF("Before resuming the child process where it left off " 49831.115Skamil "and without signal to be sent\n"); 49841.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 49851.115Skamil 49861.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49871.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 49881.115Skamil child); 49891.115Skamil 49901.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49911.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49921.115Skamil} 49931.115Skamil 49941.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 49951.115SkamilATF_TC(test); \ 49961.115SkamilATF_TC_HEAD(test, tc) \ 49971.115Skamil{ \ 49981.115Skamil atf_tc_set_md_var(tc, "descr", \ 49991.115Skamil "Verify bytes EOF byte transfer for the " operation \ 50001.115Skamil " operation"); \ 50011.115Skamil} \ 50021.115Skamil \ 50031.115SkamilATF_TC_BODY(test, tc) \ 50041.115Skamil{ \ 50051.115Skamil \ 50061.115Skamil bytes_transfer_eof(operation); \ 50071.115Skamil} 50081.115Skamil 50091.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 50101.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 50111.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 50121.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 50131.115Skamil 50141.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 50151.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 50161.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 50171.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 50181.115Skamil 50191.115Skamil/// ---------------------------------------------------------------------------- 50201.115Skamil 50211.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 50221.72Skamilstatic void 50231.72Skamilaccess_regs(const char *regset, const char *aux) 50241.1Skamil{ 50251.1Skamil const int exitval = 5; 50261.1Skamil const int sigval = SIGSTOP; 50271.1Skamil pid_t child, wpid; 50281.1Skamil#if defined(TWAIT_HAVE_STATUS) 50291.1Skamil int status; 50301.1Skamil#endif 50311.72Skamil#if defined(HAVE_GPREGS) 50321.72Skamil struct reg gpr; 50331.76Sscole register_t rgstr; 50341.1Skamil#endif 50351.72Skamil#if defined(HAVE_FPREGS) 50361.72Skamil struct fpreg fpr; 50371.1Skamil#endif 50381.76Sscole 50391.72Skamil#if !defined(HAVE_GPREGS) 50401.72Skamil if (strcmp(regset, "regs") == 0) 50411.72Skamil atf_tc_fail("Impossible test scenario!"); 50421.1Skamil#endif 50431.1Skamil 50441.72Skamil#if !defined(HAVE_FPREGS) 50451.72Skamil if (strcmp(regset, "fpregs") == 0) 50461.72Skamil atf_tc_fail("Impossible test scenario!"); 50471.1Skamil#endif 50481.1Skamil 50491.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 50501.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 50511.1Skamil if (child == 0) { 50521.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 50531.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 50541.1Skamil 50551.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 50561.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 50571.1Skamil 50581.13Schristos DPRINTF("Before exiting of the child process\n"); 50591.1Skamil _exit(exitval); 50601.1Skamil } 50611.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 50621.1Skamil 50631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50651.1Skamil 50661.1Skamil validate_status_stopped(status, sigval); 50671.1Skamil 50681.1Skamil#if defined(HAVE_GPREGS) 50691.72Skamil if (strcmp(regset, "regs") == 0) { 50701.72Skamil DPRINTF("Call GETREGS for the child process\n"); 50711.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 50721.72Skamil 50731.72Skamil if (strcmp(aux, "none") == 0) { 50741.72Skamil DPRINTF("Retrieved registers\n"); 50751.72Skamil } else if (strcmp(aux, "pc") == 0) { 50761.72Skamil rgstr = PTRACE_REG_PC(&gpr); 50771.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 50781.147Skamil } else if (strstr(aux, "set_pc") != NULL) { 50791.72Skamil rgstr = PTRACE_REG_PC(&gpr); 50801.147Skamil DPRINTF("Retrieved PC %" PRIxREGISTER "\n", rgstr); 50811.147Skamil if (strstr(aux, "0x1") != NULL) { 50821.147Skamil rgstr |= 0x1; 50831.147Skamil } else if (strstr(aux, "0x3") != NULL) { 50841.147Skamil rgstr |= 0x3; 50851.147Skamil } else if (strstr(aux, "0x7") != NULL) { 50861.147Skamil rgstr |= 0x7; 50871.147Skamil } 50881.147Skamil DPRINTF("Set PC %" PRIxREGISTER "\n", rgstr); 50891.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 50901.147Skamil if (strcmp(aux, "set_pc") != 0) { 50911.147Skamil /* This call can fail with EINVAL or similar. */ 50921.147Skamil ptrace(PT_SETREGS, child, &gpr, 0); 50931.147Skamil } 50941.72Skamil } else if (strcmp(aux, "sp") == 0) { 50951.72Skamil rgstr = PTRACE_REG_SP(&gpr); 50961.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 50971.72Skamil } else if (strcmp(aux, "intrv") == 0) { 50981.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 50991.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 51001.72Skamil } else if (strcmp(aux, "setregs") == 0) { 51011.72Skamil DPRINTF("Call SETREGS for the child process\n"); 51021.72Skamil SYSCALL_REQUIRE( 51031.147Skamil ptrace(PT_SETREGS, child, &gpr, 0) != -1); 51041.72Skamil } 51051.72Skamil } 51061.1Skamil#endif 51071.1Skamil 51081.72Skamil#if defined(HAVE_FPREGS) 51091.72Skamil if (strcmp(regset, "fpregs") == 0) { 51101.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 51111.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 51121.72Skamil 51131.72Skamil if (strcmp(aux, "getfpregs") == 0) { 51141.72Skamil DPRINTF("Retrieved FP registers\n"); 51151.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 51161.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 51171.72Skamil SYSCALL_REQUIRE( 51181.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 51191.72Skamil } 51201.1Skamil } 51211.1Skamil#endif 51221.1Skamil 51231.13Schristos DPRINTF("Before resuming the child process where it left off and " 51241.1Skamil "without signal to be sent\n"); 51251.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 51261.1Skamil 51271.147Skamil if (strstr(aux, "unaligned") != NULL) { 51281.147Skamil DPRINTF("Before resuming the child process where it left off " 51291.147Skamil "and without signal to be sent\n"); 51301.147Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 51311.147Skamil 51321.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51331.147Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 51341.147Skamil child); 51351.147Skamil 51361.147Skamil validate_status_signaled(status, SIGKILL, 0); 51371.147Skamil 51381.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51391.147Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 51401.147Skamil wpid = TWAIT_GENERIC(child, &status, 0)); 51411.147Skamil } else { 51421.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51431.147Skamil TWAIT_REQUIRE_SUCCESS( 51441.147Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 51451.1Skamil 51461.147Skamil validate_status_exited(status, exitval); 51471.1Skamil 51481.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51491.147Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 51501.147Skamil wpid = TWAIT_GENERIC(child, &status, 0)); 51511.147Skamil } 51521.1Skamil} 51531.1Skamil 51541.72Skamil#define ACCESS_REGS(test, regset, aux) \ 51551.72SkamilATF_TC(test); \ 51561.72SkamilATF_TC_HEAD(test, tc) \ 51571.72Skamil{ \ 51581.72Skamil atf_tc_set_md_var(tc, "descr", \ 51591.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 51601.72Skamil} \ 51611.72Skamil \ 51621.72SkamilATF_TC_BODY(test, tc) \ 51631.72Skamil{ \ 51641.72Skamil \ 51651.72Skamil access_regs(regset, aux); \ 51661.1Skamil} 51671.1Skamil#endif 51681.1Skamil 51691.72Skamil#if defined(HAVE_GPREGS) 51701.72SkamilACCESS_REGS(access_regs1, "regs", "none") 51711.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 51721.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 51731.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 51741.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 51751.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 51761.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x1, "regs", "set_pc+unaligned+0x1") 51771.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x3, "regs", "set_pc+unaligned+0x3") 51781.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x7, "regs", "set_pc+unaligned+0x7") 51791.1Skamil#endif 51801.1Skamil#if defined(HAVE_FPREGS) 51811.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 51821.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 51831.1Skamil#endif 51841.1Skamil 51851.72Skamil/// ---------------------------------------------------------------------------- 51861.1Skamil 51871.1Skamil#if defined(PT_STEP) 51881.1Skamilstatic void 51891.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 51901.1Skamil{ 51911.1Skamil const int exitval = 5; 51921.1Skamil const int sigval = SIGSTOP; 51931.1Skamil pid_t child, wpid; 51941.1Skamil#if defined(TWAIT_HAVE_STATUS) 51951.1Skamil int status; 51961.1Skamil#endif 51971.1Skamil int happy; 51981.95Skamil struct sigaction sa; 51991.81Skamil struct ptrace_siginfo info; 52001.95Skamil sigset_t intmask; 52011.95Skamil struct kinfo_proc2 kp; 52021.95Skamil size_t len = sizeof(kp); 52031.95Skamil 52041.95Skamil int name[6]; 52051.95Skamil const size_t namelen = __arraycount(name); 52061.95Skamil ki_sigset_t kp_sigmask; 52071.95Skamil ki_sigset_t kp_sigignore; 52081.1Skamil 52091.1Skamil#if defined(__arm__) 52101.1Skamil /* PT_STEP not supported on arm 32-bit */ 52111.1Skamil atf_tc_expect_fail("PR kern/52119"); 52121.1Skamil#endif 52131.1Skamil 52141.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52151.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52161.1Skamil if (child == 0) { 52171.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 52181.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 52191.1Skamil 52201.95Skamil if (masked) { 52211.95Skamil sigemptyset(&intmask); 52221.95Skamil sigaddset(&intmask, SIGTRAP); 52231.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 52241.95Skamil } 52251.95Skamil 52261.95Skamil if (ignored) { 52271.95Skamil memset(&sa, 0, sizeof(sa)); 52281.95Skamil sa.sa_handler = SIG_IGN; 52291.95Skamil sigemptyset(&sa.sa_mask); 52301.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 52311.95Skamil } 52321.95Skamil 52331.1Skamil happy = check_happy(999); 52341.1Skamil 52351.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 52361.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 52371.1Skamil 52381.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 52391.1Skamil 52401.13Schristos DPRINTF("Before exiting of the child process\n"); 52411.1Skamil _exit(exitval); 52421.1Skamil } 52431.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52441.1Skamil 52451.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52461.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52471.1Skamil 52481.1Skamil validate_status_stopped(status, sigval); 52491.1Skamil 52501.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52511.81Skamil SYSCALL_REQUIRE( 52521.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52531.81Skamil 52541.81Skamil DPRINTF("Before checking siginfo_t\n"); 52551.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 52561.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 52571.81Skamil 52581.95Skamil name[0] = CTL_KERN, 52591.95Skamil name[1] = KERN_PROC2, 52601.95Skamil name[2] = KERN_PROC_PID; 52611.95Skamil name[3] = child; 52621.95Skamil name[4] = sizeof(kp); 52631.95Skamil name[5] = 1; 52641.95Skamil 52651.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52661.95Skamil 52671.95Skamil if (masked) 52681.95Skamil kp_sigmask = kp.p_sigmask; 52691.95Skamil 52701.95Skamil if (ignored) 52711.95Skamil kp_sigignore = kp.p_sigignore; 52721.95Skamil 52731.1Skamil while (N --> 0) { 52741.2Skamil if (setstep) { 52751.13Schristos DPRINTF("Before resuming the child process where it " 52761.2Skamil "left off and without signal to be sent (use " 52771.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 52781.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 52791.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 52801.2Skamil != -1); 52811.2Skamil } else { 52821.13Schristos DPRINTF("Before resuming the child process where it " 52831.2Skamil "left off and without signal to be sent (use " 52841.2Skamil "PT_STEP)\n"); 52851.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 52861.2Skamil != -1); 52871.2Skamil } 52881.1Skamil 52891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 52911.1Skamil child); 52921.1Skamil 52931.1Skamil validate_status_stopped(status, SIGTRAP); 52941.2Skamil 52951.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52961.81Skamil SYSCALL_REQUIRE( 52971.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52981.81Skamil 52991.81Skamil DPRINTF("Before checking siginfo_t\n"); 53001.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 53011.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 53021.81Skamil 53031.2Skamil if (setstep) { 53041.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 53051.2Skamil } 53061.95Skamil 53071.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53081.95Skamil 53091.95Skamil if (masked) { 53101.95Skamil DPRINTF("kp_sigmask=" 53111.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53121.95Skamil PRIx32 "\n", 53131.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53141.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53151.95Skamil 53161.95Skamil DPRINTF("kp.p_sigmask=" 53171.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53181.95Skamil PRIx32 "\n", 53191.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53201.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53211.95Skamil 53221.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53231.95Skamil sizeof(kp_sigmask))); 53241.95Skamil } 53251.95Skamil 53261.95Skamil if (ignored) { 53271.95Skamil DPRINTF("kp_sigignore=" 53281.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53291.95Skamil PRIx32 "\n", 53301.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53311.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53321.95Skamil 53331.95Skamil DPRINTF("kp.p_sigignore=" 53341.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53351.95Skamil PRIx32 "\n", 53361.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53371.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53381.95Skamil 53391.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53401.95Skamil sizeof(kp_sigignore))); 53411.95Skamil } 53421.1Skamil } 53431.1Skamil 53441.13Schristos DPRINTF("Before resuming the child process where it left off and " 53451.1Skamil "without signal to be sent\n"); 53461.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53471.1Skamil 53481.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53501.1Skamil 53511.1Skamil validate_status_exited(status, exitval); 53521.1Skamil 53531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53541.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53551.1Skamil} 53561.1Skamil 53571.73Skamil#define PTRACE_STEP(test, N, setstep) \ 53581.73SkamilATF_TC(test); \ 53591.73SkamilATF_TC_HEAD(test, tc) \ 53601.73Skamil{ \ 53611.73Skamil atf_tc_set_md_var(tc, "descr", \ 53621.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 53631.73Skamil} \ 53641.73Skamil \ 53651.73SkamilATF_TC_BODY(test, tc) \ 53661.73Skamil{ \ 53671.73Skamil \ 53681.95Skamil ptrace_step(N, setstep, false, false); \ 53691.1Skamil} 53701.1Skamil 53711.73SkamilPTRACE_STEP(step1, 1, 0) 53721.73SkamilPTRACE_STEP(step2, 2, 0) 53731.73SkamilPTRACE_STEP(step3, 3, 0) 53741.73SkamilPTRACE_STEP(step4, 4, 0) 53751.73SkamilPTRACE_STEP(setstep1, 1, 1) 53761.73SkamilPTRACE_STEP(setstep2, 2, 1) 53771.73SkamilPTRACE_STEP(setstep3, 3, 1) 53781.73SkamilPTRACE_STEP(setstep4, 4, 1) 53791.95Skamil 53801.95SkamilATF_TC(step_signalmasked); 53811.95SkamilATF_TC_HEAD(step_signalmasked, tc) 53821.95Skamil{ 53831.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 53841.95Skamil} 53851.95Skamil 53861.95SkamilATF_TC_BODY(step_signalmasked, tc) 53871.95Skamil{ 53881.95Skamil 53891.95Skamil ptrace_step(1, 0, true, false); 53901.95Skamil} 53911.95Skamil 53921.95SkamilATF_TC(step_signalignored); 53931.95SkamilATF_TC_HEAD(step_signalignored, tc) 53941.95Skamil{ 53951.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 53961.95Skamil} 53971.95Skamil 53981.95SkamilATF_TC_BODY(step_signalignored, tc) 53991.95Skamil{ 54001.95Skamil 54011.95Skamil ptrace_step(1, 0, false, true); 54021.95Skamil} 54031.1Skamil#endif 54041.1Skamil 54051.73Skamil/// ---------------------------------------------------------------------------- 54061.1Skamil 54071.75Skamilstatic void 54081.75Skamilptrace_kill(const char *type) 54091.1Skamil{ 54101.75Skamil const int sigval = SIGSTOP; 54111.1Skamil pid_t child, wpid; 54121.1Skamil#if defined(TWAIT_HAVE_STATUS) 54131.1Skamil int status; 54141.1Skamil#endif 54151.1Skamil 54161.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54171.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54181.1Skamil if (child == 0) { 54191.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54201.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54211.1Skamil 54221.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54231.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54241.1Skamil 54251.1Skamil /* NOTREACHED */ 54261.1Skamil FORKEE_ASSERTX(0 && 54271.1Skamil "Child should be terminated by a signal from its parent"); 54281.1Skamil } 54291.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54301.1Skamil 54311.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54321.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54331.1Skamil 54341.1Skamil validate_status_stopped(status, sigval); 54351.1Skamil 54361.75Skamil DPRINTF("Before killing the child process with %s\n", type); 54371.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 54381.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 54391.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 54401.75Skamil kill(child, SIGKILL); 54411.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 54421.75Skamil setpgid(child, 0); 54431.75Skamil killpg(getpgid(child), SIGKILL); 54441.75Skamil } 54451.1Skamil 54461.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54481.1Skamil 54491.75Skamil validate_status_signaled(status, SIGKILL, 0); 54501.1Skamil 54511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54521.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54531.1Skamil} 54541.1Skamil 54551.75Skamil#define PTRACE_KILL(test, type) \ 54561.75SkamilATF_TC(test); \ 54571.75SkamilATF_TC_HEAD(test, tc) \ 54581.75Skamil{ \ 54591.75Skamil atf_tc_set_md_var(tc, "descr", \ 54601.75Skamil "Verify killing the child with " type); \ 54611.75Skamil} \ 54621.75Skamil \ 54631.75SkamilATF_TC_BODY(test, tc) \ 54641.75Skamil{ \ 54651.75Skamil \ 54661.75Skamil ptrace_kill(type); \ 54671.1Skamil} 54681.1Skamil 54691.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 54701.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 54711.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 54721.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 54731.1Skamil 54741.75Skamil/// ---------------------------------------------------------------------------- 54751.1Skamil 54761.143Skamilstatic int lwpinfo_thread_sigmask[] = {SIGXCPU, SIGPIPE, SIGALRM, SIGURG}; 54771.143Skamil 54781.143Skamilstatic pthread_mutex_t lwpinfo_thread_mtx = PTHREAD_MUTEX_INITIALIZER; 54791.143Skamilstatic pthread_cond_t lwpinfo_thread_cnd = PTHREAD_COND_INITIALIZER; 54801.143Skamilstatic volatile size_t lwpinfo_thread_done; 54811.143Skamil 54821.143Skamilstatic void * 54831.143Skamillwpinfo_thread(void *arg) 54841.143Skamil{ 54851.143Skamil sigset_t s; 54861.143Skamil volatile void **tcb; 54871.143Skamil 54881.143Skamil tcb = (volatile void **)arg; 54891.143Skamil 54901.145Skamil *tcb = _lwp_getprivate(); 54911.143Skamil DPRINTF("Storing tcb[] = %p from thread %d\n", *tcb, _lwp_self()); 54921.143Skamil 54931.143Skamil pthread_setname_np(pthread_self(), "thread %d", 54941.143Skamil (void *)(intptr_t)_lwp_self()); 54951.143Skamil 54961.143Skamil sigemptyset(&s); 54971.143Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 54981.143Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 54991.143Skamil lwpinfo_thread_done++; 55001.143Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 55011.143Skamil pthread_cond_signal(&lwpinfo_thread_cnd); 55021.143Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 55031.143Skamil 55041.143Skamil return infinite_thread(NULL); 55051.143Skamil} 55061.143Skamil 55071.77Skamilstatic void 55081.143Skamiltraceme_lwpinfo(const size_t threads, const char *iter) 55091.1Skamil{ 55101.1Skamil const int sigval = SIGSTOP; 55111.77Skamil const int sigval2 = SIGINT; 55121.1Skamil pid_t child, wpid; 55131.1Skamil#if defined(TWAIT_HAVE_STATUS) 55141.1Skamil int status; 55151.1Skamil#endif 55161.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 55171.143Skamil struct ptrace_lwpstatus lwpstatus = {0}; 55181.77Skamil struct ptrace_siginfo info; 55191.143Skamil void *private; 55201.143Skamil char *name; 55211.143Skamil char namebuf[PL_LNAMELEN]; 55221.143Skamil volatile void *tcb[4]; 55231.143Skamil bool found; 55241.143Skamil sigset_t s; 55251.77Skamil 55261.77Skamil /* Maximum number of supported threads in this test */ 55271.143Skamil pthread_t t[__arraycount(tcb) - 1]; 55281.143Skamil size_t n, m; 55291.143Skamil int rv; 55301.143Skamil size_t bytes_read; 55311.143Skamil 55321.143Skamil struct ptrace_io_desc io; 55331.143Skamil sigset_t sigmask; 55341.77Skamil 55351.143Skamil ATF_REQUIRE(__arraycount(t) >= threads); 55361.143Skamil memset(tcb, 0, sizeof(tcb)); 55371.1Skamil 55381.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 55391.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 55401.1Skamil if (child == 0) { 55411.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 55421.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55431.1Skamil 55441.145Skamil tcb[0] = _lwp_getprivate(); 55451.143Skamil DPRINTF("Storing tcb[0] = %p\n", tcb[0]); 55461.143Skamil 55471.143Skamil pthread_setname_np(pthread_self(), "thread %d", 55481.143Skamil (void *)(intptr_t)_lwp_self()); 55491.143Skamil 55501.143Skamil sigemptyset(&s); 55511.143Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 55521.143Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 55531.143Skamil 55541.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 55551.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 55561.1Skamil 55571.77Skamil for (n = 0; n < threads; n++) { 55581.143Skamil rv = pthread_create(&t[n], NULL, lwpinfo_thread, 55591.143Skamil &tcb[n + 1]); 55601.77Skamil FORKEE_ASSERT(rv == 0); 55611.77Skamil } 55621.77Skamil 55631.143Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 55641.143Skamil while (lwpinfo_thread_done < threads) { 55651.143Skamil pthread_cond_wait(&lwpinfo_thread_cnd, 55661.143Skamil &lwpinfo_thread_mtx); 55671.143Skamil } 55681.143Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 55691.143Skamil 55701.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 55711.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 55721.77Skamil 55731.77Skamil /* NOTREACHED */ 55741.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 55751.1Skamil } 55761.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55771.1Skamil 55781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55801.1Skamil 55811.1Skamil validate_status_stopped(status, sigval); 55821.1Skamil 55831.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 55841.77Skamil SYSCALL_REQUIRE( 55851.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55861.77Skamil 55871.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55881.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55891.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55901.77Skamil info.psi_siginfo.si_errno); 55911.77Skamil 55921.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55931.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55941.77Skamil 55951.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 55961.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 55971.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 55981.143Skamil != -1); 55991.1Skamil 56001.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 56011.143Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 56021.1Skamil 56031.143Skamil DPRINTF("Assert that lwp thread %d received event " 56041.143Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 56051.143Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 56061.143Skamil 56071.143Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 56081.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPSTATUS " 56091.143Skamil "for child\n"); 56101.143Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 56111.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, &lwpstatus, 56121.143Skamil sizeof(lwpstatus)) != -1); 56131.143Skamil } 56141.1Skamil 56151.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 56161.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 56171.143Skamil != -1); 56181.1Skamil 56191.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 56201.143Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 56211.143Skamil } else { 56221.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 56231.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 56241.143Skamil sizeof(lwpstatus)) != -1); 56251.143Skamil 56261.143Skamil DPRINTF("Assert that there exists a single thread only %d\n", lwpstatus.pl_lwpid); 56271.143Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 56281.143Skamil 56291.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 56301.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 56311.143Skamil sizeof(lwpstatus)) != -1); 56321.143Skamil 56331.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 56341.143Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 56351.143Skamil } 56361.1Skamil 56371.13Schristos DPRINTF("Before resuming the child process where it left off and " 56381.1Skamil "without signal to be sent\n"); 56391.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56401.1Skamil 56411.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56431.1Skamil 56441.77Skamil validate_status_stopped(status, sigval2); 56451.77Skamil 56461.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 56471.77Skamil SYSCALL_REQUIRE( 56481.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56491.77Skamil 56501.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 56511.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 56521.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 56531.77Skamil info.psi_siginfo.si_errno); 56541.77Skamil 56551.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 56561.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 56571.77Skamil 56581.77Skamil memset(&lwp, 0, sizeof(lwp)); 56591.143Skamil memset(&lwpstatus, 0, sizeof(lwpstatus)); 56601.143Skamil 56611.143Skamil memset(&io, 0, sizeof(io)); 56621.143Skamil 56631.143Skamil bytes_read = 0; 56641.143Skamil io.piod_op = PIOD_READ_D; 56651.143Skamil io.piod_len = sizeof(tcb); 56661.143Skamil 56671.143Skamil do { 56681.143Skamil io.piod_addr = (char *)&tcb + bytes_read; 56691.143Skamil io.piod_offs = io.piod_addr; 56701.143Skamil 56711.143Skamil rv = ptrace(PT_IO, child, &io, sizeof(io)); 56721.143Skamil ATF_REQUIRE(rv != -1 && io.piod_len != 0); 56731.143Skamil 56741.143Skamil bytes_read += io.piod_len; 56751.143Skamil io.piod_len = sizeof(tcb) - bytes_read; 56761.143Skamil } while (bytes_read < sizeof(tcb)); 56771.77Skamil 56781.77Skamil for (n = 0; n <= threads; n++) { 56791.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 56801.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 56811.143Skamil "child\n"); 56821.143Skamil SYSCALL_REQUIRE( 56831.143Skamil ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 56841.143Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 56851.143Skamil 56861.143Skamil DPRINTF("Assert that the thread exists\n"); 56871.143Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 56881.143Skamil 56891.143Skamil DPRINTF("Assert that lwp thread %d received expected " 56901.143Skamil "event\n", lwp.pl_lwpid); 56911.143Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 56921.143Skamil info.psi_lwpid == lwp.pl_lwpid ? 56931.143Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 56941.143Skamil 56951.143Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 56961.143Skamil DPRINTF("Before calling ptrace(2) with " 56971.143Skamil "PT_LWPSTATUS for child\n"); 56981.143Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 56991.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, 57001.143Skamil &lwpstatus, sizeof(lwpstatus)) != -1); 57011.143Skamil 57021.143Skamil goto check_lwpstatus; 57031.143Skamil } 57041.143Skamil } else { 57051.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for " 57061.143Skamil "child\n"); 57071.143Skamil SYSCALL_REQUIRE( 57081.143Skamil ptrace(PT_LWPNEXT, child, &lwpstatus, 57091.143Skamil sizeof(lwpstatus)) != -1); 57101.143Skamil DPRINTF("LWP=%d\n", lwpstatus.pl_lwpid); 57111.143Skamil 57121.143Skamil DPRINTF("Assert that the thread exists\n"); 57131.143Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 57141.143Skamil 57151.143Skamil check_lwpstatus: 57161.143Skamil 57171.143Skamil if (strstr(iter, "pl_sigmask") != NULL) { 57181.143Skamil sigmask = lwpstatus.pl_sigmask; 57191.143Skamil 57201.143Skamil DPRINTF("Retrieved sigmask: " 57211.143Skamil "%02x%02x%02x%02x\n", 57221.143Skamil sigmask.__bits[0], sigmask.__bits[1], 57231.143Skamil sigmask.__bits[2], sigmask.__bits[3]); 57241.143Skamil 57251.143Skamil found = false; 57261.143Skamil for (m = 0; 57271.143Skamil m < __arraycount(lwpinfo_thread_sigmask); 57281.143Skamil m++) { 57291.143Skamil if (sigismember(&sigmask, 57301.143Skamil lwpinfo_thread_sigmask[m])) { 57311.143Skamil found = true; 57321.143Skamil lwpinfo_thread_sigmask[m] = 0; 57331.143Skamil break; 57341.143Skamil } 57351.143Skamil } 57361.143Skamil ATF_REQUIRE(found == true); 57371.143Skamil } else if (strstr(iter, "pl_name") != NULL) { 57381.143Skamil name = lwpstatus.pl_name; 57391.143Skamil 57401.143Skamil DPRINTF("Retrieved thread name: " 57411.143Skamil "%s\n", name); 57421.143Skamil 57431.143Skamil snprintf(namebuf, sizeof namebuf, "thread %d", 57441.143Skamil lwpstatus.pl_lwpid); 57451.143Skamil 57461.143Skamil ATF_REQUIRE(strcmp(name, namebuf) == 0); 57471.143Skamil } else if (strstr(iter, "pl_private") != NULL) { 57481.143Skamil private = lwpstatus.pl_private; 57491.143Skamil 57501.143Skamil DPRINTF("Retrieved thread private pointer: " 57511.143Skamil "%p\n", private); 57521.143Skamil 57531.143Skamil found = false; 57541.143Skamil for (m = 0; m < __arraycount(tcb); m++) { 57551.143Skamil DPRINTF("Comparing %p and %p\n", 57561.143Skamil private, tcb[m]); 57571.143Skamil if (private == tcb[m]) { 57581.143Skamil found = true; 57591.143Skamil break; 57601.143Skamil } 57611.143Skamil } 57621.143Skamil ATF_REQUIRE(found == true); 57631.143Skamil } 57641.143Skamil } 57651.143Skamil } 57661.143Skamil 57671.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 57681.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 57691.143Skamil "child\n"); 57701.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 57711.143Skamil != -1); 57721.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 57731.77Skamil 57741.143Skamil DPRINTF("Assert that there are no more threads\n"); 57751.143Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 57761.143Skamil } else { 57771.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 57781.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 57791.143Skamil sizeof(lwpstatus)) != -1); 57801.77Skamil 57811.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 57821.143Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 57831.143Skamil } 57841.77Skamil 57851.77Skamil DPRINTF("Before resuming the child process where it left off and " 57861.77Skamil "without signal to be sent\n"); 57871.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 57881.77Skamil 57891.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57901.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57911.77Skamil 57921.77Skamil validate_status_signaled(status, SIGKILL, 0); 57931.1Skamil 57941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57951.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57961.1Skamil} 57971.1Skamil 57981.143Skamil#define TRACEME_LWPINFO(test, threads, iter) \ 57991.77SkamilATF_TC(test); \ 58001.77SkamilATF_TC_HEAD(test, tc) \ 58011.77Skamil{ \ 58021.77Skamil atf_tc_set_md_var(tc, "descr", \ 58031.143Skamil "Verify " iter " with the child with " #threads \ 58041.77Skamil " spawned extra threads"); \ 58051.77Skamil} \ 58061.77Skamil \ 58071.77SkamilATF_TC_BODY(test, tc) \ 58081.77Skamil{ \ 58091.77Skamil \ 58101.143Skamil traceme_lwpinfo(threads, iter); \ 58111.1Skamil} 58121.1Skamil 58131.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0, "LWPINFO") 58141.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1, "LWPINFO") 58151.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2, "LWPINFO") 58161.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3, "LWPINFO") 58171.143Skamil 58181.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus, 0, "LWPINFO+LWPSTATUS") 58191.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus, 1, "LWPINFO+LWPSTATUS") 58201.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus, 2, "LWPINFO+LWPSTATUS") 58211.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus, 3, "LWPINFO+LWPSTATUS") 58221.143Skamil 58231.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_sigmask, 0, 58241.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58251.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_sigmask, 1, 58261.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58271.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_sigmask, 2, 58281.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58291.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_sigmask, 3, 58301.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58311.143Skamil 58321.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_name, 0, 58331.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58341.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_name, 1, 58351.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58361.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_name, 2, 58371.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58381.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_name, 3, 58391.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58401.143Skamil 58411.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_private, 0, 58421.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58431.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_private, 1, 58441.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58451.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_private, 2, 58461.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58471.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_private, 3, 58481.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58491.143Skamil 58501.143SkamilTRACEME_LWPINFO(traceme_lwpnext0, 0, "LWPNEXT") 58511.143SkamilTRACEME_LWPINFO(traceme_lwpnext1, 1, "LWPNEXT") 58521.143SkamilTRACEME_LWPINFO(traceme_lwpnext2, 2, "LWPNEXT") 58531.143SkamilTRACEME_LWPINFO(traceme_lwpnext3, 3, "LWPNEXT") 58541.143Skamil 58551.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_sigmask, 0, "LWPNEXT+pl_sigmask") 58561.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_sigmask, 1, "LWPNEXT+pl_sigmask") 58571.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_sigmask, 2, "LWPNEXT+pl_sigmask") 58581.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_sigmask, 3, "LWPNEXT+pl_sigmask") 58591.143Skamil 58601.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_name, 0, "LWPNEXT+pl_name") 58611.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_name, 1, "LWPNEXT+pl_name") 58621.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_name, 2, "LWPNEXT+pl_name") 58631.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_name, 3, "LWPNEXT+pl_name") 58641.143Skamil 58651.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_private, 0, "LWPNEXT+pl_private") 58661.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_private, 1, "LWPNEXT+pl_private") 58671.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_private, 2, "LWPNEXT+pl_private") 58681.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_private, 3, "LWPNEXT+pl_private") 58691.77Skamil 58701.77Skamil/// ---------------------------------------------------------------------------- 58711.77Skamil 58721.77Skamil#if defined(TWAIT_HAVE_PID) 58731.77Skamilstatic void 58741.77Skamilattach_lwpinfo(const int threads) 58751.1Skamil{ 58761.77Skamil const int sigval = SIGINT; 58771.1Skamil struct msg_fds parent_tracee, parent_tracer; 58781.1Skamil const int exitval_tracer = 10; 58791.1Skamil pid_t tracee, tracer, wpid; 58801.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 58811.1Skamil#if defined(TWAIT_HAVE_STATUS) 58821.1Skamil int status; 58831.1Skamil#endif 58841.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 58851.77Skamil struct ptrace_siginfo info; 58861.77Skamil 58871.77Skamil /* Maximum number of supported threads in this test */ 58881.77Skamil pthread_t t[3]; 58891.77Skamil int n, rv; 58901.1Skamil 58911.13Schristos DPRINTF("Spawn tracee\n"); 58921.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 58931.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 58941.1Skamil tracee = atf_utils_fork(); 58951.1Skamil if (tracee == 0) { 58961.1Skamil /* Wait for message from the parent */ 58971.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 58981.1Skamil 58991.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 59001.77Skamil 59011.77Skamil for (n = 0; n < threads; n++) { 59021.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 59031.77Skamil FORKEE_ASSERT(rv == 0); 59041.77Skamil } 59051.77Skamil 59061.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 59071.77Skamil 59081.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 59091.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 59101.77Skamil 59111.77Skamil /* NOTREACHED */ 59121.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 59131.1Skamil } 59141.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 59151.1Skamil 59161.13Schristos DPRINTF("Spawn debugger\n"); 59171.1Skamil tracer = atf_utils_fork(); 59181.1Skamil if (tracer == 0) { 59191.1Skamil /* No IPC to communicate with the child */ 59201.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 59211.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 59221.1Skamil 59231.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 59241.1Skamil FORKEE_REQUIRE_SUCCESS( 59251.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 59261.1Skamil 59271.1Skamil forkee_status_stopped(status, SIGSTOP); 59281.1Skamil 59291.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 59301.77Skamil "tracee"); 59311.77Skamil FORKEE_ASSERT( 59321.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 59331.77Skamil 59341.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 59351.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 59361.77Skamil "si_errno=%#x\n", 59371.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 59381.77Skamil info.psi_siginfo.si_errno); 59391.77Skamil 59401.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 59411.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 59421.77Skamil 59431.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 59441.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 59451.1Skamil != -1); 59461.1Skamil 59471.13Schristos DPRINTF("Assert that there exists a thread\n"); 59481.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 59491.1Skamil 59501.13Schristos DPRINTF("Assert that lwp thread %d received event " 59511.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 59521.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 59531.1Skamil 59541.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 59551.77Skamil "tracee\n"); 59561.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 59571.1Skamil != -1); 59581.1Skamil 59591.77Skamil DPRINTF("Assert that there are no more lwp threads in " 59601.77Skamil "tracee\n"); 59611.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 59621.1Skamil 59631.1Skamil /* Resume tracee with PT_CONTINUE */ 59641.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 59651.1Skamil 59661.1Skamil /* Inform parent that tracer has attached to tracee */ 59671.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 59681.77Skamil 59691.1Skamil /* Wait for parent */ 59701.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 59711.1Skamil 59721.77Skamil /* Wait for tracee and assert that it raised a signal */ 59731.77Skamil FORKEE_REQUIRE_SUCCESS( 59741.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 59751.77Skamil 59761.77Skamil forkee_status_stopped(status, SIGINT); 59771.77Skamil 59781.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 59791.77Skamil "child"); 59801.77Skamil FORKEE_ASSERT( 59811.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 59821.77Skamil 59831.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 59841.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 59851.77Skamil "si_errno=%#x\n", 59861.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 59871.77Skamil info.psi_siginfo.si_errno); 59881.77Skamil 59891.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 59901.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 59911.77Skamil 59921.77Skamil memset(&lwp, 0, sizeof(lwp)); 59931.77Skamil 59941.77Skamil for (n = 0; n <= threads; n++) { 59951.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 59961.77Skamil "child\n"); 59971.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 59981.77Skamil sizeof(lwp)) != -1); 59991.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 60001.77Skamil 60011.77Skamil DPRINTF("Assert that the thread exists\n"); 60021.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 60031.77Skamil 60041.77Skamil DPRINTF("Assert that lwp thread %d received expected " 60051.77Skamil "event\n", lwp.pl_lwpid); 60061.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 60071.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 60081.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 60091.77Skamil } 60101.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 60111.77Skamil "tracee\n"); 60121.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 60131.77Skamil != -1); 60141.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 60151.77Skamil 60161.77Skamil DPRINTF("Assert that there are no more threads\n"); 60171.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 60181.77Skamil 60191.77Skamil DPRINTF("Before resuming the child process where it left off " 60201.77Skamil "and without signal to be sent\n"); 60211.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 60221.77Skamil != -1); 60231.77Skamil 60241.1Skamil /* Wait for tracee and assert that it exited */ 60251.1Skamil FORKEE_REQUIRE_SUCCESS( 60261.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 60271.1Skamil 60281.77Skamil forkee_status_signaled(status, SIGKILL, 0); 60291.1Skamil 60301.13Schristos DPRINTF("Before exiting of the tracer process\n"); 60311.1Skamil _exit(exitval_tracer); 60321.1Skamil } 60331.1Skamil 60341.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 60351.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 60361.1Skamil 60371.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 60381.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 60391.77Skamil 60401.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 60411.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 60421.1Skamil 60431.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 60441.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 60451.1Skamil 60461.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 60471.1Skamil TWAIT_FNAME); 60481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 60491.1Skamil tracer); 60501.1Skamil 60511.1Skamil validate_status_exited(status, exitval_tracer); 60521.1Skamil 60531.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 60541.1Skamil TWAIT_FNAME); 60551.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 60561.1Skamil tracee); 60571.1Skamil 60581.77Skamil validate_status_signaled(status, SIGKILL, 0); 60591.1Skamil 60601.1Skamil msg_close(&parent_tracer); 60611.1Skamil msg_close(&parent_tracee); 60621.1Skamil} 60631.77Skamil 60641.77Skamil#define ATTACH_LWPINFO(test, threads) \ 60651.77SkamilATF_TC(test); \ 60661.77SkamilATF_TC_HEAD(test, tc) \ 60671.77Skamil{ \ 60681.77Skamil atf_tc_set_md_var(tc, "descr", \ 60691.77Skamil "Verify LWPINFO with the child with " #threads \ 60701.77Skamil " spawned extra threads (tracer is not the original " \ 60711.77Skamil "parent)"); \ 60721.77Skamil} \ 60731.77Skamil \ 60741.77SkamilATF_TC_BODY(test, tc) \ 60751.77Skamil{ \ 60761.77Skamil \ 60771.77Skamil attach_lwpinfo(threads); \ 60781.77Skamil} 60791.77Skamil 60801.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 60811.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 60821.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 60831.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 60841.1Skamil#endif 60851.1Skamil 60861.77Skamil/// ---------------------------------------------------------------------------- 60871.77Skamil 60881.1Skamilstatic void 60891.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 60901.1Skamil{ 60911.1Skamil const int exitval = 5; 60921.1Skamil const int sigval = SIGINT; 60931.1Skamil const int sigfaked = SIGTRAP; 60941.1Skamil const int sicodefaked = TRAP_BRKPT; 60951.1Skamil pid_t child, wpid; 60961.1Skamil struct sigaction sa; 60971.1Skamil#if defined(TWAIT_HAVE_STATUS) 60981.1Skamil int status; 60991.1Skamil#endif 61001.1Skamil struct ptrace_siginfo info; 61011.1Skamil memset(&info, 0, sizeof(info)); 61021.1Skamil 61031.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61041.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61051.1Skamil if (child == 0) { 61061.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61071.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61081.1Skamil 61091.79Skamil sa.sa_sigaction = sah; 61101.1Skamil sa.sa_flags = SA_SIGINFO; 61111.1Skamil sigemptyset(&sa.sa_mask); 61121.1Skamil 61131.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 61141.79Skamil != -1); 61151.1Skamil 61161.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61171.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61181.1Skamil 61191.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 61201.1Skamil 61211.13Schristos DPRINTF("Before exiting of the child process\n"); 61221.1Skamil _exit(exitval); 61231.1Skamil } 61241.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61251.1Skamil 61261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61281.1Skamil 61291.1Skamil validate_status_stopped(status, sigval); 61301.1Skamil 61311.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 61321.61Skre SYSCALL_REQUIRE( 61331.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 61341.1Skamil 61351.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 61361.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 61371.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 61381.1Skamil info.psi_siginfo.si_errno); 61391.1Skamil 61401.79Skamil if (faked) { 61411.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 61421.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 61431.79Skamil info.psi_siginfo.si_signo = sigfaked; 61441.79Skamil info.psi_siginfo.si_code = sicodefaked; 61451.79Skamil } 61461.1Skamil 61471.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 61481.61Skre SYSCALL_REQUIRE( 61491.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 61501.1Skamil 61511.79Skamil if (faked) { 61521.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 61531.79Skamil "child\n"); 61541.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 61551.79Skamil sizeof(info)) != -1); 61561.1Skamil 61571.79Skamil DPRINTF("Before checking siginfo_t\n"); 61581.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 61591.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 61601.79Skamil } 61611.1Skamil 61621.13Schristos DPRINTF("Before resuming the child process where it left off and " 61631.1Skamil "without signal to be sent\n"); 61641.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 61651.79Skamil faked ? sigfaked : sigval) != -1); 61661.1Skamil 61671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61691.1Skamil 61701.1Skamil validate_status_exited(status, exitval); 61711.1Skamil 61721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61731.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 61741.1Skamil} 61751.1Skamil 61761.79Skamil#define PTRACE_SIGINFO(test, faked) \ 61771.79SkamilATF_TC(test); \ 61781.79SkamilATF_TC_HEAD(test, tc) \ 61791.79Skamil{ \ 61801.79Skamil atf_tc_set_md_var(tc, "descr", \ 61811.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 61821.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 61831.79Skamil} \ 61841.79Skamil \ 61851.79Skamilstatic int test##_caught = 0; \ 61861.79Skamil \ 61871.79Skamilstatic void \ 61881.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 61891.79Skamil{ \ 61901.79Skamil if (faked) { \ 61911.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 61921.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 61931.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 61941.79Skamil } else { \ 61951.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 61961.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 61971.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 61981.79Skamil } \ 61991.79Skamil \ 62001.79Skamil ++ test##_caught; \ 62011.79Skamil} \ 62021.79Skamil \ 62031.79SkamilATF_TC_BODY(test, tc) \ 62041.79Skamil{ \ 62051.79Skamil \ 62061.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 62071.79Skamil} 62081.79Skamil 62091.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 62101.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 62111.79Skamil 62121.79Skamil/// ---------------------------------------------------------------------------- 62131.79Skamil 62141.97Skamilstatic void 62151.97Skamiltraceme_exec(bool masked, bool ignored) 62161.1Skamil{ 62171.1Skamil const int sigval = SIGTRAP; 62181.1Skamil pid_t child, wpid; 62191.1Skamil#if defined(TWAIT_HAVE_STATUS) 62201.1Skamil int status; 62211.1Skamil#endif 62221.97Skamil struct sigaction sa; 62231.97Skamil struct ptrace_siginfo info; 62241.97Skamil sigset_t intmask; 62251.97Skamil struct kinfo_proc2 kp; 62261.97Skamil size_t len = sizeof(kp); 62271.97Skamil 62281.97Skamil int name[6]; 62291.97Skamil const size_t namelen = __arraycount(name); 62301.97Skamil ki_sigset_t kp_sigmask; 62311.97Skamil ki_sigset_t kp_sigignore; 62321.1Skamil 62331.1Skamil memset(&info, 0, sizeof(info)); 62341.1Skamil 62351.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62361.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62371.1Skamil if (child == 0) { 62381.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62391.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62401.1Skamil 62411.97Skamil if (masked) { 62421.97Skamil sigemptyset(&intmask); 62431.97Skamil sigaddset(&intmask, sigval); 62441.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62451.97Skamil } 62461.97Skamil 62471.97Skamil if (ignored) { 62481.97Skamil memset(&sa, 0, sizeof(sa)); 62491.97Skamil sa.sa_handler = SIG_IGN; 62501.97Skamil sigemptyset(&sa.sa_mask); 62511.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 62521.97Skamil } 62531.97Skamil 62541.13Schristos DPRINTF("Before calling execve(2) from child\n"); 62551.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 62561.1Skamil 62571.1Skamil FORKEE_ASSERT(0 && "Not reached"); 62581.1Skamil } 62591.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62601.1Skamil 62611.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62621.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62631.1Skamil 62641.1Skamil validate_status_stopped(status, sigval); 62651.1Skamil 62661.97Skamil name[0] = CTL_KERN, 62671.97Skamil name[1] = KERN_PROC2, 62681.97Skamil name[2] = KERN_PROC_PID; 62691.97Skamil name[3] = getpid(); 62701.97Skamil name[4] = sizeof(kp); 62711.97Skamil name[5] = 1; 62721.97Skamil 62731.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 62741.97Skamil 62751.97Skamil if (masked) 62761.97Skamil kp_sigmask = kp.p_sigmask; 62771.97Skamil 62781.97Skamil if (ignored) 62791.97Skamil kp_sigignore = kp.p_sigignore; 62801.97Skamil 62811.97Skamil name[3] = getpid(); 62821.97Skamil 62831.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 62841.97Skamil 62851.97Skamil if (masked) { 62861.97Skamil DPRINTF("kp_sigmask=" 62871.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 62881.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 62891.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 62901.97Skamil 62911.97Skamil DPRINTF("kp.p_sigmask=" 62921.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 62931.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 62941.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 62951.97Skamil 62961.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 62971.97Skamil sizeof(kp_sigmask))); 62981.97Skamil } 62991.97Skamil 63001.97Skamil if (ignored) { 63011.97Skamil DPRINTF("kp_sigignore=" 63021.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 63031.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 63041.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 63051.97Skamil 63061.97Skamil DPRINTF("kp.p_sigignore=" 63071.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 63081.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 63091.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 63101.97Skamil 63111.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 63121.97Skamil sizeof(kp_sigignore))); 63131.97Skamil } 63141.97Skamil 63151.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 63161.61Skre SYSCALL_REQUIRE( 63171.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 63181.1Skamil 63191.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 63201.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 63211.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 63221.1Skamil info.psi_siginfo.si_errno); 63231.1Skamil 63241.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 63251.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 63261.1Skamil 63271.13Schristos DPRINTF("Before resuming the child process where it left off and " 63281.1Skamil "without signal to be sent\n"); 63291.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63301.1Skamil 63311.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63321.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63331.1Skamil 63341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63351.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63361.1Skamil} 63371.1Skamil 63381.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 63391.97SkamilATF_TC(test); \ 63401.97SkamilATF_TC_HEAD(test, tc) \ 63411.97Skamil{ \ 63421.97Skamil atf_tc_set_md_var(tc, "descr", \ 63431.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 63441.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 63451.97Skamil masked ? " with ignored signal" : ""); \ 63461.97Skamil} \ 63471.97Skamil \ 63481.97SkamilATF_TC_BODY(test, tc) \ 63491.97Skamil{ \ 63501.97Skamil \ 63511.97Skamil traceme_exec(masked, ignored); \ 63521.97Skamil} 63531.97Skamil 63541.97SkamilTRACEME_EXEC(traceme_exec, false, false) 63551.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 63561.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 63571.97Skamil 63581.82Skamil/// ---------------------------------------------------------------------------- 63591.82Skamil 63601.135Skamil#define TRACE_THREADS_NUM 100 63611.135Skamil 63621.83Skamilstatic volatile int done; 63631.137Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER; 63641.1Skamil 63651.83Skamilstatic void * 63661.83Skamiltrace_threads_cb(void *arg __unused) 63671.1Skamil{ 63681.1Skamil 63691.137Skamil pthread_mutex_lock(&trace_threads_mtx); 63701.83Skamil done++; 63711.137Skamil pthread_mutex_unlock(&trace_threads_mtx); 63721.83Skamil 63731.135Skamil while (done < TRACE_THREADS_NUM) 63741.135Skamil sched_yield(); 63751.83Skamil 63761.83Skamil return NULL; 63771.1Skamil} 63781.1Skamil 63791.83Skamilstatic void 63801.153Skamiltrace_threads(bool trace_create, bool trace_exit, bool masked) 63811.1Skamil{ 63821.1Skamil const int sigval = SIGSTOP; 63831.1Skamil pid_t child, wpid; 63841.1Skamil#if defined(TWAIT_HAVE_STATUS) 63851.1Skamil int status; 63861.1Skamil#endif 63871.1Skamil ptrace_state_t state; 63881.1Skamil const int slen = sizeof(state); 63891.1Skamil ptrace_event_t event; 63901.1Skamil const int elen = sizeof(event); 63911.83Skamil struct ptrace_siginfo info; 63921.83Skamil 63931.153Skamil sigset_t intmask; 63941.153Skamil 63951.135Skamil pthread_t t[TRACE_THREADS_NUM]; 63961.83Skamil int rv; 63971.83Skamil size_t n; 63981.1Skamil lwpid_t lid; 63991.83Skamil 64001.83Skamil /* Track created and exited threads */ 64011.141Skamil struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}}; 64021.83Skamil 64031.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64041.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64051.1Skamil if (child == 0) { 64061.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64071.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64081.1Skamil 64091.153Skamil if (masked) { 64101.153Skamil sigemptyset(&intmask); 64111.153Skamil sigaddset(&intmask, SIGTRAP); 64121.153Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 64131.153Skamil } 64141.153Skamil 64151.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64161.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64171.1Skamil 64181.83Skamil for (n = 0; n < __arraycount(t); n++) { 64191.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 64201.83Skamil NULL); 64211.83Skamil FORKEE_ASSERT(rv == 0); 64221.83Skamil } 64231.1Skamil 64241.83Skamil for (n = 0; n < __arraycount(t); n++) { 64251.83Skamil rv = pthread_join(t[n], NULL); 64261.83Skamil FORKEE_ASSERT(rv == 0); 64271.83Skamil } 64281.1Skamil 64291.83Skamil /* 64301.83Skamil * There is race between _exit() and pthread_join() detaching 64311.83Skamil * a thread. For simplicity kill the process after detecting 64321.83Skamil * LWP events. 64331.83Skamil */ 64341.83Skamil while (true) 64351.83Skamil continue; 64361.1Skamil 64371.83Skamil FORKEE_ASSERT(0 && "Not reached"); 64381.1Skamil } 64391.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64401.1Skamil 64411.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64431.1Skamil 64441.1Skamil validate_status_stopped(status, sigval); 64451.1Skamil 64461.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 64471.83Skamil SYSCALL_REQUIRE( 64481.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 64491.1Skamil 64501.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 64511.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 64521.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 64531.83Skamil info.psi_siginfo.si_errno); 64541.1Skamil 64551.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 64561.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 64571.1Skamil 64581.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 64591.83Skamil memset(&event, 0, sizeof(event)); 64601.83Skamil if (trace_create) 64611.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 64621.83Skamil if (trace_exit) 64631.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 64641.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 64651.1Skamil 64661.13Schristos DPRINTF("Before resuming the child process where it left off and " 64671.1Skamil "without signal to be sent\n"); 64681.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64691.1Skamil 64701.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 64711.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 64721.83Skamil "SIGTRAP\n", TWAIT_FNAME); 64731.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 64741.83Skamil child); 64751.1Skamil 64761.83Skamil validate_status_stopped(status, SIGTRAP); 64771.1Skamil 64781.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 64791.83Skamil "child\n"); 64801.83Skamil SYSCALL_REQUIRE( 64811.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 64821.1Skamil 64831.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 64841.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 64851.83Skamil "si_errno=%#x\n", 64861.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 64871.83Skamil info.psi_siginfo.si_errno); 64881.1Skamil 64891.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 64901.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 64911.1Skamil 64921.83Skamil SYSCALL_REQUIRE( 64931.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 64941.1Skamil 64951.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 64961.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 64971.1Skamil 64981.83Skamil lid = state.pe_lwp; 64991.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 65001.1Skamil 65011.141Skamil *FIND_EVENT_COUNT(traced_lwps, lid) += 1; 65021.1Skamil 65031.83Skamil DPRINTF("Before resuming the child process where it left off " 65041.83Skamil "and without signal to be sent\n"); 65051.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65061.83Skamil } 65071.1Skamil 65081.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 65091.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 65101.83Skamil "SIGTRAP\n", TWAIT_FNAME); 65111.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 65121.83Skamil child); 65131.1Skamil 65141.83Skamil validate_status_stopped(status, SIGTRAP); 65151.1Skamil 65161.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 65171.83Skamil "child\n"); 65181.83Skamil SYSCALL_REQUIRE( 65191.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 65201.1Skamil 65211.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 65221.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 65231.83Skamil "si_errno=%#x\n", 65241.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 65251.83Skamil info.psi_siginfo.si_errno); 65261.1Skamil 65271.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 65281.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 65291.1Skamil 65301.83Skamil SYSCALL_REQUIRE( 65311.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 65321.1Skamil 65331.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 65341.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 65351.1Skamil 65361.83Skamil lid = state.pe_lwp; 65371.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 65381.1Skamil 65391.83Skamil if (trace_create) { 65401.141Skamil int *count = FIND_EVENT_COUNT(traced_lwps, lid); 65411.141Skamil ATF_REQUIRE_EQ(*count, 1); 65421.141Skamil *count = 0; 65431.83Skamil } 65441.1Skamil 65451.83Skamil DPRINTF("Before resuming the child process where it left off " 65461.83Skamil "and without signal to be sent\n"); 65471.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65481.83Skamil } 65491.1Skamil 65501.83Skamil kill(child, SIGKILL); 65511.1Skamil 65521.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65531.1Skamil TWAIT_FNAME); 65541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65551.1Skamil 65561.83Skamil validate_status_signaled(status, SIGKILL, 0); 65571.1Skamil 65581.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65591.1Skamil TWAIT_FNAME); 65601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65611.1Skamil} 65621.1Skamil 65631.153Skamil#define TRACE_THREADS(test, trace_create, trace_exit, mask) \ 65641.83SkamilATF_TC(test); \ 65651.83SkamilATF_TC_HEAD(test, tc) \ 65661.83Skamil{ \ 65671.83Skamil atf_tc_set_md_var(tc, "descr", \ 65681.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 65691.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 65701.83Skamil trace_exit ? "" : "out"); \ 65711.83Skamil} \ 65721.83Skamil \ 65731.83SkamilATF_TC_BODY(test, tc) \ 65741.83Skamil{ \ 65751.83Skamil \ 65761.153Skamil trace_threads(trace_create, trace_exit, mask); \ 65771.83Skamil} 65781.83Skamil 65791.153SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false, false) 65801.153SkamilTRACE_THREADS(trace_thread_lwpexit, false, true, false) 65811.153SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false, false) 65821.153SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true, false) 65831.153Skamil 65841.153SkamilTRACE_THREADS(trace_thread_lwpexit_masked_sigtrap, false, true, true) 65851.153SkamilTRACE_THREADS(trace_thread_lwpcreate_masked_sigtrap, true, false, true) 65861.153SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit_masked_sigtrap, true, true, true) 65871.83Skamil 65881.83Skamil/// ---------------------------------------------------------------------------- 65891.83Skamil 65901.84SkamilATF_TC(signal_mask_unrelated); 65911.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 65921.1Skamil{ 65931.1Skamil atf_tc_set_md_var(tc, "descr", 65941.1Skamil "Verify that masking single unrelated signal does not stop tracer " 65951.1Skamil "from catching other signals"); 65961.1Skamil} 65971.1Skamil 65981.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 65991.1Skamil{ 66001.1Skamil const int exitval = 5; 66011.1Skamil const int sigval = SIGSTOP; 66021.1Skamil const int sigmasked = SIGTRAP; 66031.1Skamil const int signotmasked = SIGINT; 66041.1Skamil pid_t child, wpid; 66051.1Skamil#if defined(TWAIT_HAVE_STATUS) 66061.1Skamil int status; 66071.1Skamil#endif 66081.1Skamil sigset_t intmask; 66091.1Skamil 66101.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66111.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66121.1Skamil if (child == 0) { 66131.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66141.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66151.1Skamil 66161.1Skamil sigemptyset(&intmask); 66171.1Skamil sigaddset(&intmask, sigmasked); 66181.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 66191.1Skamil 66201.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66211.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66221.1Skamil 66231.13Schristos DPRINTF("Before raising %s from child\n", 66241.1Skamil strsignal(signotmasked)); 66251.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 66261.1Skamil 66271.13Schristos DPRINTF("Before exiting of the child process\n"); 66281.1Skamil _exit(exitval); 66291.1Skamil } 66301.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66311.1Skamil 66321.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66331.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66341.1Skamil 66351.1Skamil validate_status_stopped(status, sigval); 66361.1Skamil 66371.13Schristos DPRINTF("Before resuming the child process where it left off and " 66381.1Skamil "without signal to be sent\n"); 66391.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66401.1Skamil 66411.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66431.1Skamil 66441.1Skamil validate_status_stopped(status, signotmasked); 66451.1Skamil 66461.13Schristos DPRINTF("Before resuming the child process where it left off and " 66471.1Skamil "without signal to be sent\n"); 66481.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66491.1Skamil 66501.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66511.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66521.1Skamil 66531.1Skamil validate_status_exited(status, exitval); 66541.1Skamil 66551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66561.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66571.1Skamil} 66581.1Skamil 66591.84Skamil/// ---------------------------------------------------------------------------- 66601.84Skamil 66611.1Skamil#if defined(TWAIT_HAVE_PID) 66621.99Skamilstatic void 66631.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 66641.1Skamil{ 66651.1Skamil const int exitval = 5; 66661.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 66671.1Skamil const int sigval = SIGSTOP; 66681.99Skamil pid_t child, child2 = 0, wpid; 66691.1Skamil#if defined(TWAIT_HAVE_STATUS) 66701.1Skamil int status; 66711.1Skamil#endif 66721.1Skamil ptrace_state_t state; 66731.1Skamil const int slen = sizeof(state); 66741.1Skamil ptrace_event_t event; 66751.1Skamil const int elen = sizeof(event); 66761.99Skamil struct sigaction sa; 66771.99Skamil struct ptrace_siginfo info; 66781.99Skamil sigset_t intmask; 66791.99Skamil struct kinfo_proc2 kp; 66801.99Skamil size_t len = sizeof(kp); 66811.99Skamil 66821.99Skamil int name[6]; 66831.99Skamil const size_t namelen = __arraycount(name); 66841.99Skamil ki_sigset_t kp_sigmask; 66851.99Skamil ki_sigset_t kp_sigignore; 66861.1Skamil 66871.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 66881.14Schristos 66891.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66901.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66911.1Skamil if (child == 0) { 66921.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66931.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66941.1Skamil 66951.99Skamil if (masked) { 66961.99Skamil sigemptyset(&intmask); 66971.99Skamil sigaddset(&intmask, SIGTRAP); 66981.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 66991.99Skamil } 67001.99Skamil 67011.99Skamil if (ignored) { 67021.99Skamil memset(&sa, 0, sizeof(sa)); 67031.99Skamil sa.sa_handler = SIG_IGN; 67041.99Skamil sigemptyset(&sa.sa_mask); 67051.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 67061.99Skamil } 67071.1Skamil 67081.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67091.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67101.1Skamil 67111.126Skamil if (strcmp(fn, "spawn") == 0) { 67121.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 67131.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 67141.126Skamil } else { 67151.126Skamil if (strcmp(fn, "fork") == 0) { 67161.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 67171.126Skamil } else { 67181.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 67191.126Skamil } 67201.126Skamil if (child2 == 0) 67211.126Skamil _exit(exitval2); 67221.126Skamil } 67231.1Skamil 67241.1Skamil FORKEE_REQUIRE_SUCCESS 67251.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 67261.1Skamil 67271.1Skamil forkee_status_exited(status, exitval2); 67281.1Skamil 67291.13Schristos DPRINTF("Before exiting of the child process\n"); 67301.1Skamil _exit(exitval); 67311.1Skamil } 67321.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67331.1Skamil 67341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67361.1Skamil 67371.1Skamil validate_status_stopped(status, sigval); 67381.1Skamil 67391.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67401.99Skamil SYSCALL_REQUIRE( 67411.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67421.99Skamil 67431.99Skamil DPRINTF("Before checking siginfo_t\n"); 67441.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 67451.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 67461.1Skamil 67471.99Skamil name[0] = CTL_KERN, 67481.99Skamil name[1] = KERN_PROC2, 67491.99Skamil name[2] = KERN_PROC_PID; 67501.99Skamil name[3] = child; 67511.99Skamil name[4] = sizeof(kp); 67521.99Skamil name[5] = 1; 67531.1Skamil 67541.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 67551.1Skamil 67561.99Skamil if (masked) 67571.99Skamil kp_sigmask = kp.p_sigmask; 67581.1Skamil 67591.99Skamil if (ignored) 67601.99Skamil kp_sigignore = kp.p_sigignore; 67611.1Skamil 67621.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 67631.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 67641.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 67651.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 67661.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 67671.99Skamil event.pe_set_event = 0; 67681.126Skamil if (strcmp(fn, "spawn") == 0) 67691.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 67701.126Skamil if (strcmp(fn, "fork") == 0) 67711.99Skamil event.pe_set_event |= PTRACE_FORK; 67721.126Skamil if (strcmp(fn, "vfork") == 0) 67731.99Skamil event.pe_set_event |= PTRACE_VFORK; 67741.126Skamil if (strcmp(fn, "vforkdone") == 0) 67751.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 67761.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 67771.1Skamil 67781.99Skamil DPRINTF("Before resuming the child process where it left off and " 67791.99Skamil "without signal to be sent\n"); 67801.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67811.1Skamil 67821.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 67831.126Skamil strcmp(fn, "vfork") == 0) { 67841.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 67851.99Skamil child); 67861.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 67871.99Skamil child); 67881.1Skamil 67891.99Skamil validate_status_stopped(status, SIGTRAP); 67901.1Skamil 67911.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 67921.1Skamil 67931.99Skamil if (masked) { 67941.99Skamil DPRINTF("kp_sigmask=" 67951.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 67961.99Skamil PRIx32 "\n", 67971.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 67981.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 67991.1Skamil 68001.99Skamil DPRINTF("kp.p_sigmask=" 68011.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68021.99Skamil PRIx32 "\n", 68031.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 68041.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 68051.1Skamil 68061.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 68071.99Skamil sizeof(kp_sigmask))); 68081.99Skamil } 68091.1Skamil 68101.99Skamil if (ignored) { 68111.99Skamil DPRINTF("kp_sigignore=" 68121.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68131.99Skamil PRIx32 "\n", 68141.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 68151.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 68161.1Skamil 68171.99Skamil DPRINTF("kp.p_sigignore=" 68181.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68191.99Skamil PRIx32 "\n", 68201.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 68211.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 68221.1Skamil 68231.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 68241.99Skamil sizeof(kp_sigignore))); 68251.99Skamil } 68261.1Skamil 68271.99Skamil SYSCALL_REQUIRE( 68281.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68291.126Skamil if (strcmp(fn, "spawn") == 0) { 68301.126Skamil ATF_REQUIRE_EQ( 68311.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 68321.126Skamil PTRACE_POSIX_SPAWN); 68331.126Skamil } 68341.126Skamil if (strcmp(fn, "fork") == 0) { 68351.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68361.99Skamil PTRACE_FORK); 68371.99Skamil } 68381.126Skamil if (strcmp(fn, "vfork") == 0) { 68391.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68401.99Skamil PTRACE_VFORK); 68411.99Skamil } 68421.1Skamil 68431.99Skamil child2 = state.pe_other_pid; 68441.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 68451.1Skamil 68461.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 68471.99Skamil "%d\n", TWAIT_FNAME, child2, child); 68481.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 68491.99Skamil child2); 68501.1Skamil 68511.99Skamil validate_status_stopped(status, SIGTRAP); 68521.1Skamil 68531.99Skamil name[3] = child2; 68541.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 68551.1Skamil 68561.99Skamil if (masked) { 68571.99Skamil DPRINTF("kp_sigmask=" 68581.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68591.99Skamil PRIx32 "\n", 68601.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 68611.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 68621.1Skamil 68631.99Skamil DPRINTF("kp.p_sigmask=" 68641.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68651.99Skamil PRIx32 "\n", 68661.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 68671.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 68681.14Schristos 68691.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 68701.99Skamil sizeof(kp_sigmask))); 68711.99Skamil } 68721.1Skamil 68731.99Skamil if (ignored) { 68741.99Skamil DPRINTF("kp_sigignore=" 68751.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68761.99Skamil PRIx32 "\n", 68771.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 68781.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 68791.1Skamil 68801.99Skamil DPRINTF("kp.p_sigignore=" 68811.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68821.99Skamil PRIx32 "\n", 68831.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 68841.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 68851.1Skamil 68861.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 68871.99Skamil sizeof(kp_sigignore))); 68881.99Skamil } 68891.1Skamil 68901.99Skamil SYSCALL_REQUIRE( 68911.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 68921.126Skamil if (strcmp(fn, "spawn") == 0) { 68931.126Skamil ATF_REQUIRE_EQ( 68941.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 68951.126Skamil PTRACE_POSIX_SPAWN); 68961.126Skamil } 68971.126Skamil if (strcmp(fn, "fork") == 0) { 68981.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68991.99Skamil PTRACE_FORK); 69001.99Skamil } 69011.126Skamil if (strcmp(fn, "vfork") == 0) { 69021.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69031.99Skamil PTRACE_VFORK); 69041.99Skamil } 69051.1Skamil 69061.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 69071.1Skamil 69081.99Skamil DPRINTF("Before resuming the forkee process where it left off " 69091.99Skamil "and without signal to be sent\n"); 69101.99Skamil SYSCALL_REQUIRE( 69111.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 69121.1Skamil 69131.99Skamil DPRINTF("Before resuming the child process where it left off " 69141.99Skamil "and without signal to be sent\n"); 69151.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69161.1Skamil } 69171.1Skamil 69181.126Skamil if (strcmp(fn, "vforkdone") == 0) { 69191.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69201.99Skamil child); 69211.99Skamil TWAIT_REQUIRE_SUCCESS( 69221.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 69231.1Skamil 69241.99Skamil validate_status_stopped(status, SIGTRAP); 69251.1Skamil 69261.99Skamil name[3] = child; 69271.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 69281.1Skamil 69291.102Skamil /* 69301.102Skamil * SIGCHLD is now pending in the signal queue and 69311.102Skamil * the kernel presents it to userland as a masked signal. 69321.102Skamil */ 69331.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 69341.102Skamil 69351.99Skamil if (masked) { 69361.99Skamil DPRINTF("kp_sigmask=" 69371.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69381.99Skamil PRIx32 "\n", 69391.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 69401.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 69411.1Skamil 69421.99Skamil DPRINTF("kp.p_sigmask=" 69431.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69441.99Skamil PRIx32 "\n", 69451.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 69461.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 69471.1Skamil 69481.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 69491.99Skamil sizeof(kp_sigmask))); 69501.99Skamil } 69511.1Skamil 69521.99Skamil if (ignored) { 69531.99Skamil DPRINTF("kp_sigignore=" 69541.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69551.99Skamil PRIx32 "\n", 69561.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 69571.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 69581.1Skamil 69591.99Skamil DPRINTF("kp.p_sigignore=" 69601.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69611.99Skamil PRIx32 "\n", 69621.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 69631.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 69641.1Skamil 69651.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 69661.99Skamil sizeof(kp_sigignore))); 69671.99Skamil } 69681.1Skamil 69691.99Skamil SYSCALL_REQUIRE( 69701.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69711.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 69721.1Skamil 69731.99Skamil child2 = state.pe_other_pid; 69741.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 69751.99Skamil child2); 69761.1Skamil 69771.99Skamil DPRINTF("Before resuming the child process where it left off " 69781.99Skamil "and without signal to be sent\n"); 69791.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69801.99Skamil } 69811.1Skamil 69821.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 69831.126Skamil strcmp(fn, "vfork") == 0) { 69841.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 69851.99Skamil "\n", TWAIT_FNAME); 69861.99Skamil TWAIT_REQUIRE_SUCCESS( 69871.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 69881.1Skamil 69891.99Skamil validate_status_exited(status, exitval2); 69901.1Skamil 69911.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 69921.99Skamil "process\n", TWAIT_FNAME); 69931.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 69941.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 69951.99Skamil } 69961.1Skamil 69971.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 69981.1Skamil "SIGCHLD\n", TWAIT_FNAME); 69991.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70001.1Skamil 70011.1Skamil validate_status_stopped(status, SIGCHLD); 70021.1Skamil 70031.57Skamil DPRINTF("Before resuming the child process where it left off and " 70041.1Skamil "without signal to be sent\n"); 70051.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70061.1Skamil 70071.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 70081.1Skamil TWAIT_FNAME); 70091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70101.1Skamil 70111.1Skamil validate_status_exited(status, exitval); 70121.1Skamil 70131.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 70141.57Skamil TWAIT_FNAME); 70151.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 70161.1Skamil} 70171.1Skamil 70181.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 70191.99SkamilATF_TC(name); \ 70201.99SkamilATF_TC_HEAD(name, tc) \ 70211.99Skamil{ \ 70221.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 70231.99Skamil "regardless of signal %s%s", \ 70241.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 70251.99Skamil} \ 70261.99Skamil \ 70271.99SkamilATF_TC_BODY(name, tc) \ 70281.99Skamil{ \ 70291.99Skamil \ 70301.126Skamil fork2_body(fn, masked, ignored); \ 70311.1Skamil} 70321.1Skamil 70331.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 70341.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 70351.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 70361.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 70371.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 70381.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 70391.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 70401.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 70411.1Skamil#endif 70421.1Skamil 70431.99Skamil/// ---------------------------------------------------------------------------- 70441.1Skamil 70451.151Skamilstatic void * 70461.151Skamilthread_and_exec_thread_cb(void *arg __unused) 70471.151Skamil{ 70481.151Skamil 70491.151Skamil execlp("/bin/echo", "/bin/echo", NULL); 70501.151Skamil 70511.151Skamil abort(); 70521.151Skamil} 70531.151Skamil 70541.151Skamilstatic void 70551.151Skamilthreads_and_exec(void) 70561.151Skamil{ 70571.151Skamil const int sigval = SIGSTOP; 70581.151Skamil pid_t child, wpid; 70591.151Skamil#if defined(TWAIT_HAVE_STATUS) 70601.151Skamil int status; 70611.151Skamil#endif 70621.151Skamil ptrace_state_t state; 70631.151Skamil const int slen = sizeof(state); 70641.151Skamil ptrace_event_t event; 70651.151Skamil const int elen = sizeof(event); 70661.151Skamil struct ptrace_siginfo info; 70671.151Skamil 70681.151Skamil pthread_t t; 70691.151Skamil lwpid_t lid; 70701.151Skamil 70711.151Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 70721.151Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70731.151Skamil if (child == 0) { 70741.151Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70751.151Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70761.151Skamil 70771.151Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70781.151Skamil FORKEE_ASSERT(raise(sigval) == 0); 70791.151Skamil 70801.151Skamil FORKEE_ASSERT(pthread_create(&t, NULL, 70811.151Skamil thread_and_exec_thread_cb, NULL) == 0); 70821.151Skamil 70831.151Skamil for (;;) 70841.151Skamil continue; 70851.151Skamil 70861.151Skamil FORKEE_ASSERT(0 && "Not reached"); 70871.151Skamil } 70881.151Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 70891.151Skamil 70901.151Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 70911.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70921.151Skamil 70931.151Skamil validate_status_stopped(status, sigval); 70941.151Skamil 70951.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 70961.151Skamil SYSCALL_REQUIRE( 70971.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 70981.151Skamil 70991.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71001.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 71011.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71021.151Skamil info.psi_siginfo.si_errno); 71031.151Skamil 71041.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 71051.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71061.151Skamil 71071.151Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 71081.151Skamil memset(&event, 0, sizeof(event)); 71091.151Skamil event.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT; 71101.151Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 71111.151Skamil 71121.151Skamil DPRINTF("Before resuming the child process where it left off and " 71131.151Skamil "without signal to be sent\n"); 71141.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71151.151Skamil 71161.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71171.151Skamil "SIGTRAP\n", TWAIT_FNAME); 71181.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71191.151Skamil child); 71201.151Skamil 71211.151Skamil validate_status_stopped(status, SIGTRAP); 71221.151Skamil 71231.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 71241.151Skamil "child\n"); 71251.151Skamil SYSCALL_REQUIRE( 71261.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71271.151Skamil 71281.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71291.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 71301.151Skamil "si_errno=%#x\n", 71311.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71321.151Skamil info.psi_siginfo.si_errno); 71331.151Skamil 71341.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 71351.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 71361.151Skamil 71371.151Skamil SYSCALL_REQUIRE( 71381.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71391.151Skamil 71401.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 71411.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 71421.151Skamil 71431.151Skamil lid = state.pe_lwp; 71441.151Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 71451.151Skamil 71461.151Skamil DPRINTF("Before resuming the child process where it left off " 71471.151Skamil "and without signal to be sent\n"); 71481.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71491.151Skamil 71501.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71511.151Skamil "SIGTRAP\n", TWAIT_FNAME); 71521.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71531.151Skamil child); 71541.151Skamil 71551.151Skamil validate_status_stopped(status, SIGTRAP); 71561.151Skamil 71571.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 71581.151Skamil "child\n"); 71591.151Skamil SYSCALL_REQUIRE( 71601.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71611.151Skamil 71621.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71631.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 71641.151Skamil "si_errno=%#x\n", 71651.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71661.151Skamil info.psi_siginfo.si_errno); 71671.151Skamil 71681.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 71691.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 71701.151Skamil 71711.151Skamil SYSCALL_REQUIRE( 71721.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71731.151Skamil 71741.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 71751.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 71761.151Skamil 71771.151Skamil lid = state.pe_lwp; 71781.151Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 71791.151Skamil 71801.151Skamil DPRINTF("Before resuming the child process where it left off " 71811.151Skamil "and without signal to be sent\n"); 71821.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71831.151Skamil 71841.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71851.151Skamil "SIGTRAP\n", TWAIT_FNAME); 71861.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71871.151Skamil child); 71881.151Skamil 71891.151Skamil validate_status_stopped(status, SIGTRAP); 71901.151Skamil 71911.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 71921.151Skamil "child\n"); 71931.151Skamil SYSCALL_REQUIRE( 71941.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71951.151Skamil 71961.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71971.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 71981.151Skamil "si_errno=%#x\n", 71991.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 72001.151Skamil info.psi_siginfo.si_errno); 72011.151Skamil 72021.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 72031.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 72041.151Skamil 72051.151Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 72061.151Skamil 72071.151Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 72081.151Skamil TWAIT_FNAME); 72091.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72101.151Skamil 72111.151Skamil validate_status_signaled(status, SIGKILL, 0); 72121.151Skamil 72131.151Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 72141.151Skamil TWAIT_FNAME); 72151.151Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 72161.151Skamil} 72171.151Skamil 72181.151SkamilATF_TC(threads_and_exec); 72191.151SkamilATF_TC_HEAD(threads_and_exec, tc) 72201.151Skamil{ 72211.151Skamil atf_tc_set_md_var(tc, "descr", 72221.151Skamil "Verify that multithreaded application on exec() will report " 72231.151Skamil "LWP_EXIT events"); 72241.151Skamil} 72251.151Skamil 72261.151SkamilATF_TC_BODY(threads_and_exec, tc) 72271.151Skamil{ 72281.151Skamil 72291.151Skamil threads_and_exec(); 72301.151Skamil} 72311.151Skamil 72321.151Skamil/// ---------------------------------------------------------------------------- 72331.151Skamil 72341.154SkamilATF_TC(suspend_no_deadlock); 72351.154SkamilATF_TC_HEAD(suspend_no_deadlock, tc) 72361.1Skamil{ 72371.1Skamil atf_tc_set_md_var(tc, "descr", 72381.1Skamil "Verify that the while the only thread within a process is " 72391.1Skamil "suspended, the whole process cannot be unstopped"); 72401.1Skamil} 72411.1Skamil 72421.154SkamilATF_TC_BODY(suspend_no_deadlock, tc) 72431.1Skamil{ 72441.1Skamil const int exitval = 5; 72451.1Skamil const int sigval = SIGSTOP; 72461.1Skamil pid_t child, wpid; 72471.1Skamil#if defined(TWAIT_HAVE_STATUS) 72481.1Skamil int status; 72491.1Skamil#endif 72501.1Skamil struct ptrace_siginfo psi; 72511.1Skamil 72521.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 72531.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 72541.1Skamil if (child == 0) { 72551.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 72561.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 72571.1Skamil 72581.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 72591.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 72601.1Skamil 72611.13Schristos DPRINTF("Before exiting of the child process\n"); 72621.1Skamil _exit(exitval); 72631.1Skamil } 72641.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 72651.1Skamil 72661.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 72671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72681.1Skamil 72691.1Skamil validate_status_stopped(status, sigval); 72701.1Skamil 72711.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 72721.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 72731.1Skamil 72741.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 72751.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 72761.1Skamil 72771.13Schristos DPRINTF("Before resuming the child process where it left off and " 72781.1Skamil "without signal to be sent\n"); 72791.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 72801.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 72811.1Skamil 72821.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 72831.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 72841.1Skamil 72851.13Schristos DPRINTF("Before resuming the child process where it left off and " 72861.1Skamil "without signal to be sent\n"); 72871.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72881.1Skamil 72891.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 72901.1Skamil TWAIT_FNAME); 72911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72921.1Skamil 72931.1Skamil validate_status_exited(status, exitval); 72941.1Skamil 72951.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 72961.1Skamil TWAIT_FNAME); 72971.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 72981.1Skamil} 72991.1Skamil 73001.154Skamil/// ---------------------------------------------------------------------------- 73011.154Skamil 73021.155Skamilstatic pthread_barrier_t barrier1_resume; 73031.155Skamilstatic pthread_barrier_t barrier2_resume; 73041.154Skamil 73051.155Skamilstatic void * 73061.155Skamilresume_thread(void *arg) 73071.154Skamil{ 73081.154Skamil 73091.155Skamil raise(SIGUSR1); 73101.155Skamil 73111.155Skamil pthread_barrier_wait(&barrier1_resume); 73121.155Skamil 73131.155Skamil /* Debugger will suspend the process here */ 73141.155Skamil 73151.155Skamil pthread_barrier_wait(&barrier2_resume); 73161.154Skamil 73171.155Skamil raise(SIGUSR2); 73181.155Skamil 73191.155Skamil return infinite_thread(arg); 73201.154Skamil} 73211.154Skamil 73221.155SkamilATF_TC(resume); 73231.155SkamilATF_TC_HEAD(resume, tc) 73241.1Skamil{ 73251.1Skamil atf_tc_set_md_var(tc, "descr", 73261.1Skamil "Verify that a thread can be suspended by a debugger and later " 73271.1Skamil "resumed by the debugger"); 73281.1Skamil} 73291.1Skamil 73301.155SkamilATF_TC_BODY(resume, tc) 73311.1Skamil{ 73321.1Skamil const int sigval = SIGSTOP; 73331.1Skamil pid_t child, wpid; 73341.1Skamil#if defined(TWAIT_HAVE_STATUS) 73351.1Skamil int status; 73361.1Skamil#endif 73371.1Skamil lwpid_t lid; 73381.1Skamil struct ptrace_siginfo psi; 73391.155Skamil pthread_t t; 73401.1Skamil 73411.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 73421.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 73431.1Skamil if (child == 0) { 73441.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 73451.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 73461.1Skamil 73471.155Skamil pthread_barrier_init(&barrier1_resume, NULL, 2); 73481.155Skamil pthread_barrier_init(&barrier2_resume, NULL, 2); 73491.155Skamil 73501.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 73511.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 73521.1Skamil 73531.155Skamil DPRINTF("Before creating new thread in child\n"); 73541.155Skamil FORKEE_ASSERT(pthread_create(&t, NULL, resume_thread, NULL) == 0); 73551.1Skamil 73561.155Skamil pthread_barrier_wait(&barrier1_resume); 73571.1Skamil 73581.155Skamil pthread_barrier_wait(&barrier2_resume); 73591.1Skamil 73601.155Skamil infinite_thread(NULL); 73611.1Skamil } 73621.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 73631.1Skamil 73641.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 73651.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73661.1Skamil 73671.1Skamil validate_status_stopped(status, sigval); 73681.1Skamil 73691.13Schristos DPRINTF("Before resuming the child process where it left off and " 73701.1Skamil "without signal to be sent\n"); 73711.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73721.1Skamil 73731.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 73741.155Skamil "SIGUSR1\n", TWAIT_FNAME); 73751.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73761.1Skamil 73771.155Skamil validate_status_stopped(status, SIGUSR1); 73781.1Skamil 73791.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 73801.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 73811.1Skamil 73821.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 73831.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 73841.1Skamil 73851.155Skamil lid = psi.psi_lwpid; 73861.1Skamil 73871.13Schristos DPRINTF("Before resuming the child process where it left off and " 73881.1Skamil "without signal to be sent\n"); 73891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73901.1Skamil 73911.155Skamil DPRINTF("Before suspending the parent for 1 second, we expect no signals\n"); 73921.155Skamil SYSCALL_REQUIRE(sleep(1) == 0); 73931.155Skamil 73941.155Skamil#if defined(TWAIT_HAVE_OPTIONS) 73951.155Skamil DPRINTF("Before calling %s() for the child - expected no status\n", 73961.155Skamil TWAIT_FNAME); 73971.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, WNOHANG), 0); 73981.155Skamil#endif 73991.155Skamil 74001.155Skamil DPRINTF("Before resuming the child process where it left off and " 74011.155Skamil "without signal to be sent\n"); 74021.155Skamil SYSCALL_REQUIRE(ptrace(PT_STOP, child, NULL, 0) != -1); 74031.155Skamil 74041.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 74051.155Skamil "SIGSTOP\n", TWAIT_FNAME); 74061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74071.1Skamil 74081.155Skamil validate_status_stopped(status, SIGSTOP); 74091.1Skamil 74101.155Skamil DPRINTF("Before resuming LWP %d\n", lid); 74111.155Skamil SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, lid) != -1); 74121.155Skamil 74131.155Skamil DPRINTF("Before resuming the child process where it left off and " 74141.155Skamil "without signal to be sent\n"); 74151.155Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74161.1Skamil 74171.155Skamil DPRINTF("Before calling %s() for the child - expected stopped " 74181.155Skamil "SIGUSR2\n", TWAIT_FNAME); 74191.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74201.1Skamil 74211.155Skamil validate_status_stopped(status, SIGUSR2); 74221.1Skamil 74231.13Schristos DPRINTF("Before resuming the child process where it left off and " 74241.1Skamil "without signal to be sent\n"); 74251.155Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 74261.1Skamil 74271.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 74281.1Skamil TWAIT_FNAME); 74291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74301.1Skamil 74311.155Skamil validate_status_signaled(status, SIGKILL, 0); 74321.1Skamil 74331.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 74341.1Skamil TWAIT_FNAME); 74351.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74361.155Skamil} 74371.1Skamil 74381.155Skamil/// ---------------------------------------------------------------------------- 74391.1Skamil 74401.167Skamilstatic int test_syscall_caught; 74411.167Skamil 74421.167Skamilstatic void 74431.167Skamilsyscall_sighand(int arg) 74441.167Skamil{ 74451.167Skamil 74461.167Skamil DPRINTF("Caught a signal %d in process %d\n", arg, getpid()); 74471.167Skamil 74481.167Skamil FORKEE_ASSERT_EQ(arg, SIGINFO); 74491.167Skamil 74501.167Skamil ++test_syscall_caught; 74511.167Skamil 74521.167Skamil FORKEE_ASSERT_EQ(test_syscall_caught, 1); 74531.167Skamil} 74541.167Skamil 74551.166Skamilstatic void 74561.167Skamilsyscall_body(const char *op) 74571.1Skamil{ 74581.1Skamil const int exitval = 5; 74591.1Skamil const int sigval = SIGSTOP; 74601.1Skamil pid_t child, wpid; 74611.1Skamil#if defined(TWAIT_HAVE_STATUS) 74621.1Skamil int status; 74631.1Skamil#endif 74641.1Skamil struct ptrace_siginfo info; 74651.167Skamil 74661.1Skamil memset(&info, 0, sizeof(info)); 74671.1Skamil 74681.167Skamil#if defined(TWAIT_HAVE_STATUS) 74691.167Skamil if (strstr(op, "signal") != NULL) { 74701.167Skamil atf_tc_expect_fail("XXX: behavior under investigation"); 74711.167Skamil } 74721.167Skamil#endif 74731.167Skamil 74741.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 74751.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 74761.1Skamil if (child == 0) { 74771.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74781.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74791.1Skamil 74801.167Skamil signal(SIGINFO, syscall_sighand); 74811.167Skamil 74821.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 74831.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 74841.1Skamil 74851.1Skamil syscall(SYS_getpid); 74861.1Skamil 74871.167Skamil if (strstr(op, "signal") != NULL) { 74881.167Skamil FORKEE_ASSERT_EQ(test_syscall_caught, 1); 74891.167Skamil } 74901.167Skamil 74911.13Schristos DPRINTF("Before exiting of the child process\n"); 74921.1Skamil _exit(exitval); 74931.1Skamil } 74941.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74951.1Skamil 74961.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74981.1Skamil 74991.1Skamil validate_status_stopped(status, sigval); 75001.1Skamil 75011.13Schristos DPRINTF("Before resuming the child process where it left off and " 75021.1Skamil "without signal to be sent\n"); 75031.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 75041.1Skamil 75051.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75071.1Skamil 75081.1Skamil validate_status_stopped(status, SIGTRAP); 75091.1Skamil 75101.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 75111.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 75121.1Skamil 75131.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 75141.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 75151.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 75161.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 75171.1Skamil 75181.167Skamil if (strstr(op, "killed") != NULL) { 75191.166Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 75201.166Skamil 75211.166Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75221.166Skamil TWAIT_REQUIRE_SUCCESS( 75231.166Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 75241.166Skamil 75251.166Skamil validate_status_signaled(status, SIGKILL, 0); 75261.166Skamil } else { 75271.167Skamil if (strstr(op, "signal") != NULL) { 75281.167Skamil DPRINTF("Before resuming the child %d and sending a " 75291.167Skamil "signal SIGINFO\n", child); 75301.167Skamil SYSCALL_REQUIRE( 75311.167Skamil ptrace(PT_CONTINUE, child, (void *)1, SIGINFO) 75321.167Skamil != -1); 75331.167Skamil } else if (strstr(op, "detach") != NULL) { 75341.167Skamil DPRINTF("Before detaching the child %d\n", child); 75351.167Skamil SYSCALL_REQUIRE( 75361.167Skamil ptrace(PT_DETACH, child, (void *)1, 0) != -1); 75371.167Skamil } else { 75381.167Skamil DPRINTF("Before resuming the child process where it " 75391.167Skamil "left off and without signal to be sent\n"); 75401.167Skamil SYSCALL_REQUIRE( 75411.167Skamil ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 75421.166Skamil 75431.167Skamil DPRINTF("Before calling %s() for the child\n", 75441.167Skamil TWAIT_FNAME); 75451.167Skamil TWAIT_REQUIRE_SUCCESS( 75461.167Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 75471.1Skamil 75481.167Skamil validate_status_stopped(status, SIGTRAP); 75491.1Skamil 75501.167Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO " 75511.167Skamil "for child\n"); 75521.167Skamil SYSCALL_REQUIRE( 75531.167Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 75541.167Skamil != -1); 75551.1Skamil 75561.167Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 75571.167Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 75581.167Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 75591.167Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 75601.1Skamil 75611.167Skamil DPRINTF("Before resuming the child process where it " 75621.167Skamil "left off and without signal to be sent\n"); 75631.167Skamil SYSCALL_REQUIRE( 75641.167Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 75651.167Skamil } 75661.1Skamil 75671.166Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75681.166Skamil TWAIT_REQUIRE_SUCCESS( 75691.166Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 75701.1Skamil 75711.166Skamil validate_status_exited(status, exitval); 75721.166Skamil } 75731.1Skamil 75741.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75751.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75761.1Skamil} 75771.1Skamil 75781.167Skamil#define SYSCALL_TEST(name,op) \ 75791.166SkamilATF_TC(name); \ 75801.166SkamilATF_TC_HEAD(name, tc) \ 75811.166Skamil{ \ 75821.170Skamil atf_tc_set_md_var(tc, "timeout", "15"); \ 75831.166Skamil atf_tc_set_md_var(tc, "descr", \ 75841.166Skamil "Verify that getpid(2) can be traced with PT_SYSCALL %s", \ 75851.167Skamil #op ); \ 75861.166Skamil} \ 75871.166Skamil \ 75881.166SkamilATF_TC_BODY(name, tc) \ 75891.166Skamil{ \ 75901.166Skamil \ 75911.167Skamil syscall_body(op); \ 75921.166Skamil} 75931.166Skamil 75941.167SkamilSYSCALL_TEST(syscall, "") 75951.167SkamilSYSCALL_TEST(syscall_killed_on_sce, "and killed") 75961.167SkamilSYSCALL_TEST(syscall_signal_on_sce, "and signaled") 75971.167SkamilSYSCALL_TEST(syscall_detach_on_sce, "and detached") 75981.166Skamil 75991.164Skamil/// ---------------------------------------------------------------------------- 76001.164Skamil 76011.1SkamilATF_TC(syscallemu1); 76021.1SkamilATF_TC_HEAD(syscallemu1, tc) 76031.1Skamil{ 76041.1Skamil atf_tc_set_md_var(tc, "descr", 76051.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 76061.1Skamil} 76071.1Skamil 76081.1SkamilATF_TC_BODY(syscallemu1, tc) 76091.1Skamil{ 76101.1Skamil const int exitval = 5; 76111.1Skamil const int sigval = SIGSTOP; 76121.1Skamil pid_t child, wpid; 76131.1Skamil#if defined(TWAIT_HAVE_STATUS) 76141.1Skamil int status; 76151.1Skamil#endif 76161.1Skamil 76171.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 76181.6Skamil /* syscallemu does not work on sparc (32-bit) */ 76191.6Skamil atf_tc_expect_fail("PR kern/52166"); 76201.6Skamil#endif 76211.6Skamil 76221.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 76231.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 76241.1Skamil if (child == 0) { 76251.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 76261.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 76271.1Skamil 76281.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 76291.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 76301.1Skamil 76311.1Skamil syscall(SYS_exit, 100); 76321.1Skamil 76331.13Schristos DPRINTF("Before exiting of the child process\n"); 76341.1Skamil _exit(exitval); 76351.1Skamil } 76361.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 76371.1Skamil 76381.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76391.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76401.1Skamil 76411.1Skamil validate_status_stopped(status, sigval); 76421.1Skamil 76431.13Schristos DPRINTF("Before resuming the child process where it left off and " 76441.1Skamil "without signal to be sent\n"); 76451.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 76461.1Skamil 76471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76491.1Skamil 76501.1Skamil validate_status_stopped(status, SIGTRAP); 76511.1Skamil 76521.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 76531.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 76541.1Skamil 76551.13Schristos DPRINTF("Before resuming the child process where it left off and " 76561.1Skamil "without signal to be sent\n"); 76571.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 76581.1Skamil 76591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76611.1Skamil 76621.1Skamil validate_status_stopped(status, SIGTRAP); 76631.1Skamil 76641.13Schristos DPRINTF("Before resuming the child process where it left off and " 76651.1Skamil "without signal to be sent\n"); 76661.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 76671.1Skamil 76681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76691.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76701.1Skamil 76711.1Skamil validate_status_exited(status, exitval); 76721.1Skamil 76731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76741.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76751.1Skamil} 76761.1Skamil 76771.103Skamil/// ---------------------------------------------------------------------------- 76781.103Skamil 76791.106Skamilstatic void 76801.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 76811.106Skamil bool trackvforkdone) 76821.106Skamil{ 76831.106Skamil const int exitval = 5; 76841.106Skamil const int exitval2 = 15; 76851.106Skamil const int sigval = SIGSTOP; 76861.106Skamil pid_t child, child2 = 0, wpid; 76871.106Skamil#if defined(TWAIT_HAVE_STATUS) 76881.106Skamil int status; 76891.106Skamil#endif 76901.106Skamil ptrace_state_t state; 76911.106Skamil const int slen = sizeof(state); 76921.106Skamil ptrace_event_t event; 76931.106Skamil const int elen = sizeof(event); 76941.106Skamil 76951.106Skamil const size_t stack_size = 1024 * 1024; 76961.106Skamil void *stack, *stack_base; 76971.106Skamil 76981.106Skamil stack = malloc(stack_size); 76991.106Skamil ATF_REQUIRE(stack != NULL); 77001.106Skamil 77011.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 77021.106Skamil stack_base = stack; 77031.106Skamil#else 77041.106Skamil stack_base = (char *)stack + stack_size; 77051.106Skamil#endif 77061.106Skamil 77071.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 77081.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 77091.106Skamil if (child == 0) { 77101.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 77111.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 77121.106Skamil 77131.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 77141.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 77151.106Skamil 77161.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 77171.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 77181.106Skamil 77191.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 77201.106Skamil child2); 77211.106Skamil 77221.106Skamil // XXX WALLSIG? 77231.106Skamil FORKEE_REQUIRE_SUCCESS 77241.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 77251.106Skamil 77261.106Skamil forkee_status_exited(status, exitval2); 77271.106Skamil 77281.106Skamil DPRINTF("Before exiting of the child process\n"); 77291.106Skamil _exit(exitval); 77301.106Skamil } 77311.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 77321.106Skamil 77331.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77341.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77351.106Skamil 77361.106Skamil validate_status_stopped(status, sigval); 77371.106Skamil 77381.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 77391.106Skamil trackfork ? "|PTRACE_FORK" : "", 77401.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 77411.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 77421.106Skamil event.pe_set_event = 0; 77431.106Skamil if (trackfork) 77441.106Skamil event.pe_set_event |= PTRACE_FORK; 77451.106Skamil if (trackvfork) 77461.106Skamil event.pe_set_event |= PTRACE_VFORK; 77471.106Skamil if (trackvforkdone) 77481.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 77491.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 77501.106Skamil 77511.106Skamil DPRINTF("Before resuming the child process where it left off and " 77521.106Skamil "without signal to be sent\n"); 77531.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 77541.106Skamil 77551.106Skamil#if defined(TWAIT_HAVE_PID) 77561.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 77571.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 77581.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 77591.106Skamil child); 77601.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 77611.106Skamil child); 77621.106Skamil 77631.106Skamil validate_status_stopped(status, SIGTRAP); 77641.106Skamil 77651.106Skamil SYSCALL_REQUIRE( 77661.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 77671.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 77681.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 77691.106Skamil PTRACE_FORK); 77701.106Skamil } 77711.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 77721.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 77731.106Skamil PTRACE_VFORK); 77741.106Skamil } 77751.106Skamil 77761.106Skamil child2 = state.pe_other_pid; 77771.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 77781.106Skamil 77791.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 77801.106Skamil "%d\n", TWAIT_FNAME, child2, child); 77811.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 77821.106Skamil child2); 77831.106Skamil 77841.106Skamil validate_status_stopped(status, SIGTRAP); 77851.106Skamil 77861.106Skamil SYSCALL_REQUIRE( 77871.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 77881.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 77891.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 77901.106Skamil PTRACE_FORK); 77911.106Skamil } 77921.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 77931.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 77941.106Skamil PTRACE_VFORK); 77951.106Skamil } 77961.106Skamil 77971.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 77981.106Skamil 77991.106Skamil DPRINTF("Before resuming the forkee process where it left off " 78001.106Skamil "and without signal to be sent\n"); 78011.106Skamil SYSCALL_REQUIRE( 78021.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 78031.106Skamil 78041.106Skamil DPRINTF("Before resuming the child process where it left off " 78051.106Skamil "and without signal to be sent\n"); 78061.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78071.106Skamil } 78081.106Skamil#endif 78091.106Skamil 78101.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 78111.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 78121.106Skamil child); 78131.106Skamil TWAIT_REQUIRE_SUCCESS( 78141.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 78151.106Skamil 78161.106Skamil validate_status_stopped(status, SIGTRAP); 78171.106Skamil 78181.106Skamil SYSCALL_REQUIRE( 78191.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 78201.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 78211.106Skamil 78221.106Skamil child2 = state.pe_other_pid; 78231.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 78241.106Skamil child2); 78251.106Skamil 78261.106Skamil DPRINTF("Before resuming the child process where it left off " 78271.106Skamil "and without signal to be sent\n"); 78281.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78291.106Skamil } 78301.106Skamil 78311.103Skamil#if defined(TWAIT_HAVE_PID) 78321.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 78331.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 78341.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 78351.106Skamil "\n", TWAIT_FNAME); 78361.106Skamil TWAIT_REQUIRE_SUCCESS( 78371.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 78381.106Skamil 78391.106Skamil validate_status_exited(status, exitval2); 78401.106Skamil 78411.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 78421.106Skamil "process\n", TWAIT_FNAME); 78431.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 78441.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 78451.106Skamil } 78461.106Skamil#endif 78471.106Skamil 78481.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 78491.106Skamil "SIGCHLD\n", TWAIT_FNAME); 78501.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 78511.106Skamil 78521.106Skamil validate_status_stopped(status, SIGCHLD); 78531.106Skamil 78541.106Skamil DPRINTF("Before resuming the child process where it left off and " 78551.106Skamil "without signal to be sent\n"); 78561.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78571.106Skamil 78581.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 78591.106Skamil TWAIT_FNAME); 78601.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 78611.106Skamil 78621.106Skamil validate_status_exited(status, exitval); 78631.103Skamil 78641.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 78651.106Skamil TWAIT_FNAME); 78661.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 78671.106Skamil} 78681.103Skamil 78691.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 78701.106SkamilATF_TC(name); \ 78711.106SkamilATF_TC_HEAD(name, tc) \ 78721.106Skamil{ \ 78731.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 78741.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 78751.106Skamil #flags, \ 78761.106Skamil tfork ? "|PTRACE_FORK" : "", \ 78771.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 78781.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 78791.106Skamil} \ 78801.106Skamil \ 78811.106SkamilATF_TC_BODY(name, tc) \ 78821.106Skamil{ \ 78831.106Skamil \ 78841.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 78851.103Skamil} 78861.103Skamil 78871.106SkamilCLONE_TEST(clone1, 0, false, false, false) 78881.106Skamil#if defined(TWAIT_HAVE_PID) 78891.106SkamilCLONE_TEST(clone2, 0, true, false, false) 78901.106SkamilCLONE_TEST(clone3, 0, false, true, false) 78911.106SkamilCLONE_TEST(clone4, 0, true, true, false) 78921.106Skamil#endif 78931.106SkamilCLONE_TEST(clone5, 0, false, false, true) 78941.106Skamil#if defined(TWAIT_HAVE_PID) 78951.106SkamilCLONE_TEST(clone6, 0, true, false, true) 78961.106SkamilCLONE_TEST(clone7, 0, false, true, true) 78971.106SkamilCLONE_TEST(clone8, 0, true, true, true) 78981.106Skamil#endif 78991.106Skamil 79001.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 79011.106Skamil#if defined(TWAIT_HAVE_PID) 79021.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 79031.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 79041.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 79051.106Skamil#endif 79061.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 79071.106Skamil#if defined(TWAIT_HAVE_PID) 79081.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 79091.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 79101.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 79111.106Skamil#endif 79121.106Skamil 79131.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 79141.106Skamil#if defined(TWAIT_HAVE_PID) 79151.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 79161.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 79171.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 79181.106Skamil#endif 79191.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 79201.106Skamil#if defined(TWAIT_HAVE_PID) 79211.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 79221.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 79231.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 79241.106Skamil#endif 79251.106Skamil 79261.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 79271.106Skamil#if defined(TWAIT_HAVE_PID) 79281.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 79291.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 79301.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 79311.106Skamil#endif 79321.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 79331.106Skamil#if defined(TWAIT_HAVE_PID) 79341.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 79351.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 79361.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 79371.106Skamil#endif 79381.106Skamil 79391.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 79401.106Skamil#if defined(TWAIT_HAVE_PID) 79411.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 79421.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 79431.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 79441.106Skamil#endif 79451.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 79461.106Skamil#if defined(TWAIT_HAVE_PID) 79471.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 79481.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 79491.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 79501.106Skamil#endif 79511.106Skamil 79521.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 79531.106Skamil#if defined(TWAIT_HAVE_PID) 79541.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 79551.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 79561.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 79571.106Skamil#endif 79581.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 79591.106Skamil#if defined(TWAIT_HAVE_PID) 79601.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 79611.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 79621.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 79631.106Skamil#endif 79641.106Skamil 79651.106Skamil/// ---------------------------------------------------------------------------- 79661.106Skamil 79671.106Skamil#if defined(TWAIT_HAVE_PID) 79681.103Skamilstatic void 79691.106Skamilclone_body2(int flags, bool masked, bool ignored) 79701.103Skamil{ 79711.103Skamil const int exitval = 5; 79721.103Skamil const int exitval2 = 15; 79731.103Skamil const int sigval = SIGSTOP; 79741.103Skamil pid_t child, child2 = 0, wpid; 79751.103Skamil#if defined(TWAIT_HAVE_STATUS) 79761.103Skamil int status; 79771.103Skamil#endif 79781.103Skamil ptrace_state_t state; 79791.103Skamil const int slen = sizeof(state); 79801.103Skamil ptrace_event_t event; 79811.103Skamil const int elen = sizeof(event); 79821.103Skamil struct sigaction sa; 79831.103Skamil struct ptrace_siginfo info; 79841.103Skamil sigset_t intmask; 79851.103Skamil struct kinfo_proc2 kp; 79861.103Skamil size_t len = sizeof(kp); 79871.103Skamil 79881.103Skamil int name[6]; 79891.103Skamil const size_t namelen = __arraycount(name); 79901.103Skamil ki_sigset_t kp_sigmask; 79911.103Skamil ki_sigset_t kp_sigignore; 79921.103Skamil 79931.103Skamil const size_t stack_size = 1024 * 1024; 79941.103Skamil void *stack, *stack_base; 79951.103Skamil 79961.103Skamil stack = malloc(stack_size); 79971.103Skamil ATF_REQUIRE(stack != NULL); 79981.103Skamil 79991.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 80001.103Skamil stack_base = stack; 80011.103Skamil#else 80021.103Skamil stack_base = (char *)stack + stack_size; 80031.103Skamil#endif 80041.103Skamil 80051.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 80061.103Skamil if (child == 0) { 80071.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 80081.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 80091.103Skamil 80101.103Skamil if (masked) { 80111.103Skamil sigemptyset(&intmask); 80121.103Skamil sigaddset(&intmask, SIGTRAP); 80131.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 80141.103Skamil } 80151.103Skamil 80161.103Skamil if (ignored) { 80171.103Skamil memset(&sa, 0, sizeof(sa)); 80181.103Skamil sa.sa_handler = SIG_IGN; 80191.103Skamil sigemptyset(&sa.sa_mask); 80201.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 80211.103Skamil } 80221.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 80231.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 80241.103Skamil 80251.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 80261.103Skamil flags); 80271.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 80281.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 80291.103Skamil 80301.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 80311.103Skamil child2); 80321.103Skamil 80331.103Skamil // XXX WALLSIG? 80341.103Skamil FORKEE_REQUIRE_SUCCESS 80351.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 80361.103Skamil 80371.103Skamil forkee_status_exited(status, exitval2); 80381.103Skamil 80391.103Skamil DPRINTF("Before exiting of the child process\n"); 80401.103Skamil _exit(exitval); 80411.103Skamil } 80421.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 80431.103Skamil 80441.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 80451.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 80461.103Skamil 80471.103Skamil validate_status_stopped(status, sigval); 80481.103Skamil 80491.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 80501.103Skamil SYSCALL_REQUIRE( 80511.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 80521.103Skamil 80531.103Skamil DPRINTF("Before checking siginfo_t\n"); 80541.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 80551.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 80561.103Skamil 80571.103Skamil name[0] = CTL_KERN, 80581.103Skamil name[1] = KERN_PROC2, 80591.103Skamil name[2] = KERN_PROC_PID; 80601.103Skamil name[3] = child; 80611.103Skamil name[4] = sizeof(kp); 80621.103Skamil name[5] = 1; 80631.103Skamil 80641.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 80651.103Skamil 80661.103Skamil if (masked) 80671.103Skamil kp_sigmask = kp.p_sigmask; 80681.103Skamil 80691.103Skamil if (ignored) 80701.103Skamil kp_sigignore = kp.p_sigignore; 80711.103Skamil 80721.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 80731.103Skamil "EVENT_MASK for the child %d\n", child); 80741.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 80751.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 80761.103Skamil 80771.103Skamil DPRINTF("Before resuming the child process where it left off and " 80781.103Skamil "without signal to be sent\n"); 80791.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 80801.103Skamil 80811.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 80821.103Skamil child); 80831.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 80841.103Skamil child); 80851.103Skamil 80861.103Skamil validate_status_stopped(status, SIGTRAP); 80871.103Skamil 80881.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 80891.103Skamil 80901.103Skamil if (masked) { 80911.103Skamil DPRINTF("kp_sigmask=" 80921.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 80931.103Skamil PRIx32 "\n", 80941.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 80951.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 80961.103Skamil 80971.103Skamil DPRINTF("kp.p_sigmask=" 80981.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 80991.103Skamil PRIx32 "\n", 81001.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 81011.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 81021.103Skamil 81031.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 81041.103Skamil sizeof(kp_sigmask))); 81051.103Skamil } 81061.103Skamil 81071.103Skamil if (ignored) { 81081.103Skamil DPRINTF("kp_sigignore=" 81091.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81101.103Skamil PRIx32 "\n", 81111.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 81121.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 81131.103Skamil 81141.103Skamil DPRINTF("kp.p_sigignore=" 81151.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81161.103Skamil PRIx32 "\n", 81171.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 81181.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 81191.103Skamil 81201.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 81211.103Skamil sizeof(kp_sigignore))); 81221.103Skamil } 81231.103Skamil 81241.103Skamil SYSCALL_REQUIRE( 81251.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 81261.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 81271.103Skamil child2); 81281.103Skamil if (!(flags & CLONE_VFORK)) { 81291.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 81301.103Skamil PTRACE_FORK); 81311.103Skamil } else { 81321.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 81331.103Skamil PTRACE_VFORK); 81341.103Skamil } 81351.103Skamil 81361.103Skamil child2 = state.pe_other_pid; 81371.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 81381.103Skamil 81391.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 81401.103Skamil "%d\n", TWAIT_FNAME, child2, child); 81411.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 81421.103Skamil child2); 81431.103Skamil 81441.103Skamil validate_status_stopped(status, SIGTRAP); 81451.103Skamil 81461.103Skamil name[3] = child2; 81471.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 81481.103Skamil 81491.103Skamil if (masked) { 81501.103Skamil DPRINTF("kp_sigmask=" 81511.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81521.103Skamil PRIx32 "\n", 81531.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 81541.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 81551.103Skamil 81561.103Skamil DPRINTF("kp.p_sigmask=" 81571.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81581.103Skamil PRIx32 "\n", 81591.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 81601.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 81611.103Skamil 81621.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 81631.103Skamil sizeof(kp_sigmask))); 81641.103Skamil } 81651.103Skamil 81661.103Skamil if (ignored) { 81671.103Skamil DPRINTF("kp_sigignore=" 81681.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81691.103Skamil PRIx32 "\n", 81701.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 81711.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 81721.103Skamil 81731.103Skamil DPRINTF("kp.p_sigignore=" 81741.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81751.103Skamil PRIx32 "\n", 81761.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 81771.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 81781.103Skamil 81791.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 81801.103Skamil sizeof(kp_sigignore))); 81811.103Skamil } 81821.103Skamil 81831.103Skamil SYSCALL_REQUIRE( 81841.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 81851.103Skamil if (!(flags & CLONE_VFORK)) { 81861.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 81871.103Skamil PTRACE_FORK); 81881.103Skamil } else { 81891.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 81901.103Skamil PTRACE_VFORK); 81911.103Skamil } 81921.103Skamil 81931.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 81941.103Skamil 81951.103Skamil DPRINTF("Before resuming the forkee process where it left off " 81961.103Skamil "and without signal to be sent\n"); 81971.103Skamil SYSCALL_REQUIRE( 81981.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 81991.103Skamil 82001.103Skamil DPRINTF("Before resuming the child process where it left off " 82011.103Skamil "and without signal to be sent\n"); 82021.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 82031.103Skamil 82041.103Skamil if (flags & CLONE_VFORK) { 82051.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 82061.103Skamil child); 82071.103Skamil TWAIT_REQUIRE_SUCCESS( 82081.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 82091.103Skamil 82101.103Skamil validate_status_stopped(status, SIGTRAP); 82111.103Skamil 82121.103Skamil name[3] = child; 82131.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 82141.103Skamil 82151.103Skamil /* 82161.103Skamil * SIGCHLD is now pending in the signal queue and 82171.103Skamil * the kernel presents it to userland as a masked signal. 82181.103Skamil */ 82191.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 82201.103Skamil 82211.103Skamil if (masked) { 82221.103Skamil DPRINTF("kp_sigmask=" 82231.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 82241.103Skamil PRIx32 "\n", 82251.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 82261.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 82271.103Skamil 82281.103Skamil DPRINTF("kp.p_sigmask=" 82291.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 82301.103Skamil PRIx32 "\n", 82311.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 82321.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 82331.103Skamil 82341.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 82351.103Skamil sizeof(kp_sigmask))); 82361.103Skamil } 82371.103Skamil 82381.103Skamil if (ignored) { 82391.103Skamil DPRINTF("kp_sigignore=" 82401.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 82411.103Skamil PRIx32 "\n", 82421.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 82431.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 82441.103Skamil 82451.103Skamil DPRINTF("kp.p_sigignore=" 82461.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 82471.103Skamil PRIx32 "\n", 82481.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 82491.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 82501.103Skamil 82511.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 82521.103Skamil sizeof(kp_sigignore))); 82531.103Skamil } 82541.103Skamil 82551.103Skamil SYSCALL_REQUIRE( 82561.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 82571.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 82581.103Skamil 82591.103Skamil child2 = state.pe_other_pid; 82601.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 82611.103Skamil child2); 82621.103Skamil 82631.103Skamil DPRINTF("Before resuming the child process where it left off " 82641.103Skamil "and without signal to be sent\n"); 82651.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 82661.103Skamil } 82671.103Skamil 82681.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 82691.103Skamil "\n", TWAIT_FNAME); 82701.103Skamil TWAIT_REQUIRE_SUCCESS( 82711.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 82721.103Skamil 82731.103Skamil validate_status_exited(status, exitval2); 82741.103Skamil 82751.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 82761.103Skamil "process\n", TWAIT_FNAME); 82771.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 82781.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 82791.103Skamil 82801.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 82811.103Skamil "SIGCHLD\n", TWAIT_FNAME); 82821.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 82831.103Skamil 82841.103Skamil validate_status_stopped(status, SIGCHLD); 82851.103Skamil 82861.103Skamil DPRINTF("Before resuming the child process where it left off and " 82871.103Skamil "without signal to be sent\n"); 82881.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 82891.103Skamil 82901.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 82911.103Skamil TWAIT_FNAME); 82921.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 82931.103Skamil 82941.103Skamil validate_status_exited(status, exitval); 82951.103Skamil 82961.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 82971.103Skamil TWAIT_FNAME); 82981.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 82991.103Skamil} 83001.103Skamil 83011.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 83021.103SkamilATF_TC(name); \ 83031.103SkamilATF_TC_HEAD(name, tc) \ 83041.103Skamil{ \ 83051.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 83061.103Skamil " regardless of signal %s%s", \ 83071.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 83081.103Skamil} \ 83091.103Skamil \ 83101.103SkamilATF_TC_BODY(name, tc) \ 83111.103Skamil{ \ 83121.103Skamil \ 83131.106Skamil clone_body2(flags, masked, ignored); \ 83141.103Skamil} 83151.103Skamil 83161.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 83171.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 83181.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 83191.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 83201.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 83211.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 83221.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 83231.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 83241.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 83251.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 83261.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 83271.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 83281.103Skamil#endif 83291.103Skamil 83301.103Skamil/// ---------------------------------------------------------------------------- 83311.103Skamil 83321.107Skamil#if defined(TWAIT_HAVE_PID) 83331.107Skamilstatic void 83341.107Skamiltraceme_vfork_clone_body(int flags) 83351.107Skamil{ 83361.107Skamil const int exitval = 5; 83371.107Skamil const int exitval2 = 15; 83381.107Skamil pid_t child, child2 = 0, wpid; 83391.107Skamil#if defined(TWAIT_HAVE_STATUS) 83401.107Skamil int status; 83411.107Skamil#endif 83421.107Skamil 83431.107Skamil const size_t stack_size = 1024 * 1024; 83441.107Skamil void *stack, *stack_base; 83451.107Skamil 83461.107Skamil stack = malloc(stack_size); 83471.107Skamil ATF_REQUIRE(stack != NULL); 83481.107Skamil 83491.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 83501.107Skamil stack_base = stack; 83511.107Skamil#else 83521.107Skamil stack_base = (char *)stack + stack_size; 83531.107Skamil#endif 83541.107Skamil 83551.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 83561.107Skamil if (child == 0) { 83571.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 83581.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 83591.107Skamil 83601.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 83611.107Skamil flags); 83621.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 83631.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 83641.107Skamil 83651.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 83661.107Skamil child2); 83671.107Skamil 83681.107Skamil // XXX WALLSIG? 83691.107Skamil FORKEE_REQUIRE_SUCCESS 83701.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 83711.107Skamil 83721.107Skamil forkee_status_exited(status, exitval2); 83731.107Skamil 83741.107Skamil DPRINTF("Before exiting of the child process\n"); 83751.107Skamil _exit(exitval); 83761.107Skamil } 83771.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 83781.107Skamil 83791.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 83801.107Skamil TWAIT_FNAME); 83811.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 83821.107Skamil 83831.107Skamil validate_status_exited(status, exitval); 83841.107Skamil 83851.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 83861.107Skamil TWAIT_FNAME); 83871.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 83881.107Skamil} 83891.107Skamil 83901.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 83911.107SkamilATF_TC(name); \ 83921.107SkamilATF_TC_HEAD(name, tc) \ 83931.107Skamil{ \ 83941.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 83951.107Skamil "handled correctly with vfork(2)ed tracer", \ 83961.107Skamil #flags); \ 83971.107Skamil} \ 83981.107Skamil \ 83991.107SkamilATF_TC_BODY(name, tc) \ 84001.107Skamil{ \ 84011.107Skamil \ 84021.107Skamil traceme_vfork_clone_body(flags); \ 84031.107Skamil} 84041.107Skamil 84051.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 84061.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 84071.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 84081.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 84091.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 84101.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 84111.107Skamil#endif 84121.107Skamil 84131.107Skamil/// ---------------------------------------------------------------------------- 84141.107Skamil 84151.122Skamilstatic void 84161.122Skamiluser_va0_disable(int operation) 84171.122Skamil{ 84181.122Skamil pid_t child, wpid; 84191.122Skamil#if defined(TWAIT_HAVE_STATUS) 84201.122Skamil int status; 84211.122Skamil#endif 84221.122Skamil const int sigval = SIGSTOP; 84231.122Skamil int rv; 84241.122Skamil 84251.122Skamil struct ptrace_siginfo info; 84261.122Skamil 84271.122Skamil if (get_user_va0_disable() == 0) 84281.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 84291.122Skamil 84301.122Skamil memset(&info, 0, sizeof(info)); 84311.122Skamil 84321.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 84331.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 84341.122Skamil if (child == 0) { 84351.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 84361.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 84371.122Skamil 84381.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 84391.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 84401.122Skamil 84411.122Skamil /* NOTREACHED */ 84421.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 84431.122Skamil __unreachable(); 84441.122Skamil } 84451.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 84461.122Skamil 84471.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 84481.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 84491.122Skamil 84501.122Skamil validate_status_stopped(status, sigval); 84511.122Skamil 84521.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 84531.122Skamil "child\n"); 84541.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 84551.122Skamil sizeof(info)) != -1); 84561.122Skamil 84571.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 84581.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 84591.122Skamil "si_errno=%#x\n", 84601.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 84611.122Skamil info.psi_siginfo.si_errno); 84621.122Skamil 84631.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 84641.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 84651.122Skamil 84661.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 84671.122Skamil "and without signal to be sent\n"); 84681.122Skamil errno = 0; 84691.122Skamil rv = ptrace(operation, child, (void *)0, 0); 84701.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 84711.122Skamil ATF_REQUIRE_EQ(rv, -1); 84721.122Skamil 84731.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 84741.122Skamil 84751.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 84761.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 84771.122Skamil validate_status_signaled(status, SIGKILL, 0); 84781.122Skamil 84791.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 84801.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 84811.122Skamil} 84821.122Skamil 84831.122Skamil#define USER_VA0_DISABLE(test, operation) \ 84841.122SkamilATF_TC(test); \ 84851.122SkamilATF_TC_HEAD(test, tc) \ 84861.122Skamil{ \ 84871.122Skamil atf_tc_set_md_var(tc, "descr", \ 84881.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 84891.122Skamil} \ 84901.122Skamil \ 84911.122SkamilATF_TC_BODY(test, tc) \ 84921.122Skamil{ \ 84931.122Skamil \ 84941.122Skamil user_va0_disable(operation); \ 84951.122Skamil} 84961.122Skamil 84971.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 84981.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 84991.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 85001.122Skamil 85011.122Skamil/// ---------------------------------------------------------------------------- 85021.122Skamil 85031.130Smgorny/* 85041.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 85051.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 85061.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 85071.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 85081.130Smgorny * found, -1 is returned. 85091.130Smgorny */ 85101.130Smgornystatic ssize_t core_find_note(const char *core_path, 85111.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 85121.130Smgorny{ 85131.130Smgorny int core_fd; 85141.130Smgorny Elf *core_elf; 85151.130Smgorny size_t core_numhdr, i; 85161.130Smgorny ssize_t ret = -1; 85171.130Smgorny /* note: we assume note name will be null-terminated */ 85181.130Smgorny size_t name_len = strlen(note_name) + 1; 85191.130Smgorny 85201.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 85211.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 85221.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 85231.130Smgorny 85241.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 85251.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 85261.130Smgorny GElf_Phdr core_hdr; 85271.130Smgorny size_t offset; 85281.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 85291.130Smgorny if (core_hdr.p_type != PT_NOTE) 85301.130Smgorny continue; 85311.130Smgorny 85321.130Smgorny for (offset = core_hdr.p_offset; 85331.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 85341.130Smgorny Elf64_Nhdr note_hdr; 85351.130Smgorny char name_buf[64]; 85361.130Smgorny 85371.130Smgorny switch (gelf_getclass(core_elf)) { 85381.130Smgorny case ELFCLASS64: 85391.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 85401.130Smgorny sizeof(note_hdr), offset) 85411.130Smgorny == sizeof(note_hdr)); 85421.130Smgorny offset += sizeof(note_hdr); 85431.130Smgorny break; 85441.130Smgorny case ELFCLASS32: 85451.130Smgorny { 85461.130Smgorny Elf32_Nhdr tmp_hdr; 85471.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 85481.130Smgorny sizeof(tmp_hdr), offset) 85491.130Smgorny == sizeof(tmp_hdr)); 85501.130Smgorny offset += sizeof(tmp_hdr); 85511.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 85521.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 85531.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 85541.130Smgorny } 85551.130Smgorny break; 85561.130Smgorny } 85571.130Smgorny 85581.130Smgorny /* indicates end of notes */ 85591.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 85601.130Smgorny break; 85611.130Smgorny if (note_hdr.n_namesz == name_len && 85621.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 85631.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 85641.130Smgorny note_hdr.n_namesz, offset) 85651.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 85661.130Smgorny 85671.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 85681.130Smgorny note_hdr.n_type == note_type) 85691.130Smgorny ret = note_hdr.n_descsz; 85701.130Smgorny } 85711.130Smgorny 85721.130Smgorny offset += note_hdr.n_namesz; 85731.130Smgorny /* fix to alignment */ 85741.146Smgorny offset = roundup(offset, core_hdr.p_align); 85751.130Smgorny 85761.130Smgorny /* if name & type matched above */ 85771.130Smgorny if (ret != -1) { 85781.130Smgorny ssize_t read_len = MIN(buf_len, 85791.130Smgorny note_hdr.n_descsz); 85801.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 85811.130Smgorny read_len, offset) == read_len); 85821.130Smgorny break; 85831.130Smgorny } 85841.130Smgorny 85851.130Smgorny offset += note_hdr.n_descsz; 85861.146Smgorny /* fix to alignment */ 85871.146Smgorny offset = roundup(offset, core_hdr.p_align); 85881.130Smgorny } 85891.130Smgorny } 85901.130Smgorny 85911.130Smgorny elf_end(core_elf); 85921.130Smgorny close(core_fd); 85931.130Smgorny 85941.130Smgorny return ret; 85951.130Smgorny} 85961.130Smgorny 85971.130SmgornyATF_TC(core_dump_procinfo); 85981.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 85991.130Smgorny{ 86001.130Smgorny atf_tc_set_md_var(tc, "descr", 86011.130Smgorny "Trigger a core dump and verify its contents."); 86021.130Smgorny} 86031.130Smgorny 86041.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 86051.130Smgorny{ 86061.130Smgorny const int exitval = 5; 86071.130Smgorny pid_t child, wpid; 86081.130Smgorny#if defined(TWAIT_HAVE_STATUS) 86091.130Smgorny const int sigval = SIGTRAP; 86101.130Smgorny int status; 86111.130Smgorny#endif 86121.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 86131.130Smgorny int core_fd; 86141.130Smgorny struct netbsd_elfcore_procinfo procinfo; 86151.130Smgorny 86161.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 86171.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 86181.130Smgorny if (child == 0) { 86191.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 86201.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 86211.130Smgorny 86221.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 86231.130Smgorny trigger_trap(); 86241.130Smgorny 86251.130Smgorny DPRINTF("Before exiting of the child process\n"); 86261.130Smgorny _exit(exitval); 86271.130Smgorny } 86281.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 86291.130Smgorny 86301.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 86311.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 86321.130Smgorny 86331.130Smgorny validate_status_stopped(status, sigval); 86341.130Smgorny 86351.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 86361.130Smgorny close(core_fd); 86371.130Smgorny 86381.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 86391.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 86401.130Smgorny != -1); 86411.130Smgorny 86421.130Smgorny DPRINTF("Read core file\n"); 86431.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 86441.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 86451.130Smgorny sizeof(procinfo)); 86461.130Smgorny 86471.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 86481.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 86491.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 86501.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 86511.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 86521.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 86531.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 86541.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 86551.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 86561.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 86571.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 86581.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 86591.130Smgorny ATF_CHECK_EQ(procinfo.cpi_siglwp, 1); 86601.130Smgorny 86611.130Smgorny unlink(core_path); 86621.130Smgorny 86631.130Smgorny DPRINTF("Before resuming the child process where it left off and " 86641.130Smgorny "without signal to be sent\n"); 86651.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 86661.130Smgorny 86671.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 86681.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 86691.130Smgorny 86701.130Smgorny validate_status_exited(status, exitval); 86711.130Smgorny 86721.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 86731.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 86741.130Smgorny} 86751.130Smgorny 86761.130Smgorny/// ---------------------------------------------------------------------------- 86771.130Smgorny 86781.138Smgorny#if defined(TWAIT_HAVE_STATUS) 86791.138Smgorny 86801.160Smgorny#define THREAD_CONCURRENT_BREAKPOINT_NUM 50 86811.156Smgorny#define THREAD_CONCURRENT_SIGNALS_NUM 50 86821.161Smgorny#define THREAD_CONCURRENT_WATCHPOINT_NUM 50 86831.138Smgorny 86841.138Smgorny/* List of signals to use for the test */ 86851.138Smgornyconst int thread_concurrent_signals_list[] = { 86861.138Smgorny SIGIO, 86871.138Smgorny SIGXCPU, 86881.138Smgorny SIGXFSZ, 86891.138Smgorny SIGVTALRM, 86901.138Smgorny SIGPROF, 86911.138Smgorny SIGWINCH, 86921.138Smgorny SIGINFO, 86931.138Smgorny SIGUSR1, 86941.138Smgorny SIGUSR2 86951.138Smgorny}; 86961.138Smgorny 86971.157Smgornyenum thread_concurrent_signal_handling { 86981.157Smgorny /* the signal is discarded by debugger */ 86991.157Smgorny TCSH_DISCARD, 87001.157Smgorny /* the handler is set to SIG_IGN */ 87011.157Smgorny TCSH_SIG_IGN, 87021.157Smgorny /* an actual handler is used */ 87031.157Smgorny TCSH_HANDLER 87041.157Smgorny}; 87051.157Smgorny 87061.156Smgornystatic pthread_barrier_t thread_concurrent_barrier; 87071.158Smgornystatic pthread_key_t thread_concurrent_key; 87081.161Smgornystatic uint32_t thread_concurrent_watchpoint_var = 0; 87091.138Smgorny 87101.160Smgornystatic void * 87111.160Smgornythread_concurrent_breakpoint_thread(void *arg) 87121.160Smgorny{ 87131.160Smgorny static volatile int watchme = 1; 87141.160Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 87151.160Smgorny DPRINTF("Before entering breakpoint func from LWP %d\n", _lwp_self()); 87161.160Smgorny check_happy(watchme); 87171.160Smgorny return NULL; 87181.160Smgorny} 87191.160Smgorny 87201.157Smgornystatic void 87211.157Smgornythread_concurrent_sig_handler(int sig) 87221.157Smgorny{ 87231.158Smgorny void *tls_val = pthread_getspecific(thread_concurrent_key); 87241.158Smgorny DPRINTF("Before increment, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 87251.158Smgorny FORKEE_ASSERT(pthread_setspecific(thread_concurrent_key, 87261.158Smgorny (void*)((uintptr_t)tls_val + 1)) == 0); 87271.157Smgorny} 87281.157Smgorny 87291.138Smgornystatic void * 87301.138Smgornythread_concurrent_signals_thread(void *arg) 87311.138Smgorny{ 87321.138Smgorny int sigval = thread_concurrent_signals_list[ 87331.138Smgorny _lwp_self() % __arraycount(thread_concurrent_signals_list)]; 87341.158Smgorny enum thread_concurrent_signal_handling *signal_handle = arg; 87351.158Smgorny void *tls_val; 87361.158Smgorny 87371.156Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 87381.138Smgorny DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval), 87391.138Smgorny _lwp_self()); 87401.138Smgorny pthread_kill(pthread_self(), sigval); 87411.158Smgorny if (*signal_handle == TCSH_HANDLER) { 87421.158Smgorny tls_val = pthread_getspecific(thread_concurrent_key); 87431.158Smgorny DPRINTF("After raising, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 87441.158Smgorny FORKEE_ASSERT(tls_val == (void*)1); 87451.158Smgorny } 87461.138Smgorny return NULL; 87471.138Smgorny} 87481.138Smgorny 87491.161Smgornystatic void * 87501.161Smgornythread_concurrent_watchpoint_thread(void *arg) 87511.161Smgorny{ 87521.161Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 87531.161Smgorny DPRINTF("Before modifying var from LWP %d\n", _lwp_self()); 87541.161Smgorny thread_concurrent_watchpoint_var = 1; 87551.161Smgorny return NULL; 87561.161Smgorny} 87571.161Smgorny 87581.160Smgorny#if defined(__i386__) || defined(__x86_64__) 87591.160Smgornyenum thread_concurrent_sigtrap_event { 87601.160Smgorny TCSE_UNKNOWN, 87611.161Smgorny TCSE_BREAKPOINT, 87621.161Smgorny TCSE_WATCHPOINT 87631.160Smgorny}; 87641.160Smgorny 87651.160Smgornystatic void 87661.160Smgornythread_concurrent_lwp_setup(pid_t child, lwpid_t lwpid); 87671.160Smgornystatic enum thread_concurrent_sigtrap_event 87681.160Smgornythread_concurrent_handle_sigtrap(pid_t child, ptrace_siginfo_t *info); 87691.160Smgorny#endif 87701.160Smgorny 87711.156Smgornystatic void 87721.157Smgornythread_concurrent_test(enum thread_concurrent_signal_handling signal_handle, 87731.161Smgorny int breakpoint_threads, int signal_threads, int watchpoint_threads) 87741.138Smgorny{ 87751.138Smgorny const int exitval = 5; 87761.138Smgorny const int sigval = SIGSTOP; 87771.138Smgorny pid_t child, wpid; 87781.138Smgorny int status; 87791.141Skamil struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM] 87801.141Skamil = {{0, 0}}; 87811.160Smgorny struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 87821.160Smgorny = {{0, 0}}; 87831.161Smgorny struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 87841.161Smgorny = {{0, 0}}; 87851.159Smgorny ptrace_event_t event; 87861.156Smgorny int i; 87871.156Smgorny 87881.164Skamil#if defined(HAVE_DBREGS) 87891.164Skamil if (!can_we_set_dbregs()) { 87901.164Skamil atf_tc_skip("Either run this test as root or set sysctl(3) " 87911.164Skamil "security.models.extensions.user_set_dbregs to 1"); 87921.164Skamil } 87931.164Skamil#endif 87941.164Skamil 87951.164Skamil atf_tc_skip("PR kern/54960"); 87961.157Smgorny 87971.156Smgorny /* Protect against out-of-bounds array access. */ 87981.160Smgorny ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM); 87991.156Smgorny ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM); 88001.161Smgorny ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM); 88011.138Smgorny 88021.138Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 88031.138Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 88041.138Smgorny if (child == 0) { 88051.160Smgorny pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM]; 88061.156Smgorny pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM]; 88071.161Smgorny pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM]; 88081.138Smgorny 88091.138Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 88101.138Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 88111.138Smgorny 88121.138Smgorny DPRINTF("Before raising %s from child\n", strsignal(sigval)); 88131.138Smgorny FORKEE_ASSERT(raise(sigval) == 0); 88141.138Smgorny 88151.157Smgorny if (signal_handle != TCSH_DISCARD) { 88161.157Smgorny struct sigaction sa; 88171.157Smgorny unsigned int j; 88181.157Smgorny 88191.157Smgorny memset(&sa, 0, sizeof(sa)); 88201.157Smgorny if (signal_handle == TCSH_SIG_IGN) 88211.157Smgorny sa.sa_handler = SIG_IGN; 88221.157Smgorny else 88231.157Smgorny sa.sa_handler = thread_concurrent_sig_handler; 88241.157Smgorny sigemptyset(&sa.sa_mask); 88251.157Smgorny 88261.157Smgorny for (j = 0; 88271.157Smgorny j < __arraycount(thread_concurrent_signals_list); 88281.157Smgorny j++) 88291.157Smgorny FORKEE_ASSERT(sigaction( 88301.157Smgorny thread_concurrent_signals_list[j], &sa, NULL) 88311.157Smgorny != -1); 88321.157Smgorny } 88331.157Smgorny 88341.138Smgorny DPRINTF("Before starting threads from the child\n"); 88351.138Smgorny FORKEE_ASSERT(pthread_barrier_init( 88361.156Smgorny &thread_concurrent_barrier, NULL, 88371.161Smgorny breakpoint_threads + signal_threads + watchpoint_threads) 88381.161Smgorny == 0); 88391.158Smgorny FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL) 88401.158Smgorny == 0); 88411.138Smgorny 88421.156Smgorny for (i = 0; i < signal_threads; i++) { 88431.156Smgorny FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL, 88441.158Smgorny thread_concurrent_signals_thread, 88451.158Smgorny &signal_handle) == 0); 88461.138Smgorny } 88471.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 88481.160Smgorny FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL, 88491.160Smgorny thread_concurrent_breakpoint_thread, NULL) == 0); 88501.160Smgorny } 88511.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 88521.161Smgorny FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL, 88531.161Smgorny thread_concurrent_watchpoint_thread, NULL) == 0); 88541.161Smgorny } 88551.138Smgorny 88561.138Smgorny DPRINTF("Before joining threads from the child\n"); 88571.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 88581.161Smgorny FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0); 88591.161Smgorny } 88601.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 88611.160Smgorny FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0); 88621.160Smgorny } 88631.156Smgorny for (i = 0; i < signal_threads; i++) { 88641.156Smgorny FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0); 88651.138Smgorny } 88661.138Smgorny 88671.158Smgorny FORKEE_ASSERT(pthread_key_delete(thread_concurrent_key) == 0); 88681.138Smgorny FORKEE_ASSERT(pthread_barrier_destroy( 88691.156Smgorny &thread_concurrent_barrier) == 0); 88701.138Smgorny 88711.138Smgorny DPRINTF("Before exiting of the child process\n"); 88721.138Smgorny _exit(exitval); 88731.138Smgorny } 88741.138Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 88751.138Smgorny 88761.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 88771.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 88781.138Smgorny 88791.138Smgorny validate_status_stopped(status, sigval); 88801.138Smgorny 88811.159Smgorny DPRINTF("Set LWP event mask for the child process\n"); 88821.159Smgorny memset(&event, 0, sizeof(event)); 88831.159Smgorny event.pe_set_event |= PTRACE_LWP_CREATE; 88841.159Smgorny SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event)) 88851.159Smgorny != -1); 88861.159Smgorny 88871.138Smgorny DPRINTF("Before resuming the child process where it left off\n"); 88881.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 88891.138Smgorny 88901.138Smgorny DPRINTF("Before entering signal collection loop\n"); 88911.138Smgorny while (1) { 88921.138Smgorny ptrace_siginfo_t info; 88931.138Smgorny 88941.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 88951.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 88961.138Smgorny child); 88971.138Smgorny if (WIFEXITED(status)) 88981.138Smgorny break; 88991.138Smgorny /* Note: we use validate_status_stopped() to get nice error 89001.138Smgorny * message. Signal is irrelevant since it won't be reached. 89011.138Smgorny */ 89021.138Smgorny else if (!WIFSTOPPED(status)) 89031.138Smgorny validate_status_stopped(status, 0); 89041.138Smgorny 89051.138Smgorny DPRINTF("Before calling PT_GET_SIGINFO\n"); 89061.138Smgorny SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 89071.138Smgorny sizeof(info)) != -1); 89081.138Smgorny 89091.138Smgorny DPRINTF("Received signal %d from LWP %d (wait: %d)\n", 89101.138Smgorny info.psi_siginfo.si_signo, info.psi_lwpid, 89111.138Smgorny WSTOPSIG(status)); 89121.138Smgorny 89131.159Smgorny ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status), 89141.159Smgorny "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid, 89151.159Smgorny WSTOPSIG(status), info.psi_siginfo.si_signo); 89161.159Smgorny 89171.159Smgorny if (WSTOPSIG(status) != SIGTRAP) { 89181.159Smgorny int expected_sig = 89191.159Smgorny thread_concurrent_signals_list[info.psi_lwpid % 89201.159Smgorny __arraycount(thread_concurrent_signals_list)]; 89211.159Smgorny ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig, 89221.159Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 89231.159Smgorny expected_sig, WSTOPSIG(status)); 89241.138Smgorny 89251.159Smgorny *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1; 89261.160Smgorny } else if (info.psi_siginfo.si_code == TRAP_LWP) { 89271.160Smgorny#if defined(__i386__) || defined(__x86_64__) 89281.160Smgorny thread_concurrent_lwp_setup(child, info.psi_lwpid); 89291.160Smgorny#endif 89301.159Smgorny } else { 89311.160Smgorny#if defined(__i386__) || defined(__x86_64__) 89321.160Smgorny switch (thread_concurrent_handle_sigtrap(child, &info)) { 89331.160Smgorny case TCSE_UNKNOWN: 89341.160Smgorny /* already reported inside the function */ 89351.160Smgorny break; 89361.160Smgorny case TCSE_BREAKPOINT: 89371.160Smgorny *FIND_EVENT_COUNT(bp_counts, 89381.160Smgorny info.psi_lwpid) += 1; 89391.160Smgorny break; 89401.161Smgorny case TCSE_WATCHPOINT: 89411.161Smgorny *FIND_EVENT_COUNT(wp_counts, 89421.161Smgorny info.psi_lwpid) += 1; 89431.161Smgorny break; 89441.160Smgorny } 89451.160Smgorny#else 89461.160Smgorny ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n", 89471.160Smgorny info.psi_siginfo.si_code); 89481.160Smgorny#endif 89491.159Smgorny } 89501.138Smgorny 89511.138Smgorny DPRINTF("Before resuming the child process\n"); 89521.157Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 89531.159Smgorny signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP 89541.159Smgorny ? WSTOPSIG(status) : 0) != -1); 89551.138Smgorny } 89561.138Smgorny 89571.156Smgorny for (i = 0; i < signal_threads; i++) 89581.141Skamil ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1, 89591.141Skamil "signal_counts[%d].lec_count=%d; lec_lwp=%d", 89601.141Skamil i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 89611.156Smgorny for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++) 89621.156Smgorny ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0, 89631.156Smgorny "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d", 89641.156Smgorny i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 89651.138Smgorny 89661.160Smgorny for (i = 0; i < breakpoint_threads; i++) 89671.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1, 89681.160Smgorny "bp_counts[%d].lec_count=%d; lec_lwp=%d", 89691.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 89701.160Smgorny for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++) 89711.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0, 89721.160Smgorny "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d", 89731.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 89741.160Smgorny 89751.161Smgorny for (i = 0; i < watchpoint_threads; i++) 89761.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1, 89771.161Smgorny "wp_counts[%d].lec_count=%d; lec_lwp=%d", 89781.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 89791.161Smgorny for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++) 89801.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0, 89811.161Smgorny "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d", 89821.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 89831.161Smgorny 89841.138Smgorny validate_status_exited(status, exitval); 89851.138Smgorny} 89861.138Smgorny 89871.161Smgorny#define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr) \ 89881.156SmgornyATF_TC(test); \ 89891.156SmgornyATF_TC_HEAD(test, tc) \ 89901.156Smgorny{ \ 89911.156Smgorny atf_tc_set_md_var(tc, "descr", descr); \ 89921.156Smgorny} \ 89931.156Smgorny \ 89941.156SmgornyATF_TC_BODY(test, tc) \ 89951.156Smgorny{ \ 89961.161Smgorny thread_concurrent_test(sig_hdl, bps, sigs, wps); \ 89971.156Smgorny} 89981.156Smgorny 89991.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD, 90001.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90011.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 90021.157Smgorny "correctly"); 90031.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN, 90041.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90051.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 90061.157Smgorny "correctly and passed back to SIG_IGN handler"); 90071.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER, 90081.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90091.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 90101.157Smgorny "correctly and passed back to a handler function"); 90111.156Smgorny 90121.163Skamil#if defined(__i386__) || defined(__x86_64__) 90131.160SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD, 90141.161Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0, 90151.161Smgorny "Verify that concurrent breakpoints are reported correctly"); 90161.161SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD, 90171.161Smgorny 0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 90181.160Smgorny "Verify that concurrent breakpoints are reported correctly"); 90191.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD, 90201.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 90211.162Smgorny "Verify that concurrent breakpoints and watchpoints are reported " 90221.162Smgorny "correctly"); 90231.162Smgorny 90241.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD, 90251.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90261.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly"); 90271.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN, 90281.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90291.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 90301.162Smgorny "and passed back to SIG_IGN handler"); 90311.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER, 90321.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90331.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 90341.162Smgorny "and passed back to a handler function"); 90351.162Smgorny 90361.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD, 90371.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 90381.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly"); 90391.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN, 90401.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 90411.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 90421.162Smgorny "and passed back to SIG_IGN handler"); 90431.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER, 90441.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 90451.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 90461.162Smgorny "and passed back to a handler function"); 90471.162Smgorny 90481.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD, 90491.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 90501.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 90511.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90521.162Smgorny "correctly"); 90531.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN, 90541.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 90551.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 90561.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90571.162Smgorny "correctly and passed back to SIG_IGN handler"); 90581.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER, 90591.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 90601.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 90611.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90621.162Smgorny "correctly and passed back to a handler function"); 90631.163Skamil#endif 90641.160Smgorny 90651.138Smgorny#endif /*defined(TWAIT_HAVE_STATUS)*/ 90661.138Smgorny 90671.138Smgorny/// ---------------------------------------------------------------------------- 90681.138Smgorny 90691.1Skamil#include "t_ptrace_amd64_wait.h" 90701.1Skamil#include "t_ptrace_i386_wait.h" 90711.1Skamil#include "t_ptrace_x86_wait.h" 90721.1Skamil 90731.165Skamil/// ---------------------------------------------------------------------------- 90741.165Skamil 90751.165Skamil#else 90761.165SkamilATF_TC(dummy); 90771.165SkamilATF_TC_HEAD(dummy, tc) 90781.165Skamil{ 90791.165Skamil atf_tc_set_md_var(tc, "descr", "A dummy test"); 90801.165Skamil} 90811.165Skamil 90821.165SkamilATF_TC_BODY(dummy, tc) 90831.165Skamil{ 90841.165Skamil 90851.165Skamil // Dummy, skipped 90861.165Skamil // The ATF framework requires at least a single defined test. 90871.165Skamil} 90881.165Skamil#endif 90891.165Skamil 90901.1SkamilATF_TP_ADD_TCS(tp) 90911.1Skamil{ 90921.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 90931.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 90941.33Skamil 90951.165Skamil#ifdef ENABLE_TESTS 90961.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 90971.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 90981.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 90991.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 91001.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 91011.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 91021.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 91031.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 91041.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 91051.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 91061.33Skamil 91071.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 91081.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 91091.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 91101.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 91111.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 91121.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 91131.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 91141.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 91151.87Skamil 91161.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 91171.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 91181.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 91191.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 91201.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 91211.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 91221.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 91231.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 91241.86Skamil 91251.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 91261.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 91271.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 91281.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 91291.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 91301.59Skamil 91311.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 91321.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 91331.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 91341.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 91351.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 91361.88Skamil 91371.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 91381.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 91391.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 91401.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 91411.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 91421.88Skamil 91431.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 91441.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 91451.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 91461.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 91471.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 91481.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 91491.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 91501.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 91511.50Skamil 91521.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 91531.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 91541.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 91551.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 91561.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 91571.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 91581.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 91591.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 91601.50Skamil 91611.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 91621.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 91631.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 91641.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 91651.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 91661.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 91671.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 91681.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 91691.50Skamil 91701.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 91711.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 91721.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 91731.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 91741.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 91751.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 91761.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 91771.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 91781.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 91791.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 91801.1Skamil 91811.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 91821.37Skamil 91831.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 91841.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 91851.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 91861.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 91871.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 91881.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 91891.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 91901.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 91911.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 91921.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 91931.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 91941.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 91951.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 91961.40Skamil 91971.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 91981.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 91991.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 92001.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 92011.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 92021.41Skamil 92031.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 92041.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 92051.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 92061.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 92071.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 92081.92Skamil 92091.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 92101.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 92111.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 92121.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 92131.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 92141.92Skamil 92151.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 92161.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 92171.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 92181.43Skamil 92191.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 92201.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 92211.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 92221.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 92231.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 92241.59Skamil 92251.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92261.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 92271.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92281.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 92291.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92301.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 92311.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92321.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 92331.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92341.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 92351.94Skamil 92361.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92371.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 92381.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92391.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 92401.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92411.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 92421.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92431.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 92441.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92451.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 92461.94Skamil 92471.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 92481.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 92491.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 92501.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 92511.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 92521.51Skamil 92531.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 92541.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 92551.51Skamil 92561.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 92571.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 92581.51Skamil 92591.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92601.51Skamil tracee_sees_its_original_parent_getppid); 92611.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92621.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 92631.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92641.51Skamil tracee_sees_its_original_parent_procfs_status); 92651.1Skamil 92661.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 92671.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 92681.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 92691.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 92701.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 92711.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 92721.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 92731.1Skamil 92741.31Skamil ATF_TP_ADD_TC(tp, fork1); 92751.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 92761.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 92771.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 92781.31Skamil ATF_TP_ADD_TC(tp, fork5); 92791.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 92801.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 92811.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 92821.125Skamil ATF_TP_ADD_TC(tp, fork9); 92831.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 92841.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 92851.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 92861.125Skamil ATF_TP_ADD_TC(tp, fork13); 92871.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 92881.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 92891.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 92901.31Skamil 92911.31Skamil ATF_TP_ADD_TC(tp, vfork1); 92921.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 92931.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 92941.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 92951.31Skamil ATF_TP_ADD_TC(tp, vfork5); 92961.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 92971.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 92981.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 92991.125Skamil ATF_TP_ADD_TC(tp, vfork9); 93001.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 93011.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 93021.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 93031.125Skamil ATF_TP_ADD_TC(tp, vfork13); 93041.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 93051.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 93061.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 93071.1Skamil 93081.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 93091.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 93101.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 93111.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 93121.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 93131.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 93141.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 93151.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 93161.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 93171.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 93181.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 93191.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 93201.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 93211.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 93221.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 93231.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 93241.124Skamil 93251.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork1); 93261.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork2); 93271.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork3); 93281.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork4); 93291.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork5); 93301.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork6); 93311.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork7); 93321.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork8); 93331.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork9); 93341.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork10); 93351.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork11); 93361.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork12); 93371.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork13); 93381.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork14); 93391.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork15); 93401.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork16); 93411.149Skamil 93421.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork1); 93431.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork2); 93441.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork3); 93451.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork4); 93461.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork5); 93471.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork6); 93481.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork7); 93491.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork8); 93501.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork9); 93511.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork10); 93521.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork11); 93531.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork12); 93541.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork13); 93551.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork14); 93561.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork15); 93571.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork16); 93581.149Skamil 93591.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn1); 93601.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn2); 93611.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn3); 93621.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn4); 93631.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn5); 93641.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn6); 93651.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn7); 93661.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn8); 93671.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn9); 93681.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn10); 93691.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn11); 93701.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn12); 93711.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn13); 93721.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn14); 93731.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn15); 93741.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn16); 93751.149Skamil 93761.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 93771.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 93781.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 93791.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 93801.126Skamil 93811.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 93821.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 93831.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 93841.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 93851.116Skamil 93861.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn_detach_spawner); 93871.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork_detach_forker); 93881.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_detach_vforker); 93891.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_detach_vforkerdone); 93901.150Skamil 93911.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn_kill_spawner); 93921.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork_kill_forker); 93931.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_kill_vforker); 93941.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_kill_vforkerdone); 93951.150Skamil 93961.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 93971.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 93981.108Skamil 93991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 94001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 94011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 94021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 94031.54Skamil 94041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 94051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 94061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 94071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 94081.54Skamil 94091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 94101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 94111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 94121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 94131.54Skamil 94141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 94151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 94161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 94171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 94181.54Skamil 94191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 94201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 94211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 94221.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 94231.54Skamil 94241.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 94251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 94261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 94271.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 94281.54Skamil 94291.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 94301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 94311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 94321.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 94331.54Skamil 94341.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 94351.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 94361.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 94371.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 94381.54Skamil 94391.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 94401.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 94411.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 94421.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 94431.54Skamil 94441.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 94451.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 94461.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 94471.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 94481.1Skamil 94491.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 94501.1Skamil 94511.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 94521.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 94531.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 94541.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 94551.101Skamil 94561.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 94571.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 94581.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 94591.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 94601.101Skamil 94611.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 94621.101Skamil 94631.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 94641.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 94651.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 94661.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 94671.115Skamil 94681.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 94691.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 94701.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 94711.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 94721.115Skamil 94731.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 94741.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 94751.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 94761.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 94771.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 94781.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 94791.1Skamil 94801.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x1); 94811.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x3); 94821.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x7); 94831.147Skamil 94841.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 94851.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 94861.1Skamil 94871.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 94881.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 94891.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 94901.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 94911.1Skamil 94921.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 94931.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 94941.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 94951.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 94961.2Skamil 94971.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 94981.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 94991.95Skamil 95001.1Skamil ATF_TP_ADD_TC(tp, kill1); 95011.1Skamil ATF_TP_ADD_TC(tp, kill2); 95021.75Skamil ATF_TP_ADD_TC(tp, kill3); 95031.1Skamil 95041.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 95051.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 95061.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 95071.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 95081.77Skamil 95091.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus); 95101.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus); 95111.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus); 95121.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus); 95131.143Skamil 95141.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_sigmask); 95151.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_sigmask); 95161.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_sigmask); 95171.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_sigmask); 95181.143Skamil 95191.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_name); 95201.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_name); 95211.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_name); 95221.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_name); 95231.143Skamil 95241.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_private); 95251.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_private); 95261.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_private); 95271.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_private); 95281.143Skamil 95291.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0); 95301.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1); 95311.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2); 95321.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3); 95331.143Skamil 95341.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_sigmask); 95351.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_sigmask); 95361.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_sigmask); 95371.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_sigmask); 95381.143Skamil 95391.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_name); 95401.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_name); 95411.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_name); 95421.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_name); 95431.143Skamil 95441.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_private); 95451.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_private); 95461.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_private); 95471.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_private); 95481.143Skamil 95491.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 95501.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 95511.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 95521.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 95531.1Skamil 95541.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 95551.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 95561.79Skamil 95571.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 95581.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 95591.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 95601.1Skamil 95611.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 95621.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 95631.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 95641.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 95651.1Skamil 95661.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap); 95671.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap); 95681.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap); 95691.153Skamil 95701.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 95711.84Skamil 95721.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 95731.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 95741.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 95751.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 95761.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 95771.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 95781.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 95791.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 95801.99Skamil 95811.151Skamil ATF_TP_ADD_TC(tp, threads_and_exec); 95821.151Skamil 95831.154Skamil ATF_TP_ADD_TC(tp, suspend_no_deadlock); 95841.1Skamil 95851.155Skamil ATF_TP_ADD_TC(tp, resume); 95861.1Skamil 95871.166Skamil ATF_TP_ADD_TC(tp, syscall); 95881.166Skamil ATF_TP_ADD_TC(tp, syscall_killed_on_sce); 95891.167Skamil ATF_TP_ADD_TC(tp, syscall_signal_on_sce); 95901.167Skamil ATF_TP_ADD_TC(tp, syscall_detach_on_sce); 95911.1Skamil 95921.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 95931.1Skamil 95941.106Skamil ATF_TP_ADD_TC(tp, clone1); 95951.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 95961.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 95971.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 95981.106Skamil ATF_TP_ADD_TC(tp, clone5); 95991.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 96001.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 96011.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 96021.106Skamil 96031.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 96041.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 96051.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 96061.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 96071.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 96081.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 96091.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 96101.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 96111.106Skamil 96121.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 96131.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 96141.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 96151.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 96161.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 96171.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 96181.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 96191.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 96201.106Skamil 96211.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 96221.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 96231.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 96241.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 96251.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 96261.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 96271.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 96281.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 96291.106Skamil 96301.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 96311.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 96321.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 96331.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 96341.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 96351.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 96361.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 96371.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 96381.106Skamil 96391.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 96401.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 96411.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 96421.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 96431.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 96441.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 96451.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 96461.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 96471.106Skamil 96481.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 96491.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 96501.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 96511.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 96521.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 96531.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 96541.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 96551.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 96561.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 96571.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 96581.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 96591.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 96601.103Skamil 96611.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 96621.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 96631.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 96641.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 96651.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 96661.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 96671.107Skamil 96681.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 96691.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 96701.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 96711.122Skamil 96721.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 96731.130Smgorny 96741.138Smgorny#if defined(TWAIT_HAVE_STATUS) 96751.138Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals); 96761.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_sig_ign); 96771.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_handler); 96781.160Smgorny#if defined(__i386__) || defined(__x86_64__) 96791.160Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_breakpoints); 96801.161Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_watchpoints); 96811.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp); 96821.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig); 96831.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_sig_ign); 96841.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_handler); 96851.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig); 96861.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_sig_ign); 96871.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_handler); 96881.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig); 96891.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_sig_ign); 96901.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_handler); 96911.160Smgorny#endif 96921.138Smgorny#endif 96931.138Smgorny 96941.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 96951.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 96961.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 96971.1Skamil 96981.165Skamil#else 96991.165Skamil ATF_TP_ADD_TC(tp, dummy); 97001.165Skamil#endif 97011.165Skamil 97021.1Skamil return atf_no_error(); 97031.1Skamil} 9704