t_ptrace_wait.c revision 1.173
11.173Skamil/* $NetBSD: t_ptrace_wait.c,v 1.173 2020/04/24 12:17:45 kamil Exp $ */ 21.1Skamil 31.1Skamil/*- 41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. 51.1Skamil * All rights reserved. 61.1Skamil * 71.1Skamil * Redistribution and use in source and binary forms, with or without 81.1Skamil * modification, are permitted provided that the following conditions 91.1Skamil * are met: 101.1Skamil * 1. Redistributions of source code must retain the above copyright 111.1Skamil * notice, this list of conditions and the following disclaimer. 121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright 131.1Skamil * notice, this list of conditions and the following disclaimer in the 141.1Skamil * documentation and/or other materials provided with the distribution. 151.1Skamil * 161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Skamil * POSSIBILITY OF SUCH DAMAGE. 271.1Skamil */ 281.1Skamil 291.1Skamil#include <sys/cdefs.h> 301.173Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.173 2020/04/24 12:17:45 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.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_report_event) == 781.171Skamil sizeof(((siginfo_t *)0)->si_pe_report_event)); 791.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 801.171Skamil sizeof(((siginfo_t *)0)->si_pe_other_pid)); 811.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_lwp) == 821.171Skamil sizeof(((siginfo_t *)0)->si_pe_lwp)); 831.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 841.171Skamil sizeof(((struct ptrace_state *)0)->pe_lwp)); 851.132Skamil 861.1Skamil#include "h_macros.h" 871.1Skamil 881.1Skamil#include "t_ptrace_wait.h" 891.1Skamil#include "msg.h" 901.1Skamil 911.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 921.13Schristos strerror(errno)) 931.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 941.18Schristos "%d(%s) != %d", res, strerror(res), exp) 951.13Schristos 961.152Skamilstatic int debug = 0; 971.13Schristos 981.13Schristos#define DPRINTF(a, ...) do \ 991.123Skamil if (debug) \ 1001.142Skamil printf("%s() %d.%d %s:%d " a, \ 1011.142Skamil __func__, getpid(), _lwp_self(), __FILE__, __LINE__, ##__VA_ARGS__); \ 1021.13Schristos while (/*CONSTCOND*/0) 1031.1Skamil 1041.34Skamil/// ---------------------------------------------------------------------------- 1051.34Skamil 1061.33Skamilstatic void 1071.33Skamiltraceme_raise(int sigval) 1081.1Skamil{ 1091.1Skamil const int exitval = 5; 1101.1Skamil pid_t child, wpid; 1111.1Skamil#if defined(TWAIT_HAVE_STATUS) 1121.1Skamil int status; 1131.1Skamil#endif 1141.1Skamil 1151.133Skamil ptrace_state_t state, zero_state; 1161.133Skamil const int slen = sizeof(state); 1171.45Skamil struct ptrace_siginfo info; 1181.133Skamil memset(&zero_state, 0, sizeof(zero_state)); 1191.45Skamil memset(&info, 0, sizeof(info)); 1201.45Skamil 1211.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1221.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1231.1Skamil if (child == 0) { 1241.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1251.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1261.1Skamil 1271.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1281.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1291.1Skamil 1301.36Skamil switch (sigval) { 1311.36Skamil case SIGKILL: 1321.36Skamil /* NOTREACHED */ 1331.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1341.70Smrg __unreachable(); 1351.36Skamil default: 1361.36Skamil DPRINTF("Before exiting of the child process\n"); 1371.36Skamil _exit(exitval); 1381.36Skamil } 1391.1Skamil } 1401.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1411.1Skamil 1421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1441.1Skamil 1451.36Skamil switch (sigval) { 1461.36Skamil case SIGKILL: 1471.36Skamil validate_status_signaled(status, sigval, 0); 1481.133Skamil SYSCALL_REQUIRE( 1491.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) == -1); 1501.133Skamil 1511.36Skamil break; 1521.36Skamil default: 1531.36Skamil validate_status_stopped(status, sigval); 1541.1Skamil 1551.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1561.61Skre "child\n"); 1571.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1581.61Skre sizeof(info)) != -1); 1591.45Skamil 1601.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1611.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1621.61Skre "si_errno=%#x\n", 1631.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1641.61Skre info.psi_siginfo.si_errno); 1651.45Skamil 1661.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1671.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1681.45Skamil 1691.133Skamil DPRINTF("Assert that PT_GET_PROCESS_STATE returns non-error"); 1701.133Skamil SYSCALL_REQUIRE( 1711.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 1721.133Skamil ATF_REQUIRE(memcmp(&state, &zero_state, slen) == 0); 1731.133Skamil 1741.36Skamil DPRINTF("Before resuming the child process where it left off " 1751.36Skamil "and without signal to be sent\n"); 1761.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1771.1Skamil 1781.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1791.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1801.61Skre child); 1811.36Skamil break; 1821.36Skamil } 1831.1Skamil 1841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1851.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1861.1Skamil} 1871.1Skamil 1881.61Skre#define TRACEME_RAISE(test, sig) \ 1891.61SkreATF_TC(test); \ 1901.61SkreATF_TC_HEAD(test, tc) \ 1911.61Skre{ \ 1921.61Skre atf_tc_set_md_var(tc, "descr", \ 1931.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1941.61Skre} \ 1951.61Skre \ 1961.61SkreATF_TC_BODY(test, tc) \ 1971.61Skre{ \ 1981.61Skre \ 1991.61Skre traceme_raise(sig); \ 2001.33Skamil} 2011.33Skamil 2021.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2031.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2041.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2051.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2061.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2071.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2081.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2091.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2101.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2111.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2121.33Skamil 2131.34Skamil/// ---------------------------------------------------------------------------- 2141.1Skamil 2151.1Skamilstatic void 2161.87Skamiltraceme_raisesignal_ignored(int sigignored) 2171.87Skamil{ 2181.87Skamil const int exitval = 5; 2191.87Skamil const int sigval = SIGSTOP; 2201.87Skamil pid_t child, wpid; 2211.87Skamil struct sigaction sa; 2221.87Skamil#if defined(TWAIT_HAVE_STATUS) 2231.87Skamil int status; 2241.87Skamil#endif 2251.87Skamil struct ptrace_siginfo info; 2261.87Skamil 2271.87Skamil memset(&info, 0, sizeof(info)); 2281.87Skamil 2291.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2301.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2311.87Skamil if (child == 0) { 2321.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2331.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2341.87Skamil 2351.87Skamil memset(&sa, 0, sizeof(sa)); 2361.87Skamil sa.sa_handler = SIG_IGN; 2371.87Skamil sigemptyset(&sa.sa_mask); 2381.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2391.87Skamil 2401.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2411.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2421.87Skamil 2431.87Skamil DPRINTF("Before raising %s from child\n", 2441.87Skamil strsignal(sigignored)); 2451.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2461.87Skamil 2471.87Skamil DPRINTF("Before exiting of the child process\n"); 2481.87Skamil _exit(exitval); 2491.87Skamil } 2501.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2511.87Skamil 2521.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2531.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2541.87Skamil 2551.87Skamil validate_status_stopped(status, sigval); 2561.87Skamil 2571.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2581.87Skamil SYSCALL_REQUIRE( 2591.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2601.87Skamil 2611.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2621.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2631.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2641.87Skamil info.psi_siginfo.si_errno); 2651.87Skamil 2661.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2671.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2681.87Skamil 2691.87Skamil DPRINTF("Before resuming the child process where it left off and " 2701.87Skamil "without signal to be sent\n"); 2711.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2721.87Skamil 2731.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2741.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2751.87Skamil 2761.87Skamil validate_status_stopped(status, sigignored); 2771.87Skamil 2781.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2791.87Skamil SYSCALL_REQUIRE( 2801.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2811.87Skamil 2821.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2831.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2841.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2851.87Skamil info.psi_siginfo.si_errno); 2861.87Skamil 2871.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2881.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2891.87Skamil 2901.87Skamil DPRINTF("Before resuming the child process where it left off and " 2911.87Skamil "without signal to be sent\n"); 2921.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2931.87Skamil 2941.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2951.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2961.87Skamil 2971.87Skamil validate_status_exited(status, exitval); 2981.87Skamil 2991.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3001.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3011.87Skamil} 3021.87Skamil 3031.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3041.87SkamilATF_TC(test); \ 3051.87SkamilATF_TC_HEAD(test, tc) \ 3061.87Skamil{ \ 3071.87Skamil atf_tc_set_md_var(tc, "descr", \ 3081.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3091.87Skamil "does not stop tracer from catching this raised signal"); \ 3101.87Skamil} \ 3111.87Skamil \ 3121.87SkamilATF_TC_BODY(test, tc) \ 3131.87Skamil{ \ 3141.87Skamil \ 3151.87Skamil traceme_raisesignal_ignored(sig); \ 3161.87Skamil} 3171.87Skamil 3181.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3191.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3201.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3211.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3221.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3231.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3241.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3251.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3261.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3271.87Skamil 3281.87Skamil/// ---------------------------------------------------------------------------- 3291.87Skamil 3301.87Skamilstatic void 3311.86Skamiltraceme_raisesignal_masked(int sigmasked) 3321.86Skamil{ 3331.86Skamil const int exitval = 5; 3341.86Skamil const int sigval = SIGSTOP; 3351.86Skamil pid_t child, wpid; 3361.86Skamil#if defined(TWAIT_HAVE_STATUS) 3371.86Skamil int status; 3381.86Skamil#endif 3391.86Skamil sigset_t intmask; 3401.86Skamil struct ptrace_siginfo info; 3411.86Skamil 3421.86Skamil memset(&info, 0, sizeof(info)); 3431.86Skamil 3441.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3451.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3461.86Skamil if (child == 0) { 3471.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3481.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3491.86Skamil 3501.86Skamil sigemptyset(&intmask); 3511.86Skamil sigaddset(&intmask, sigmasked); 3521.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3531.86Skamil 3541.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3551.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3561.86Skamil 3571.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3581.86Skamil strsignal(sigmasked)); 3591.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3601.86Skamil 3611.86Skamil DPRINTF("Before exiting of the child process\n"); 3621.86Skamil _exit(exitval); 3631.86Skamil } 3641.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3651.86Skamil 3661.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3671.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3681.86Skamil 3691.86Skamil validate_status_stopped(status, sigval); 3701.86Skamil 3711.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3721.86Skamil SYSCALL_REQUIRE( 3731.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3741.86Skamil 3751.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3761.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3771.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3781.86Skamil info.psi_siginfo.si_errno); 3791.86Skamil 3801.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3811.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3821.86Skamil 3831.86Skamil DPRINTF("Before resuming the child process where it left off and " 3841.86Skamil "without signal to be sent\n"); 3851.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3861.86Skamil 3871.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3881.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3891.86Skamil 3901.86Skamil validate_status_exited(status, exitval); 3911.86Skamil 3921.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3931.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3941.86Skamil} 3951.86Skamil 3961.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3971.86SkamilATF_TC(test); \ 3981.86SkamilATF_TC_HEAD(test, tc) \ 3991.86Skamil{ \ 4001.86Skamil atf_tc_set_md_var(tc, "descr", \ 4011.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4021.86Skamil "stops tracer from catching this raised signal"); \ 4031.86Skamil} \ 4041.86Skamil \ 4051.86SkamilATF_TC_BODY(test, tc) \ 4061.86Skamil{ \ 4071.86Skamil \ 4081.86Skamil traceme_raisesignal_masked(sig); \ 4091.86Skamil} 4101.86Skamil 4111.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4121.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4131.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4141.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4151.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4161.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4171.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4181.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4191.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4201.86Skamil 4211.86Skamil/// ---------------------------------------------------------------------------- 4221.86Skamil 4231.86Skamilstatic void 4241.59Skamiltraceme_crash(int sig) 4251.59Skamil{ 4261.59Skamil pid_t child, wpid; 4271.59Skamil#if defined(TWAIT_HAVE_STATUS) 4281.59Skamil int status; 4291.59Skamil#endif 4301.59Skamil struct ptrace_siginfo info; 4311.61Skre 4321.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4331.71Skamil if (sig == SIGILL) 4341.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4351.71Skamil#endif 4361.71Skamil 4371.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4381.114Skamil atf_tc_skip("FP exceptions are not supported"); 4391.114Skamil 4401.59Skamil memset(&info, 0, sizeof(info)); 4411.59Skamil 4421.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4431.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4441.59Skamil if (child == 0) { 4451.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4461.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4471.59Skamil 4481.59Skamil DPRINTF("Before executing a trap\n"); 4491.59Skamil switch (sig) { 4501.59Skamil case SIGTRAP: 4511.59Skamil trigger_trap(); 4521.59Skamil break; 4531.59Skamil case SIGSEGV: 4541.59Skamil trigger_segv(); 4551.59Skamil break; 4561.59Skamil case SIGILL: 4571.59Skamil trigger_ill(); 4581.59Skamil break; 4591.59Skamil case SIGFPE: 4601.59Skamil trigger_fpe(); 4611.59Skamil break; 4621.59Skamil case SIGBUS: 4631.59Skamil trigger_bus(); 4641.59Skamil break; 4651.59Skamil default: 4661.59Skamil /* NOTREACHED */ 4671.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4681.59Skamil } 4691.59Skamil 4701.59Skamil /* NOTREACHED */ 4711.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4721.59Skamil } 4731.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4741.59Skamil 4751.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4761.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4771.59Skamil 4781.59Skamil validate_status_stopped(status, sig); 4791.59Skamil 4801.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4811.61Skre SYSCALL_REQUIRE( 4821.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4831.59Skamil 4841.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4851.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4861.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4871.61Skre info.psi_siginfo.si_errno); 4881.59Skamil 4891.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4901.59Skamil switch (sig) { 4911.59Skamil case SIGTRAP: 4921.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4931.59Skamil break; 4941.59Skamil case SIGSEGV: 4951.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4961.59Skamil break; 4971.71Skamil case SIGILL: 4981.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 4991.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5001.71Skamil break; 5011.59Skamil case SIGFPE: 5021.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5031.59Skamil break; 5041.59Skamil case SIGBUS: 5051.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5061.59Skamil break; 5071.59Skamil } 5081.59Skamil 5091.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5101.59Skamil 5111.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5121.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5131.59Skamil 5141.59Skamil validate_status_signaled(status, SIGKILL, 0); 5151.59Skamil 5161.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5171.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5181.59Skamil} 5191.59Skamil 5201.61Skre#define TRACEME_CRASH(test, sig) \ 5211.61SkreATF_TC(test); \ 5221.61SkreATF_TC_HEAD(test, tc) \ 5231.61Skre{ \ 5241.61Skre atf_tc_set_md_var(tc, "descr", \ 5251.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5261.61Skre} \ 5271.61Skre \ 5281.61SkreATF_TC_BODY(test, tc) \ 5291.61Skre{ \ 5301.61Skre \ 5311.61Skre traceme_crash(sig); \ 5321.59Skamil} 5331.59Skamil 5341.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5351.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5361.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5371.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5381.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5391.59Skamil 5401.59Skamil/// ---------------------------------------------------------------------------- 5411.59Skamil 5421.59Skamilstatic void 5431.88Skamiltraceme_signalmasked_crash(int sig) 5441.88Skamil{ 5451.89Skamil const int sigval = SIGSTOP; 5461.88Skamil pid_t child, wpid; 5471.88Skamil#if defined(TWAIT_HAVE_STATUS) 5481.88Skamil int status; 5491.88Skamil#endif 5501.88Skamil struct ptrace_siginfo info; 5511.88Skamil sigset_t intmask; 5521.89Skamil struct kinfo_proc2 kp; 5531.89Skamil size_t len = sizeof(kp); 5541.89Skamil 5551.89Skamil int name[6]; 5561.89Skamil const size_t namelen = __arraycount(name); 5571.89Skamil ki_sigset_t kp_sigmask; 5581.88Skamil 5591.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5601.88Skamil if (sig == SIGILL) 5611.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5621.88Skamil#endif 5631.88Skamil 5641.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5651.114Skamil atf_tc_skip("FP exceptions are not supported"); 5661.114Skamil 5671.88Skamil memset(&info, 0, sizeof(info)); 5681.88Skamil 5691.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5701.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5711.88Skamil if (child == 0) { 5721.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5731.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5741.88Skamil 5751.88Skamil sigemptyset(&intmask); 5761.88Skamil sigaddset(&intmask, sig); 5771.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5781.88Skamil 5791.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5801.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5811.89Skamil 5821.88Skamil DPRINTF("Before executing a trap\n"); 5831.88Skamil switch (sig) { 5841.88Skamil case SIGTRAP: 5851.88Skamil trigger_trap(); 5861.88Skamil break; 5871.88Skamil case SIGSEGV: 5881.88Skamil trigger_segv(); 5891.88Skamil break; 5901.88Skamil case SIGILL: 5911.88Skamil trigger_ill(); 5921.88Skamil break; 5931.88Skamil case SIGFPE: 5941.88Skamil trigger_fpe(); 5951.88Skamil break; 5961.88Skamil case SIGBUS: 5971.88Skamil trigger_bus(); 5981.88Skamil break; 5991.88Skamil default: 6001.88Skamil /* NOTREACHED */ 6011.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6021.88Skamil } 6031.88Skamil 6041.88Skamil /* NOTREACHED */ 6051.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6061.88Skamil } 6071.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6081.88Skamil 6091.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6101.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6111.88Skamil 6121.89Skamil validate_status_stopped(status, sigval); 6131.89Skamil 6141.89Skamil name[0] = CTL_KERN, 6151.89Skamil name[1] = KERN_PROC2, 6161.89Skamil name[2] = KERN_PROC_PID; 6171.89Skamil name[3] = child; 6181.89Skamil name[4] = sizeof(kp); 6191.89Skamil name[5] = 1; 6201.89Skamil 6211.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6221.89Skamil 6231.89Skamil kp_sigmask = kp.p_sigmask; 6241.89Skamil 6251.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6261.89Skamil SYSCALL_REQUIRE( 6271.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6281.89Skamil 6291.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6301.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6311.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6321.89Skamil info.psi_siginfo.si_errno); 6331.89Skamil 6341.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6351.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6361.89Skamil 6371.89Skamil DPRINTF("Before resuming the child process where it left off and " 6381.89Skamil "without signal to be sent\n"); 6391.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6401.89Skamil 6411.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6421.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6431.89Skamil 6441.88Skamil validate_status_stopped(status, sig); 6451.88Skamil 6461.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6471.88Skamil SYSCALL_REQUIRE( 6481.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6491.88Skamil 6501.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6511.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6521.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6531.88Skamil info.psi_siginfo.si_errno); 6541.88Skamil 6551.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6561.89Skamil 6571.89Skamil DPRINTF("kp_sigmask=" 6581.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6591.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6601.89Skamil kp_sigmask.__bits[3]); 6611.89Skamil 6621.89Skamil DPRINTF("kp.p_sigmask=" 6631.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6641.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6651.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6661.89Skamil 6671.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6681.89Skamil 6691.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6701.88Skamil switch (sig) { 6711.88Skamil case SIGTRAP: 6721.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6731.88Skamil break; 6741.88Skamil case SIGSEGV: 6751.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6761.88Skamil break; 6771.88Skamil case SIGILL: 6781.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6791.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6801.88Skamil break; 6811.88Skamil case SIGFPE: 6821.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6831.88Skamil break; 6841.88Skamil case SIGBUS: 6851.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6861.88Skamil break; 6871.88Skamil } 6881.88Skamil 6891.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6901.88Skamil 6911.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6921.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6931.88Skamil 6941.88Skamil validate_status_signaled(status, SIGKILL, 0); 6951.88Skamil 6961.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6971.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6981.88Skamil} 6991.88Skamil 7001.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7011.88SkamilATF_TC(test); \ 7021.88SkamilATF_TC_HEAD(test, tc) \ 7031.88Skamil{ \ 7041.88Skamil atf_tc_set_md_var(tc, "descr", \ 7051.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7061.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7071.88Skamil} \ 7081.88Skamil \ 7091.88SkamilATF_TC_BODY(test, tc) \ 7101.88Skamil{ \ 7111.88Skamil \ 7121.88Skamil traceme_signalmasked_crash(sig); \ 7131.88Skamil} 7141.88Skamil 7151.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7161.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7171.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7181.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7191.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7201.88Skamil 7211.88Skamil/// ---------------------------------------------------------------------------- 7221.88Skamil 7231.88Skamilstatic void 7241.88Skamiltraceme_signalignored_crash(int sig) 7251.88Skamil{ 7261.90Skamil const int sigval = SIGSTOP; 7271.88Skamil pid_t child, wpid; 7281.88Skamil#if defined(TWAIT_HAVE_STATUS) 7291.88Skamil int status; 7301.88Skamil#endif 7311.88Skamil struct sigaction sa; 7321.88Skamil struct ptrace_siginfo info; 7331.90Skamil struct kinfo_proc2 kp; 7341.90Skamil size_t len = sizeof(kp); 7351.90Skamil 7361.90Skamil int name[6]; 7371.90Skamil const size_t namelen = __arraycount(name); 7381.90Skamil ki_sigset_t kp_sigignore; 7391.88Skamil 7401.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7411.88Skamil if (sig == SIGILL) 7421.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7431.88Skamil#endif 7441.88Skamil 7451.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7461.114Skamil atf_tc_skip("FP exceptions are not supported"); 7471.114Skamil 7481.88Skamil memset(&info, 0, sizeof(info)); 7491.88Skamil 7501.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7511.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7521.88Skamil if (child == 0) { 7531.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7541.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7551.88Skamil 7561.88Skamil memset(&sa, 0, sizeof(sa)); 7571.88Skamil sa.sa_handler = SIG_IGN; 7581.88Skamil sigemptyset(&sa.sa_mask); 7591.88Skamil 7601.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7611.88Skamil 7621.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7631.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7641.90Skamil 7651.88Skamil DPRINTF("Before executing a trap\n"); 7661.88Skamil switch (sig) { 7671.88Skamil case SIGTRAP: 7681.88Skamil trigger_trap(); 7691.88Skamil break; 7701.88Skamil case SIGSEGV: 7711.88Skamil trigger_segv(); 7721.88Skamil break; 7731.88Skamil case SIGILL: 7741.88Skamil trigger_ill(); 7751.88Skamil break; 7761.88Skamil case SIGFPE: 7771.88Skamil trigger_fpe(); 7781.88Skamil break; 7791.88Skamil case SIGBUS: 7801.88Skamil trigger_bus(); 7811.88Skamil break; 7821.88Skamil default: 7831.88Skamil /* NOTREACHED */ 7841.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7851.88Skamil } 7861.88Skamil 7871.88Skamil /* NOTREACHED */ 7881.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7891.88Skamil } 7901.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7911.88Skamil 7921.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7931.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7941.88Skamil 7951.90Skamil validate_status_stopped(status, sigval); 7961.90Skamil 7971.90Skamil name[0] = CTL_KERN, 7981.90Skamil name[1] = KERN_PROC2, 7991.90Skamil name[2] = KERN_PROC_PID; 8001.90Skamil name[3] = child; 8011.90Skamil name[4] = sizeof(kp); 8021.90Skamil name[5] = 1; 8031.90Skamil 8041.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8051.90Skamil 8061.90Skamil kp_sigignore = kp.p_sigignore; 8071.90Skamil 8081.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8091.90Skamil SYSCALL_REQUIRE( 8101.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8111.90Skamil 8121.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8131.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8141.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8151.90Skamil info.psi_siginfo.si_errno); 8161.90Skamil 8171.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8181.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8191.90Skamil 8201.90Skamil DPRINTF("Before resuming the child process where it left off and " 8211.90Skamil "without signal to be sent\n"); 8221.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8231.90Skamil 8241.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8251.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8261.90Skamil 8271.88Skamil validate_status_stopped(status, sig); 8281.88Skamil 8291.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8301.88Skamil SYSCALL_REQUIRE( 8311.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8321.88Skamil 8331.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8341.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8351.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8361.88Skamil info.psi_siginfo.si_errno); 8371.88Skamil 8381.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8391.90Skamil 8401.90Skamil DPRINTF("kp_sigignore=" 8411.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8421.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8431.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8441.90Skamil 8451.90Skamil DPRINTF("kp.p_sigignore=" 8461.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8471.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8481.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8491.90Skamil 8501.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8511.90Skamil 8521.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8531.88Skamil switch (sig) { 8541.88Skamil case SIGTRAP: 8551.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8561.88Skamil break; 8571.88Skamil case SIGSEGV: 8581.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8591.88Skamil break; 8601.88Skamil case SIGILL: 8611.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8621.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8631.88Skamil break; 8641.88Skamil case SIGFPE: 8651.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8661.88Skamil break; 8671.88Skamil case SIGBUS: 8681.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8691.88Skamil break; 8701.88Skamil } 8711.88Skamil 8721.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8731.88Skamil 8741.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8751.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8761.88Skamil 8771.88Skamil validate_status_signaled(status, SIGKILL, 0); 8781.88Skamil 8791.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8801.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8811.88Skamil} 8821.88Skamil 8831.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8841.88SkamilATF_TC(test); \ 8851.88SkamilATF_TC_HEAD(test, tc) \ 8861.88Skamil{ \ 8871.88Skamil atf_tc_set_md_var(tc, "descr", \ 8881.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8891.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8901.88Skamil} \ 8911.88Skamil \ 8921.88SkamilATF_TC_BODY(test, tc) \ 8931.88Skamil{ \ 8941.88Skamil \ 8951.88Skamil traceme_signalignored_crash(sig); \ 8961.88Skamil} 8971.88Skamil 8981.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8991.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9001.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9011.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9021.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9031.88Skamil 9041.88Skamil/// ---------------------------------------------------------------------------- 9051.88Skamil 9061.88Skamilstatic void 9071.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9081.1Skamil{ 9091.1Skamil const int exitval = 5; 9101.34Skamil const int sigval = SIGSTOP; 9111.1Skamil pid_t child, wpid; 9121.1Skamil struct sigaction sa; 9131.1Skamil#if defined(TWAIT_HAVE_STATUS) 9141.1Skamil int status; 9151.1Skamil#endif 9161.61Skre struct ptrace_siginfo info; 9171.1Skamil 9181.45Skamil memset(&info, 0, sizeof(info)); 9191.45Skamil 9201.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9211.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9221.1Skamil if (child == 0) { 9231.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9241.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9251.1Skamil 9261.34Skamil sa.sa_handler = sah; 9271.1Skamil sa.sa_flags = SA_SIGINFO; 9281.1Skamil sigemptyset(&sa.sa_mask); 9291.1Skamil 9301.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9311.1Skamil 9321.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9331.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9341.1Skamil 9351.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9361.1Skamil 9371.13Schristos DPRINTF("Before exiting of the child process\n"); 9381.1Skamil _exit(exitval); 9391.1Skamil } 9401.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9411.1Skamil 9421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9441.1Skamil 9451.1Skamil validate_status_stopped(status, sigval); 9461.1Skamil 9471.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9481.61Skre SYSCALL_REQUIRE( 9491.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9501.45Skamil 9511.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9521.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9531.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9541.45Skamil info.psi_siginfo.si_errno); 9551.45Skamil 9561.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9571.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9581.45Skamil 9591.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9601.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9611.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9621.1Skamil 9631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9651.1Skamil 9661.1Skamil validate_status_exited(status, exitval); 9671.1Skamil 9681.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9701.1Skamil} 9711.1Skamil 9721.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9731.61SkreATF_TC(test); \ 9741.61SkreATF_TC_HEAD(test, tc) \ 9751.61Skre{ \ 9761.61Skre atf_tc_set_md_var(tc, "descr", \ 9771.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9781.61Skre "handled correctly and caught by a signal handler"); \ 9791.61Skre} \ 9801.61Skre \ 9811.61Skrestatic int test##_caught = 0; \ 9821.61Skre \ 9831.61Skrestatic void \ 9841.61Skretest##_sighandler(int arg) \ 9851.61Skre{ \ 9861.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9871.61Skre \ 9881.61Skre ++ test##_caught; \ 9891.61Skre} \ 9901.61Skre \ 9911.61SkreATF_TC_BODY(test, tc) \ 9921.61Skre{ \ 9931.61Skre \ 9941.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9951.34Skamil} 9961.34Skamil 9971.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9981.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9991.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10001.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10011.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10021.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10031.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10041.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10051.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10061.34Skamil 10071.34Skamil/// ---------------------------------------------------------------------------- 10081.34Skamil 10091.35Skamilstatic void 10101.50Skamiltraceme_sendsignal_masked(int sigsent) 10111.50Skamil{ 10121.50Skamil const int exitval = 5; 10131.50Skamil const int sigval = SIGSTOP; 10141.50Skamil pid_t child, wpid; 10151.50Skamil sigset_t set; 10161.50Skamil#if defined(TWAIT_HAVE_STATUS) 10171.50Skamil int status; 10181.50Skamil#endif 10191.61Skre struct ptrace_siginfo info; 10201.50Skamil 10211.50Skamil memset(&info, 0, sizeof(info)); 10221.50Skamil 10231.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10241.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10251.50Skamil if (child == 0) { 10261.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10271.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10281.50Skamil 10291.50Skamil sigemptyset(&set); 10301.50Skamil sigaddset(&set, sigsent); 10311.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10321.50Skamil 10331.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10341.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10351.50Skamil 10361.50Skamil _exit(exitval); 10371.50Skamil } 10381.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10391.50Skamil 10401.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10411.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10421.50Skamil 10431.50Skamil validate_status_stopped(status, sigval); 10441.50Skamil 10451.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10461.61Skre SYSCALL_REQUIRE( 10471.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10481.50Skamil 10491.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10501.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10511.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10521.50Skamil info.psi_siginfo.si_errno); 10531.50Skamil 10541.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10551.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10561.50Skamil 10571.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10581.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10591.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10601.50Skamil 10611.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10621.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10631.50Skamil 10641.50Skamil validate_status_exited(status, exitval); 10651.50Skamil 10661.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10671.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10681.50Skamil} 10691.50Skamil 10701.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10711.61SkreATF_TC(test); \ 10721.61SkreATF_TC_HEAD(test, tc) \ 10731.61Skre{ \ 10741.61Skre atf_tc_set_md_var(tc, "descr", \ 10751.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10761.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10771.61Skre} \ 10781.61Skre \ 10791.61SkreATF_TC_BODY(test, tc) \ 10801.61Skre{ \ 10811.61Skre \ 10821.61Skre traceme_sendsignal_masked(sig); \ 10831.50Skamil} 10841.50Skamil 10851.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10861.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10871.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10881.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10891.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10901.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10911.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10921.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10931.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10941.50Skamil 10951.50Skamil/// ---------------------------------------------------------------------------- 10961.50Skamil 10971.50Skamilstatic void 10981.50Skamiltraceme_sendsignal_ignored(int sigsent) 10991.50Skamil{ 11001.50Skamil const int exitval = 5; 11011.50Skamil const int sigval = SIGSTOP; 11021.50Skamil pid_t child, wpid; 11031.50Skamil struct sigaction sa; 11041.50Skamil#if defined(TWAIT_HAVE_STATUS) 11051.50Skamil int status; 11061.50Skamil#endif 11071.61Skre struct ptrace_siginfo info; 11081.50Skamil 11091.50Skamil memset(&info, 0, sizeof(info)); 11101.50Skamil 11111.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11121.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11131.50Skamil if (child == 0) { 11141.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11151.61Skre 11161.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11171.50Skamil 11181.50Skamil memset(&sa, 0, sizeof(sa)); 11191.50Skamil sa.sa_handler = SIG_IGN; 11201.50Skamil sigemptyset(&sa.sa_mask); 11211.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11221.50Skamil 11231.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11241.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11251.50Skamil 11261.50Skamil _exit(exitval); 11271.50Skamil } 11281.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11291.50Skamil 11301.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11311.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11321.50Skamil 11331.50Skamil validate_status_stopped(status, sigval); 11341.50Skamil 11351.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11361.61Skre SYSCALL_REQUIRE( 11371.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11381.50Skamil 11391.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11401.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11411.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11421.50Skamil info.psi_siginfo.si_errno); 11431.50Skamil 11441.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11451.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11461.50Skamil 11471.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11481.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11491.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11501.50Skamil 11511.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11521.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11531.50Skamil 11541.50Skamil validate_status_exited(status, exitval); 11551.50Skamil 11561.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11571.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11581.50Skamil} 11591.50Skamil 11601.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11611.61SkreATF_TC(test); \ 11621.61SkreATF_TC_HEAD(test, tc) \ 11631.61Skre{ \ 11641.61Skre atf_tc_set_md_var(tc, "descr", \ 11651.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11661.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11671.61Skre} \ 11681.61Skre \ 11691.61SkreATF_TC_BODY(test, tc) \ 11701.61Skre{ \ 11711.61Skre \ 11721.61Skre traceme_sendsignal_ignored(sig); \ 11731.50Skamil} 11741.50Skamil 11751.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11761.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11771.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11781.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11791.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11801.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11811.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11821.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11831.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11841.50Skamil 11851.50Skamil/// ---------------------------------------------------------------------------- 11861.50Skamil 11871.50Skamilstatic void 11881.50Skamiltraceme_sendsignal_simple(int sigsent) 11891.1Skamil{ 11901.35Skamil const int sigval = SIGSTOP; 11911.35Skamil int exitval = 0; 11921.1Skamil pid_t child, wpid; 11931.1Skamil#if defined(TWAIT_HAVE_STATUS) 11941.1Skamil int status; 11951.85Skamil int expect_core; 11961.85Skamil 11971.85Skamil switch (sigsent) { 11981.85Skamil case SIGABRT: 11991.85Skamil case SIGTRAP: 12001.85Skamil case SIGBUS: 12011.85Skamil case SIGILL: 12021.85Skamil case SIGFPE: 12031.85Skamil case SIGSEGV: 12041.85Skamil expect_core = 1; 12051.85Skamil break; 12061.85Skamil default: 12071.85Skamil expect_core = 0; 12081.85Skamil break; 12091.85Skamil } 12101.1Skamil#endif 12111.61Skre struct ptrace_siginfo info; 12121.1Skamil 12131.45Skamil memset(&info, 0, sizeof(info)); 12141.45Skamil 12151.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12161.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12171.1Skamil if (child == 0) { 12181.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12191.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12201.1Skamil 12211.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12221.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12231.1Skamil 12241.35Skamil switch (sigsent) { 12251.35Skamil case SIGCONT: 12261.48Skamil case SIGSTOP: 12271.35Skamil _exit(exitval); 12281.35Skamil default: 12291.35Skamil /* NOTREACHED */ 12301.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12311.35Skamil } 12321.1Skamil } 12331.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12341.1Skamil 12351.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12361.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12371.1Skamil 12381.1Skamil validate_status_stopped(status, sigval); 12391.1Skamil 12401.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12411.61Skre SYSCALL_REQUIRE( 12421.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12431.45Skamil 12441.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12451.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12461.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12471.45Skamil info.psi_siginfo.si_errno); 12481.45Skamil 12491.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12501.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12511.45Skamil 12521.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12531.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12541.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12551.1Skamil 12561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12581.1Skamil 12591.35Skamil switch (sigsent) { 12601.48Skamil case SIGSTOP: 12611.48Skamil validate_status_stopped(status, sigsent); 12621.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12631.61Skre "child\n"); 12641.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12651.61Skre sizeof(info)) != -1); 12661.48Skamil 12671.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12681.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12691.61Skre "si_errno=%#x\n", 12701.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12711.61Skre info.psi_siginfo.si_errno); 12721.48Skamil 12731.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12741.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12751.48Skamil 12761.48Skamil DPRINTF("Before resuming the child process where it left off " 12771.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12781.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12791.48Skamil 12801.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12811.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12821.61Skre child); 12831.48Skamil /* FALLTHROUGH */ 12841.35Skamil case SIGCONT: 12851.35Skamil validate_status_exited(status, exitval); 12861.35Skamil break; 12871.35Skamil default: 12881.35Skamil validate_status_signaled(status, sigsent, expect_core); 12891.35Skamil break; 12901.35Skamil } 12911.1Skamil 12921.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12931.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12941.1Skamil} 12951.1Skamil 12961.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12971.61SkreATF_TC(test); \ 12981.61SkreATF_TC_HEAD(test, tc) \ 12991.61Skre{ \ 13001.61Skre atf_tc_set_md_var(tc, "descr", \ 13011.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13021.61Skre "handled correctly in a child without a signal handler"); \ 13031.61Skre} \ 13041.61Skre \ 13051.61SkreATF_TC_BODY(test, tc) \ 13061.61Skre{ \ 13071.61Skre \ 13081.61Skre traceme_sendsignal_simple(sig); \ 13091.35Skamil} 13101.35Skamil 13111.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13121.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13131.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13141.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13151.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13161.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13171.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13181.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13191.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13201.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13211.35Skamil 13221.35Skamil/// ---------------------------------------------------------------------------- 13231.35Skamil 13241.37SkamilATF_TC(traceme_pid1_parent); 13251.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13261.37Skamil{ 13271.37Skamil atf_tc_set_md_var(tc, "descr", 13281.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13291.37Skamil} 13301.37Skamil 13311.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13321.37Skamil{ 13331.37Skamil struct msg_fds parent_child; 13341.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13351.37Skamil pid_t child1, child2, wpid; 13361.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13371.37Skamil#if defined(TWAIT_HAVE_STATUS) 13381.37Skamil int status; 13391.37Skamil#endif 13401.37Skamil 13411.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13421.37Skamil 13431.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13441.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13451.37Skamil if (child1 == 0) { 13461.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13471.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13481.37Skamil if (child2 != 0) { 13491.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13501.61Skre getpid(), child2); 13511.37Skamil _exit(exitval_child1); 13521.37Skamil } 13531.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13541.37Skamil 13551.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13561.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13571.37Skamil 13581.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13591.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13601.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13611.37Skamil 13621.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13631.37Skamil 13641.37Skamil _exit(exitval_child2); 13651.37Skamil } 13661.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13671.37Skamil 13681.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13691.61Skre TWAIT_REQUIRE_SUCCESS( 13701.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13711.37Skamil 13721.37Skamil validate_status_exited(status, exitval_child1); 13731.37Skamil 13741.37Skamil DPRINTF("Notify that child1 is dead\n"); 13751.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13761.37Skamil 13771.37Skamil DPRINTF("Wait for exiting of child2\n"); 13781.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13791.37Skamil} 13801.37Skamil 13811.37Skamil/// ---------------------------------------------------------------------------- 13821.37Skamil 13831.40Skamilstatic void 13841.40Skamiltraceme_vfork_raise(int sigval) 13851.40Skamil{ 13861.46Skamil const int exitval = 5, exitval_watcher = 10; 13871.46Skamil pid_t child, parent, watcher, wpid; 13881.46Skamil int rv; 13891.40Skamil#if defined(TWAIT_HAVE_STATUS) 13901.40Skamil int status; 13911.85Skamil 13921.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13931.85Skamil volatile int expect_core; 13941.85Skamil 13951.85Skamil switch (sigval) { 13961.85Skamil case SIGABRT: 13971.85Skamil case SIGTRAP: 13981.85Skamil case SIGBUS: 13991.85Skamil case SIGILL: 14001.85Skamil case SIGFPE: 14011.85Skamil case SIGSEGV: 14021.85Skamil expect_core = 1; 14031.85Skamil break; 14041.85Skamil default: 14051.85Skamil expect_core = 0; 14061.85Skamil break; 14071.85Skamil } 14081.40Skamil#endif 14091.40Skamil 14101.46Skamil /* 14111.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14121.46Skamil * the SIGKILL signal to it. 14131.46Skamil * 14141.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14151.46Skamil * simpler to reparent this process to initproc and forget about it. 14161.46Skamil */ 14171.46Skamil if (sigval == SIGSTOP) { 14181.46Skamil parent = getpid(); 14191.46Skamil 14201.46Skamil watcher = fork(); 14211.46Skamil ATF_REQUIRE(watcher != 1); 14221.46Skamil if (watcher == 0) { 14231.46Skamil /* Double fork(2) trick to reparent to initproc */ 14241.46Skamil watcher = fork(); 14251.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14261.46Skamil if (watcher != 0) 14271.46Skamil _exit(exitval_watcher); 14281.46Skamil 14291.46Skamil child = await_stopped_child(parent); 14301.46Skamil 14311.46Skamil errno = 0; 14321.46Skamil rv = kill(child, SIGKILL); 14331.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14341.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14351.46Skamil 14361.46Skamil /* This exit value will be collected by initproc */ 14371.46Skamil _exit(0); 14381.46Skamil } 14391.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14401.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14411.61Skre watcher); 14421.46Skamil 14431.46Skamil validate_status_exited(status, exitval_watcher); 14441.46Skamil 14451.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14461.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14471.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14481.46Skamil } 14491.46Skamil 14501.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14511.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14521.40Skamil if (child == 0) { 14531.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14541.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14551.40Skamil 14561.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14571.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14581.40Skamil 14591.40Skamil switch (sigval) { 14601.46Skamil case SIGSTOP: 14611.40Skamil case SIGKILL: 14621.40Skamil case SIGABRT: 14631.40Skamil case SIGHUP: 14641.85Skamil case SIGTRAP: 14651.85Skamil case SIGBUS: 14661.85Skamil case SIGILL: 14671.85Skamil case SIGFPE: 14681.85Skamil case SIGSEGV: 14691.40Skamil /* NOTREACHED */ 14701.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14711.70Smrg __unreachable(); 14721.40Skamil default: 14731.40Skamil DPRINTF("Before exiting of the child process\n"); 14741.40Skamil _exit(exitval); 14751.40Skamil } 14761.40Skamil } 14771.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14781.40Skamil 14791.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14801.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14811.40Skamil 14821.40Skamil switch (sigval) { 14831.40Skamil case SIGKILL: 14841.40Skamil case SIGABRT: 14851.40Skamil case SIGHUP: 14861.85Skamil case SIGTRAP: 14871.85Skamil case SIGBUS: 14881.85Skamil case SIGILL: 14891.85Skamil case SIGFPE: 14901.85Skamil case SIGSEGV: 14911.40Skamil validate_status_signaled(status, sigval, expect_core); 14921.40Skamil break; 14931.40Skamil case SIGSTOP: 14941.46Skamil validate_status_signaled(status, SIGKILL, 0); 14951.46Skamil break; 14961.40Skamil case SIGCONT: 14971.47Skamil case SIGTSTP: 14981.47Skamil case SIGTTIN: 14991.47Skamil case SIGTTOU: 15001.40Skamil validate_status_exited(status, exitval); 15011.40Skamil break; 15021.40Skamil default: 15031.40Skamil /* NOTREACHED */ 15041.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15051.40Skamil break; 15061.40Skamil } 15071.40Skamil 15081.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15091.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15101.40Skamil} 15111.40Skamil 15121.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15131.61SkreATF_TC(test); \ 15141.61SkreATF_TC_HEAD(test, tc) \ 15151.61Skre{ \ 15161.61Skre atf_tc_set_md_var(tc, "descr", \ 15171.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15181.61Skre "vfork(2)ed child"); \ 15191.61Skre} \ 15201.61Skre \ 15211.61SkreATF_TC_BODY(test, tc) \ 15221.61Skre{ \ 15231.61Skre \ 15241.61Skre traceme_vfork_raise(sig); \ 15251.40Skamil} 15261.40Skamil 15271.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15281.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15291.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15301.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15311.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15321.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15331.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15341.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15351.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15361.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15371.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15381.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15391.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15401.40Skamil 15411.40Skamil/// ---------------------------------------------------------------------------- 15421.40Skamil 15431.52Skamilstatic void 15441.52Skamiltraceme_vfork_crash(int sig) 15451.41Skamil{ 15461.41Skamil pid_t child, wpid; 15471.41Skamil#if defined(TWAIT_HAVE_STATUS) 15481.41Skamil int status; 15491.41Skamil#endif 15501.41Skamil 15511.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15521.71Skamil if (sig == SIGILL) 15531.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15541.71Skamil#endif 15551.71Skamil 15561.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15571.114Skamil atf_tc_skip("FP exceptions are not supported"); 15581.114Skamil 15591.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15601.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15611.41Skamil if (child == 0) { 15621.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15631.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15641.41Skamil 15651.52Skamil DPRINTF("Before executing a trap\n"); 15661.52Skamil switch (sig) { 15671.52Skamil case SIGTRAP: 15681.52Skamil trigger_trap(); 15691.52Skamil break; 15701.52Skamil case SIGSEGV: 15711.52Skamil trigger_segv(); 15721.52Skamil break; 15731.52Skamil case SIGILL: 15741.52Skamil trigger_ill(); 15751.52Skamil break; 15761.52Skamil case SIGFPE: 15771.52Skamil trigger_fpe(); 15781.52Skamil break; 15791.52Skamil case SIGBUS: 15801.52Skamil trigger_bus(); 15811.52Skamil break; 15821.52Skamil default: 15831.52Skamil /* NOTREACHED */ 15841.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15851.52Skamil } 15861.41Skamil 15871.41Skamil /* NOTREACHED */ 15881.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15891.41Skamil } 15901.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15911.41Skamil 15921.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15931.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15941.41Skamil 15951.52Skamil validate_status_signaled(status, sig, 1); 15961.41Skamil 15971.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15981.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15991.41Skamil} 16001.41Skamil 16011.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16021.61SkreATF_TC(test); \ 16031.61SkreATF_TC_HEAD(test, tc) \ 16041.61Skre{ \ 16051.61Skre atf_tc_set_md_var(tc, "descr", \ 16061.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16071.61Skre "vfork(2)ed child"); \ 16081.61Skre} \ 16091.61Skre \ 16101.61SkreATF_TC_BODY(test, tc) \ 16111.61Skre{ \ 16121.61Skre \ 16131.61Skre traceme_vfork_crash(sig); \ 16141.52Skamil} 16151.52Skamil 16161.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16171.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16181.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16191.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16201.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16211.52Skamil 16221.41Skamil/// ---------------------------------------------------------------------------- 16231.41Skamil 16241.92Skamilstatic void 16251.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16261.92Skamil{ 16271.92Skamil pid_t child, wpid; 16281.92Skamil#if defined(TWAIT_HAVE_STATUS) 16291.92Skamil int status; 16301.92Skamil#endif 16311.92Skamil sigset_t intmask; 16321.92Skamil 16331.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16341.92Skamil if (sig == SIGILL) 16351.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16361.92Skamil#endif 16371.92Skamil 16381.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16391.114Skamil atf_tc_skip("FP exceptions are not supported"); 16401.114Skamil 16411.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16421.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16431.92Skamil if (child == 0) { 16441.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16451.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16461.92Skamil 16471.92Skamil sigemptyset(&intmask); 16481.92Skamil sigaddset(&intmask, sig); 16491.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16501.92Skamil 16511.92Skamil DPRINTF("Before executing a trap\n"); 16521.92Skamil switch (sig) { 16531.92Skamil case SIGTRAP: 16541.92Skamil trigger_trap(); 16551.92Skamil break; 16561.92Skamil case SIGSEGV: 16571.92Skamil trigger_segv(); 16581.92Skamil break; 16591.92Skamil case SIGILL: 16601.92Skamil trigger_ill(); 16611.92Skamil break; 16621.92Skamil case SIGFPE: 16631.92Skamil trigger_fpe(); 16641.92Skamil break; 16651.92Skamil case SIGBUS: 16661.92Skamil trigger_bus(); 16671.92Skamil break; 16681.92Skamil default: 16691.92Skamil /* NOTREACHED */ 16701.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16711.92Skamil } 16721.92Skamil 16731.92Skamil /* NOTREACHED */ 16741.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16751.92Skamil } 16761.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16771.92Skamil 16781.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16791.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16801.92Skamil 16811.92Skamil validate_status_signaled(status, sig, 1); 16821.92Skamil 16831.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16841.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16851.92Skamil} 16861.92Skamil 16871.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16881.92SkamilATF_TC(test); \ 16891.92SkamilATF_TC_HEAD(test, tc) \ 16901.92Skamil{ \ 16911.92Skamil atf_tc_set_md_var(tc, "descr", \ 16921.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16931.92Skamil "vfork(2)ed child with a masked signal"); \ 16941.92Skamil} \ 16951.92Skamil \ 16961.92SkamilATF_TC_BODY(test, tc) \ 16971.92Skamil{ \ 16981.92Skamil \ 16991.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17001.92Skamil} 17011.92Skamil 17021.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17031.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17041.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17051.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17061.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17071.92Skamil 17081.92Skamil/// ---------------------------------------------------------------------------- 17091.92Skamil 17101.92Skamilstatic void 17111.92Skamiltraceme_vfork_signalignored_crash(int sig) 17121.92Skamil{ 17131.92Skamil pid_t child, wpid; 17141.92Skamil#if defined(TWAIT_HAVE_STATUS) 17151.92Skamil int status; 17161.92Skamil#endif 17171.92Skamil struct sigaction sa; 17181.92Skamil 17191.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17201.92Skamil if (sig == SIGILL) 17211.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17221.92Skamil#endif 17231.92Skamil 17241.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17251.114Skamil atf_tc_skip("FP exceptions are not supported"); 17261.114Skamil 17271.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17281.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17291.92Skamil if (child == 0) { 17301.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17311.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17321.92Skamil 17331.92Skamil memset(&sa, 0, sizeof(sa)); 17341.92Skamil sa.sa_handler = SIG_IGN; 17351.92Skamil sigemptyset(&sa.sa_mask); 17361.92Skamil 17371.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17381.92Skamil 17391.92Skamil DPRINTF("Before executing a trap\n"); 17401.92Skamil switch (sig) { 17411.92Skamil case SIGTRAP: 17421.92Skamil trigger_trap(); 17431.92Skamil break; 17441.92Skamil case SIGSEGV: 17451.92Skamil trigger_segv(); 17461.92Skamil break; 17471.92Skamil case SIGILL: 17481.92Skamil trigger_ill(); 17491.92Skamil break; 17501.92Skamil case SIGFPE: 17511.92Skamil trigger_fpe(); 17521.92Skamil break; 17531.92Skamil case SIGBUS: 17541.92Skamil trigger_bus(); 17551.92Skamil break; 17561.92Skamil default: 17571.92Skamil /* NOTREACHED */ 17581.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17591.92Skamil } 17601.92Skamil 17611.92Skamil /* NOTREACHED */ 17621.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17631.92Skamil } 17641.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17651.92Skamil 17661.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17671.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17681.92Skamil 17691.92Skamil validate_status_signaled(status, sig, 1); 17701.92Skamil 17711.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17721.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17731.92Skamil} 17741.92Skamil 17751.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17761.92SkamilATF_TC(test); \ 17771.92SkamilATF_TC_HEAD(test, tc) \ 17781.92Skamil{ \ 17791.92Skamil atf_tc_set_md_var(tc, "descr", \ 17801.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17811.92Skamil "vfork(2)ed child with ignored signal"); \ 17821.92Skamil} \ 17831.92Skamil \ 17841.92SkamilATF_TC_BODY(test, tc) \ 17851.92Skamil{ \ 17861.92Skamil \ 17871.92Skamil traceme_vfork_signalignored_crash(sig); \ 17881.92Skamil} 17891.92Skamil 17901.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17911.92Skamil SIGTRAP) 17921.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17931.92Skamil SIGSEGV) 17941.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17951.92Skamil SIGILL) 17961.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17971.92Skamil SIGFPE) 17981.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17991.92Skamil SIGBUS) 18001.92Skamil 18011.92Skamil/// ---------------------------------------------------------------------------- 18021.92Skamil 18031.96Skamilstatic void 18041.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18051.43Skamil{ 18061.43Skamil const int sigval = SIGTRAP; 18071.43Skamil pid_t child, wpid; 18081.43Skamil#if defined(TWAIT_HAVE_STATUS) 18091.43Skamil int status; 18101.43Skamil#endif 18111.96Skamil struct sigaction sa; 18121.61Skre struct ptrace_siginfo info; 18131.96Skamil sigset_t intmask; 18141.96Skamil struct kinfo_proc2 kp; 18151.96Skamil size_t len = sizeof(kp); 18161.96Skamil 18171.96Skamil int name[6]; 18181.96Skamil const size_t namelen = __arraycount(name); 18191.96Skamil ki_sigset_t kp_sigmask; 18201.96Skamil ki_sigset_t kp_sigignore; 18211.43Skamil 18221.43Skamil memset(&info, 0, sizeof(info)); 18231.43Skamil 18241.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18251.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18261.43Skamil if (child == 0) { 18271.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18281.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18291.43Skamil 18301.96Skamil if (masked) { 18311.96Skamil sigemptyset(&intmask); 18321.96Skamil sigaddset(&intmask, sigval); 18331.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18341.96Skamil } 18351.96Skamil 18361.96Skamil if (ignored) { 18371.96Skamil memset(&sa, 0, sizeof(sa)); 18381.96Skamil sa.sa_handler = SIG_IGN; 18391.96Skamil sigemptyset(&sa.sa_mask); 18401.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18411.96Skamil } 18421.96Skamil 18431.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18441.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18451.43Skamil 18461.43Skamil /* NOTREACHED */ 18471.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18481.43Skamil } 18491.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18501.43Skamil 18511.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18521.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18531.43Skamil 18541.43Skamil validate_status_stopped(status, sigval); 18551.43Skamil 18561.96Skamil name[0] = CTL_KERN, 18571.96Skamil name[1] = KERN_PROC2, 18581.96Skamil name[2] = KERN_PROC_PID; 18591.96Skamil name[3] = getpid(); 18601.96Skamil name[4] = sizeof(kp); 18611.96Skamil name[5] = 1; 18621.96Skamil 18631.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18641.96Skamil 18651.96Skamil if (masked) 18661.96Skamil kp_sigmask = kp.p_sigmask; 18671.96Skamil 18681.96Skamil if (ignored) 18691.96Skamil kp_sigignore = kp.p_sigignore; 18701.96Skamil 18711.96Skamil name[3] = getpid(); 18721.96Skamil 18731.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18741.96Skamil 18751.96Skamil if (masked) { 18761.96Skamil DPRINTF("kp_sigmask=" 18771.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18781.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18791.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18801.96Skamil 18811.96Skamil DPRINTF("kp.p_sigmask=" 18821.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18831.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18841.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18851.96Skamil 18861.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18871.96Skamil sizeof(kp_sigmask))); 18881.96Skamil } 18891.96Skamil 18901.96Skamil if (ignored) { 18911.96Skamil DPRINTF("kp_sigignore=" 18921.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18931.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18941.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18951.96Skamil 18961.96Skamil DPRINTF("kp.p_sigignore=" 18971.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18981.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 18991.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19001.96Skamil 19011.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19021.96Skamil sizeof(kp_sigignore))); 19031.96Skamil } 19041.96Skamil 19051.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19061.61Skre SYSCALL_REQUIRE( 19071.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19081.43Skamil 19091.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19101.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19111.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19121.43Skamil info.psi_siginfo.si_errno); 19131.43Skamil 19141.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19151.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19161.43Skamil 19171.43Skamil DPRINTF("Before resuming the child process where it left off and " 19181.43Skamil "without signal to be sent\n"); 19191.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19201.43Skamil 19211.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19221.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19231.43Skamil 19241.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19251.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19261.43Skamil} 19271.43Skamil 19281.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19291.96SkamilATF_TC(test); \ 19301.96SkamilATF_TC_HEAD(test, tc) \ 19311.96Skamil{ \ 19321.96Skamil atf_tc_set_md_var(tc, "descr", \ 19331.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19341.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19351.96Skamil masked ? " with ignored signal" : ""); \ 19361.96Skamil} \ 19371.96Skamil \ 19381.96SkamilATF_TC_BODY(test, tc) \ 19391.96Skamil{ \ 19401.96Skamil \ 19411.96Skamil traceme_vfork_exec(masked, ignored); \ 19421.96Skamil} 19431.96Skamil 19441.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19451.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19461.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19471.96Skamil 19481.43Skamil/// ---------------------------------------------------------------------------- 19491.43Skamil 19501.1Skamil#if defined(TWAIT_HAVE_PID) 19511.51Skamilstatic void 19521.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19531.59Skamil{ 19541.94Skamil const int sigval = SIGSTOP; 19551.59Skamil struct msg_fds parent_tracee, parent_tracer; 19561.59Skamil const int exitval = 10; 19571.59Skamil pid_t tracee, tracer, wpid; 19581.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19591.59Skamil#if defined(TWAIT_HAVE_STATUS) 19601.59Skamil int status; 19611.59Skamil#endif 19621.94Skamil struct sigaction sa; 19631.59Skamil struct ptrace_siginfo info; 19641.94Skamil sigset_t intmask; 19651.94Skamil struct kinfo_proc2 kp; 19661.94Skamil size_t len = sizeof(kp); 19671.94Skamil 19681.94Skamil int name[6]; 19691.94Skamil const size_t namelen = __arraycount(name); 19701.94Skamil ki_sigset_t kp_sigmask; 19711.94Skamil ki_sigset_t kp_sigignore; 19721.61Skre 19731.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19741.71Skamil if (sig == SIGILL) 19751.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19761.71Skamil#endif 19771.71Skamil 19781.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19791.114Skamil atf_tc_skip("FP exceptions are not supported"); 19801.114Skamil 19811.59Skamil memset(&info, 0, sizeof(info)); 19821.59Skamil 19831.59Skamil DPRINTF("Spawn tracee\n"); 19841.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19851.59Skamil tracee = atf_utils_fork(); 19861.59Skamil if (tracee == 0) { 19871.59Skamil // Wait for parent to let us crash 19881.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19891.61Skre 19901.94Skamil if (masked) { 19911.94Skamil sigemptyset(&intmask); 19921.94Skamil sigaddset(&intmask, sig); 19931.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19941.94Skamil } 19951.94Skamil 19961.94Skamil if (ignored) { 19971.94Skamil memset(&sa, 0, sizeof(sa)); 19981.94Skamil sa.sa_handler = SIG_IGN; 19991.94Skamil sigemptyset(&sa.sa_mask); 20001.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20011.94Skamil } 20021.94Skamil 20031.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20041.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20051.94Skamil 20061.59Skamil DPRINTF("Before executing a trap\n"); 20071.59Skamil switch (sig) { 20081.59Skamil case SIGTRAP: 20091.59Skamil trigger_trap(); 20101.59Skamil break; 20111.59Skamil case SIGSEGV: 20121.59Skamil trigger_segv(); 20131.59Skamil break; 20141.59Skamil case SIGILL: 20151.59Skamil trigger_ill(); 20161.59Skamil break; 20171.59Skamil case SIGFPE: 20181.59Skamil trigger_fpe(); 20191.59Skamil break; 20201.59Skamil case SIGBUS: 20211.59Skamil trigger_bus(); 20221.59Skamil break; 20231.59Skamil default: 20241.59Skamil /* NOTREACHED */ 20251.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20261.59Skamil } 20271.59Skamil 20281.59Skamil /* NOTREACHED */ 20291.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20301.59Skamil } 20311.59Skamil 20321.59Skamil DPRINTF("Spawn debugger\n"); 20331.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20341.59Skamil tracer = atf_utils_fork(); 20351.59Skamil if (tracer == 0) { 20361.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20371.59Skamil tracer = atf_utils_fork(); 20381.59Skamil if (tracer != 0) 20391.61Skre _exit(exitval); 20401.59Skamil 20411.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20421.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20431.59Skamil 20441.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20451.59Skamil FORKEE_REQUIRE_SUCCESS( 20461.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20471.59Skamil 20481.59Skamil forkee_status_stopped(status, SIGSTOP); 20491.59Skamil 20501.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20511.94Skamil "traced process\n"); 20521.94Skamil SYSCALL_REQUIRE( 20531.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20541.94Skamil 20551.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20561.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20571.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20581.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20591.94Skamil 20601.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20611.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20621.94Skamil 20631.59Skamil /* Resume tracee with PT_CONTINUE */ 20641.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20651.59Skamil 20661.59Skamil /* Inform parent that tracer has attached to tracee */ 20671.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20681.59Skamil 20691.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20701.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20711.59Skamil 20721.59Skamil /* Wait for tracee and assert that it exited */ 20731.59Skamil FORKEE_REQUIRE_SUCCESS( 20741.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20751.59Skamil 20761.94Skamil forkee_status_stopped(status, sigval); 20771.94Skamil 20781.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20791.94Skamil "traced process\n"); 20801.94Skamil SYSCALL_REQUIRE( 20811.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20821.94Skamil 20831.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20841.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20851.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20861.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20871.94Skamil 20881.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20891.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20901.94Skamil 20911.94Skamil name[0] = CTL_KERN, 20921.94Skamil name[1] = KERN_PROC2, 20931.94Skamil name[2] = KERN_PROC_PID; 20941.94Skamil name[3] = tracee; 20951.94Skamil name[4] = sizeof(kp); 20961.94Skamil name[5] = 1; 20971.94Skamil 20981.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20991.94Skamil 21001.94Skamil if (masked) 21011.94Skamil kp_sigmask = kp.p_sigmask; 21021.94Skamil 21031.94Skamil if (ignored) 21041.94Skamil kp_sigignore = kp.p_sigignore; 21051.94Skamil 21061.94Skamil /* Resume tracee with PT_CONTINUE */ 21071.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21081.94Skamil 21091.94Skamil /* Wait for tracee and assert that it exited */ 21101.94Skamil FORKEE_REQUIRE_SUCCESS( 21111.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21121.94Skamil 21131.93Skamil forkee_status_stopped(status, sig); 21141.59Skamil 21151.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21161.61Skre "traced process\n"); 21171.61Skre SYSCALL_REQUIRE( 21181.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21191.59Skamil 21201.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21211.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21221.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21231.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21241.59Skamil 21251.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21261.94Skamil 21271.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21281.94Skamil 21291.94Skamil if (masked) { 21301.94Skamil DPRINTF("kp_sigmask=" 21311.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21321.94Skamil PRIx32 "\n", 21331.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21341.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21351.94Skamil 21361.94Skamil DPRINTF("kp.p_sigmask=" 21371.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21381.94Skamil PRIx32 "\n", 21391.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21401.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21411.94Skamil 21421.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21431.94Skamil sizeof(kp_sigmask))); 21441.94Skamil } 21451.94Skamil 21461.94Skamil if (ignored) { 21471.94Skamil DPRINTF("kp_sigignore=" 21481.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21491.94Skamil PRIx32 "\n", 21501.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21511.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21521.94Skamil 21531.94Skamil DPRINTF("kp.p_sigignore=" 21541.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21551.94Skamil PRIx32 "\n", 21561.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21571.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21581.94Skamil 21591.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21601.94Skamil sizeof(kp_sigignore))); 21611.94Skamil } 21621.94Skamil 21631.59Skamil switch (sig) { 21641.59Skamil case SIGTRAP: 21651.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21661.59Skamil break; 21671.59Skamil case SIGSEGV: 21681.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21691.59Skamil break; 21701.71Skamil case SIGILL: 21711.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21721.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21731.71Skamil break; 21741.59Skamil case SIGFPE: 21751.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21761.59Skamil break; 21771.59Skamil case SIGBUS: 21781.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21791.59Skamil break; 21801.59Skamil } 21811.59Skamil 21821.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21831.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21841.93Skamil FORKEE_REQUIRE_SUCCESS( 21851.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21861.59Skamil 21871.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21881.59Skamil 21891.71Skamil /* Inform parent that tracer is exiting normally */ 21901.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21911.71Skamil 21921.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21931.59Skamil _exit(0 /* collect by initproc */); 21941.59Skamil } 21951.59Skamil 21961.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21971.59Skamil "calling %s()\n", TWAIT_FNAME); 21981.59Skamil TWAIT_REQUIRE_SUCCESS( 21991.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22001.59Skamil 22011.59Skamil validate_status_exited(status, exitval); 22021.59Skamil 22031.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22041.59Skamil TWAIT_FNAME); 22051.59Skamil TWAIT_REQUIRE_SUCCESS( 22061.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22071.59Skamil 22081.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22091.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22101.59Skamil 22111.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22121.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22131.59Skamil 22141.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22151.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22161.59Skamil 22171.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22181.59Skamil TWAIT_FNAME); 22191.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22201.59Skamil 22211.59Skamil validate_status_signaled(status, SIGKILL, 0); 22221.59Skamil 22231.71Skamil DPRINTF("Await normal exit of tracer\n"); 22241.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22251.71Skamil 22261.59Skamil msg_close(&parent_tracer); 22271.59Skamil msg_close(&parent_tracee); 22281.59Skamil} 22291.59Skamil 22301.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22311.61SkreATF_TC(test); \ 22321.61SkreATF_TC_HEAD(test, tc) \ 22331.61Skre{ \ 22341.61Skre atf_tc_set_md_var(tc, "descr", \ 22351.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22361.94Skamil "the debuggee"); \ 22371.61Skre} \ 22381.61Skre \ 22391.61SkreATF_TC_BODY(test, tc) \ 22401.61Skre{ \ 22411.61Skre \ 22421.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22431.59Skamil} 22441.59Skamil 22451.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22461.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22471.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22481.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22491.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22501.94Skamil 22511.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22521.94SkamilATF_TC(test); \ 22531.94SkamilATF_TC_HEAD(test, tc) \ 22541.94Skamil{ \ 22551.94Skamil atf_tc_set_md_var(tc, "descr", \ 22561.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22571.94Skamil "the debuggee with masked signal"); \ 22581.94Skamil} \ 22591.94Skamil \ 22601.94SkamilATF_TC_BODY(test, tc) \ 22611.94Skamil{ \ 22621.94Skamil \ 22631.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22641.94Skamil} 22651.94Skamil 22661.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22671.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22681.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22691.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22701.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22711.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22721.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22731.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22741.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22751.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22761.94Skamil 22771.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22781.94SkamilATF_TC(test); \ 22791.94SkamilATF_TC_HEAD(test, tc) \ 22801.94Skamil{ \ 22811.94Skamil atf_tc_set_md_var(tc, "descr", \ 22821.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22831.94Skamil "the debuggee with signal ignored"); \ 22841.94Skamil} \ 22851.94Skamil \ 22861.94SkamilATF_TC_BODY(test, tc) \ 22871.94Skamil{ \ 22881.94Skamil \ 22891.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22901.94Skamil} 22911.94Skamil 22921.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22931.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22941.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22951.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22961.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22971.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 22981.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22991.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23001.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23011.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23021.59Skamil#endif 23031.59Skamil 23041.59Skamil/// ---------------------------------------------------------------------------- 23051.59Skamil 23061.59Skamil#if defined(TWAIT_HAVE_PID) 23071.59Skamilstatic void 23081.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23091.67Skamil bool stopped) 23101.1Skamil{ 23111.51Skamil /* 23121.51Skamil * notimeout - disable timeout in await zombie function 23131.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23141.67Skamil * stopped - attach to a stopped process 23151.51Skamil */ 23161.1Skamil 23171.1Skamil struct msg_fds parent_tracee, parent_tracer; 23181.1Skamil const int exitval_tracee = 5; 23191.1Skamil const int exitval_tracer = 10; 23201.1Skamil pid_t tracee, tracer, wpid; 23211.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23221.1Skamil#if defined(TWAIT_HAVE_STATUS) 23231.1Skamil int status; 23241.1Skamil#endif 23251.1Skamil 23261.67Skamil /* 23271.67Skamil * Only a subset of options are supported. 23281.67Skamil */ 23291.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23301.67Skamil (!notimeout && unrelated && !stopped) || 23311.67Skamil (notimeout && !unrelated && !stopped) || 23321.67Skamil (!notimeout && unrelated && stopped)); 23331.67Skamil 23341.13Schristos DPRINTF("Spawn tracee\n"); 23351.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23361.1Skamil tracee = atf_utils_fork(); 23371.1Skamil if (tracee == 0) { 23381.67Skamil if (stopped) { 23391.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23401.67Skamil raise(SIGSTOP); 23411.67Skamil } 23421.67Skamil 23431.1Skamil // Wait for parent to let us exit 23441.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23451.1Skamil _exit(exitval_tracee); 23461.1Skamil } 23471.1Skamil 23481.13Schristos DPRINTF("Spawn debugger\n"); 23491.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23501.1Skamil tracer = atf_utils_fork(); 23511.1Skamil if (tracer == 0) { 23521.51Skamil if(unrelated) { 23531.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23541.51Skamil tracer = atf_utils_fork(); 23551.51Skamil if (tracer != 0) 23561.51Skamil _exit(exitval_tracer); 23571.51Skamil } 23581.51Skamil 23591.67Skamil if (stopped) { 23601.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23611.67Skamil await_stopped(tracee); 23621.67Skamil } 23631.67Skamil 23641.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23651.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23661.1Skamil 23671.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23681.1Skamil FORKEE_REQUIRE_SUCCESS( 23691.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23701.1Skamil 23711.1Skamil forkee_status_stopped(status, SIGSTOP); 23721.1Skamil 23731.1Skamil /* Resume tracee with PT_CONTINUE */ 23741.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23751.1Skamil 23761.1Skamil /* Inform parent that tracer has attached to tracee */ 23771.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23781.1Skamil 23791.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23801.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23811.1Skamil 23821.1Skamil /* Wait for tracee and assert that it exited */ 23831.1Skamil FORKEE_REQUIRE_SUCCESS( 23841.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23851.1Skamil 23861.1Skamil forkee_status_exited(status, exitval_tracee); 23871.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23881.1Skamil 23891.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23901.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23911.51Skamil } 23921.51Skamil 23931.51Skamil if (unrelated) { 23941.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23951.51Skamil "calling %s()\n", TWAIT_FNAME); 23961.51Skamil TWAIT_REQUIRE_SUCCESS( 23971.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 23981.51Skamil 23991.51Skamil validate_status_exited(status, exitval_tracer); 24001.51Skamil 24011.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24021.51Skamil TWAIT_FNAME); 24031.51Skamil TWAIT_REQUIRE_SUCCESS( 24041.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24051.1Skamil } 24061.1Skamil 24071.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24081.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24091.1Skamil 24101.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24111.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24121.1Skamil 24131.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24141.51Skamil if (notimeout) 24151.26Skamil await_zombie_raw(tracee, 0); 24161.26Skamil else 24171.26Skamil await_zombie(tracee); 24181.1Skamil 24191.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24201.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24211.1Skamil TWAIT_FNAME); 24221.1Skamil TWAIT_REQUIRE_SUCCESS( 24231.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24241.1Skamil 24251.51Skamil if (unrelated) { 24261.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24271.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24281.51Skamil } else { 24291.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24301.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24311.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24321.59Skamil "%s()\n", TWAIT_FNAME); 24331.51Skamil 24341.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24351.59Skamil "tracee\n"); 24361.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24371.51Skamil tracer); 24381.1Skamil 24391.51Skamil validate_status_exited(status, exitval_tracer); 24401.51Skamil } 24411.1Skamil 24421.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24431.1Skamil TWAIT_FNAME); 24441.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24451.1Skamil 24461.1Skamil validate_status_exited(status, exitval_tracee); 24471.1Skamil 24481.1Skamil msg_close(&parent_tracer); 24491.1Skamil msg_close(&parent_tracee); 24501.1Skamil} 24511.26Skamil 24521.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24531.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24541.51Skamil{ 24551.51Skamil atf_tc_set_md_var(tc, "descr", 24561.51Skamil "Assert that tracer sees process termination before the parent"); 24571.51Skamil} 24581.51Skamil 24591.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24601.26Skamil{ 24611.26Skamil 24621.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24631.26Skamil} 24641.26Skamil 24651.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24661.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24671.1Skamil{ 24681.164Skamil atf_tc_set_md_var(tc, "timeout", "15"); 24691.1Skamil atf_tc_set_md_var(tc, "descr", 24701.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24711.51Skamil "process and no other error is reported"); 24721.1Skamil} 24731.1Skamil 24741.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24751.1Skamil{ 24761.51Skamil time_t start, end; 24771.51Skamil double diff; 24781.51Skamil unsigned long N = 0; 24791.1Skamil 24801.51Skamil /* 24811.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24821.51Skamil * This test body isn't specific to this race, however it's just good 24831.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24841.51Skamil */ 24851.1Skamil 24861.51Skamil start = time(NULL); 24871.51Skamil while (true) { 24881.51Skamil DPRINTF("Step: %lu\n", N); 24891.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24901.67Skamil false); 24911.51Skamil end = time(NULL); 24921.51Skamil diff = difftime(end, start); 24931.51Skamil if (diff >= 5.0) 24941.51Skamil break; 24951.51Skamil ++N; 24961.1Skamil } 24971.51Skamil DPRINTF("Iterations: %lu\n", N); 24981.51Skamil} 24991.1Skamil 25001.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25011.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25021.51Skamil{ 25031.51Skamil atf_tc_set_md_var(tc, "descr", 25041.51Skamil "Assert that tracer sees process termination before the parent"); 25051.51Skamil} 25061.1Skamil 25071.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25081.51Skamil{ 25091.1Skamil 25101.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25111.67Skamil} 25121.67Skamil 25131.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25141.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25151.67Skamil{ 25161.67Skamil atf_tc_set_md_var(tc, "descr", 25171.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25181.67Skamil} 25191.67Skamil 25201.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25211.67Skamil{ 25221.67Skamil 25231.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25241.1Skamil} 25251.1Skamil#endif 25261.1Skamil 25271.51Skamil/// ---------------------------------------------------------------------------- 25281.51Skamil 25291.66Skamilstatic void 25301.66Skamilparent_attach_to_its_child(bool stopped) 25311.1Skamil{ 25321.1Skamil struct msg_fds parent_tracee; 25331.1Skamil const int exitval_tracee = 5; 25341.1Skamil pid_t tracee, wpid; 25351.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25361.1Skamil#if defined(TWAIT_HAVE_STATUS) 25371.1Skamil int status; 25381.1Skamil#endif 25391.1Skamil 25401.13Schristos DPRINTF("Spawn tracee\n"); 25411.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25421.1Skamil tracee = atf_utils_fork(); 25431.1Skamil if (tracee == 0) { 25441.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25451.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25461.1Skamil 25471.66Skamil if (stopped) { 25481.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25491.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25501.66Skamil } 25511.66Skamil 25521.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25531.1Skamil /* Wait for message from the parent */ 25541.1Skamil _exit(exitval_tracee); 25551.1Skamil } 25561.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25571.57Skamil 25581.66Skamil if (stopped) { 25591.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25601.66Skamil await_stopped(tracee); 25611.66Skamil } 25621.66Skamil 25631.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25641.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25651.1Skamil 25661.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25671.1Skamil TWAIT_FNAME); 25681.1Skamil TWAIT_REQUIRE_SUCCESS( 25691.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25701.1Skamil 25711.1Skamil validate_status_stopped(status, SIGSTOP); 25721.1Skamil 25731.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25741.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25751.1Skamil 25761.13Schristos DPRINTF("Let the tracee exit now\n"); 25771.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25781.1Skamil 25791.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25801.1Skamil TWAIT_REQUIRE_SUCCESS( 25811.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25821.1Skamil 25831.1Skamil validate_status_exited(status, exitval_tracee); 25841.1Skamil 25851.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25861.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25871.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25881.1Skamil 25891.1Skamil msg_close(&parent_tracee); 25901.1Skamil} 25911.1Skamil 25921.66SkamilATF_TC(parent_attach_to_its_child); 25931.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25941.66Skamil{ 25951.66Skamil atf_tc_set_md_var(tc, "descr", 25961.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25971.66Skamil} 25981.66Skamil 25991.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26001.66Skamil{ 26011.66Skamil 26021.66Skamil parent_attach_to_its_child(false); 26031.66Skamil} 26041.66Skamil 26051.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26061.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26071.66Skamil{ 26081.66Skamil atf_tc_set_md_var(tc, "descr", 26091.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26101.66Skamil} 26111.66Skamil 26121.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26131.66Skamil{ 26141.66Skamil 26151.66Skamil parent_attach_to_its_child(true); 26161.66Skamil} 26171.66Skamil 26181.51Skamil/// ---------------------------------------------------------------------------- 26191.51Skamil 26201.65Skamilstatic void 26211.65Skamilchild_attach_to_its_parent(bool stopped) 26221.1Skamil{ 26231.1Skamil struct msg_fds parent_tracee; 26241.1Skamil const int exitval_tracer = 5; 26251.1Skamil pid_t tracer, wpid; 26261.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26271.1Skamil#if defined(TWAIT_HAVE_STATUS) 26281.1Skamil int status; 26291.1Skamil#endif 26301.1Skamil 26311.13Schristos DPRINTF("Spawn tracer\n"); 26321.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26331.1Skamil tracer = atf_utils_fork(); 26341.1Skamil if (tracer == 0) { 26351.1Skamil /* Wait for message from the parent */ 26361.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26371.1Skamil 26381.65Skamil if (stopped) { 26391.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26401.65Skamil getppid()); 26411.65Skamil await_stopped(getppid()); 26421.65Skamil } 26431.65Skamil 26441.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26451.1Skamil getppid()); 26461.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26471.1Skamil 26481.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26491.1Skamil TWAIT_FNAME); 26501.1Skamil FORKEE_REQUIRE_SUCCESS( 26511.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26521.1Skamil 26531.1Skamil forkee_status_stopped(status, SIGSTOP); 26541.1Skamil 26551.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26561.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26571.1Skamil != -1); 26581.1Skamil 26591.1Skamil /* Tell parent we are ready */ 26601.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26611.1Skamil 26621.1Skamil _exit(exitval_tracer); 26631.1Skamil } 26641.1Skamil 26651.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26661.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26671.65Skamil 26681.65Skamil if (stopped) { 26691.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26701.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26711.65Skamil } 26721.65Skamil 26731.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26741.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26751.1Skamil 26761.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26771.1Skamil TWAIT_REQUIRE_SUCCESS( 26781.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26791.1Skamil 26801.1Skamil validate_status_exited(status, exitval_tracer); 26811.1Skamil 26821.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26831.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26841.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26851.1Skamil 26861.1Skamil msg_close(&parent_tracee); 26871.1Skamil} 26881.1Skamil 26891.65SkamilATF_TC(child_attach_to_its_parent); 26901.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26911.65Skamil{ 26921.65Skamil atf_tc_set_md_var(tc, "descr", 26931.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26941.65Skamil} 26951.65Skamil 26961.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26971.65Skamil{ 26981.65Skamil 26991.65Skamil child_attach_to_its_parent(false); 27001.65Skamil} 27011.65Skamil 27021.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27031.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27041.65Skamil{ 27051.65Skamil atf_tc_set_md_var(tc, "descr", 27061.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27071.65Skamil} 27081.65Skamil 27091.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27101.65Skamil{ 27111.65Skamil /* 27121.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27131.65Skamil * this causes a pipe (established from atf-run) to be broken. 27141.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27151.65Skamil * 27161.65Skamil * As a workaround spawn this test as a subprocess. 27171.65Skamil */ 27181.65Skamil 27191.65Skamil const int exitval = 15; 27201.65Skamil pid_t child, wpid; 27211.65Skamil#if defined(TWAIT_HAVE_STATUS) 27221.65Skamil int status; 27231.65Skamil#endif 27241.65Skamil 27251.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27261.65Skamil if (child == 0) { 27271.65Skamil child_attach_to_its_parent(true); 27281.65Skamil _exit(exitval); 27291.65Skamil } else { 27301.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27311.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27321.65Skamil 27331.65Skamil validate_status_exited(status, exitval); 27341.65Skamil 27351.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27361.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27371.65Skamil } 27381.65Skamil} 27391.65Skamil 27401.51Skamil/// ---------------------------------------------------------------------------- 27411.51Skamil 27421.1Skamil#if defined(TWAIT_HAVE_PID) 27431.1Skamil 27441.51Skamilenum tracee_sees_its_original_parent_type { 27451.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27461.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27471.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27481.51Skamil}; 27491.51Skamil 27501.51Skamilstatic void 27511.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27521.1Skamil{ 27531.1Skamil struct msg_fds parent_tracer, parent_tracee; 27541.1Skamil const int exitval_tracee = 5; 27551.1Skamil const int exitval_tracer = 10; 27561.1Skamil pid_t parent, tracee, tracer, wpid; 27571.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27581.1Skamil#if defined(TWAIT_HAVE_STATUS) 27591.1Skamil int status; 27601.1Skamil#endif 27611.51Skamil /* sysctl(3) - kinfo_proc2 */ 27621.51Skamil int name[CTL_MAXNAME]; 27631.51Skamil struct kinfo_proc2 kp; 27641.51Skamil size_t len = sizeof(kp); 27651.51Skamil unsigned int namelen; 27661.51Skamil 27671.51Skamil /* procfs - status */ 27681.51Skamil FILE *fp; 27691.51Skamil struct stat st; 27701.51Skamil const char *fname = "/proc/curproc/status"; 27711.51Skamil char s_executable[MAXPATHLEN]; 27721.51Skamil int s_pid, s_ppid; 27731.51Skamil int rv; 27741.51Skamil 27751.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27761.61Skre SYSCALL_REQUIRE( 27771.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27781.61Skre if (rv != 0) 27791.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27801.51Skamil } 27811.1Skamil 27821.13Schristos DPRINTF("Spawn tracee\n"); 27831.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27841.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27851.1Skamil tracee = atf_utils_fork(); 27861.1Skamil if (tracee == 0) { 27871.1Skamil parent = getppid(); 27881.1Skamil 27891.1Skamil /* Emit message to the parent */ 27901.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27911.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27921.1Skamil 27931.51Skamil switch (type) { 27941.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27951.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27961.51Skamil break; 27971.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27981.51Skamil namelen = 0; 27991.51Skamil name[namelen++] = CTL_KERN; 28001.51Skamil name[namelen++] = KERN_PROC2; 28011.51Skamil name[namelen++] = KERN_PROC_PID; 28021.51Skamil name[namelen++] = getpid(); 28031.51Skamil name[namelen++] = len; 28041.51Skamil name[namelen++] = 1; 28051.51Skamil 28061.61Skre FORKEE_ASSERT_EQ( 28071.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28081.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28091.51Skamil break; 28101.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28111.51Skamil /* 28121.51Skamil * Format: 28131.51Skamil * EXECUTABLE PID PPID ... 28141.51Skamil */ 28151.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28161.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28171.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28181.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28191.51Skamil break; 28201.51Skamil } 28211.1Skamil 28221.1Skamil _exit(exitval_tracee); 28231.1Skamil } 28241.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28251.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28261.1Skamil 28271.13Schristos DPRINTF("Spawn debugger\n"); 28281.1Skamil tracer = atf_utils_fork(); 28291.1Skamil if (tracer == 0) { 28301.1Skamil /* No IPC to communicate with the child */ 28311.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28321.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28331.1Skamil 28341.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28351.1Skamil FORKEE_REQUIRE_SUCCESS( 28361.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28371.1Skamil 28381.1Skamil forkee_status_stopped(status, SIGSTOP); 28391.1Skamil 28401.1Skamil /* Resume tracee with PT_CONTINUE */ 28411.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28421.1Skamil 28431.1Skamil /* Inform parent that tracer has attached to tracee */ 28441.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28451.1Skamil 28461.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28471.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28481.1Skamil 28491.1Skamil /* Wait for tracee and assert that it exited */ 28501.1Skamil FORKEE_REQUIRE_SUCCESS( 28511.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28521.1Skamil 28531.1Skamil forkee_status_exited(status, exitval_tracee); 28541.1Skamil 28551.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28561.1Skamil _exit(exitval_tracer); 28571.1Skamil } 28581.1Skamil 28591.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28601.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28611.1Skamil 28621.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28631.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28641.1Skamil 28651.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28661.1Skamil await_zombie(tracee); 28671.1Skamil 28681.13Schristos DPRINTF("Assert that there is no status about tracee - " 28691.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28701.1Skamil TWAIT_REQUIRE_SUCCESS( 28711.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28721.1Skamil 28731.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28741.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28751.1Skamil 28761.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28781.1Skamil tracer); 28791.1Skamil 28801.1Skamil validate_status_exited(status, exitval_tracer); 28811.1Skamil 28821.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28831.1Skamil TWAIT_FNAME); 28841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28851.1Skamil tracee); 28861.1Skamil 28871.1Skamil validate_status_exited(status, exitval_tracee); 28881.1Skamil 28891.1Skamil msg_close(&parent_tracer); 28901.1Skamil msg_close(&parent_tracee); 28911.1Skamil} 28921.1Skamil 28931.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28941.61SkreATF_TC(test); \ 28951.61SkreATF_TC_HEAD(test, tc) \ 28961.61Skre{ \ 28971.61Skre atf_tc_set_md_var(tc, "descr", \ 28981.61Skre "Assert that tracee sees its original parent when being traced " \ 28991.61Skre "(check " descr ")"); \ 29001.61Skre} \ 29011.61Skre \ 29021.61SkreATF_TC_BODY(test, tc) \ 29031.61Skre{ \ 29041.61Skre \ 29051.61Skre tracee_sees_its_original_parent(type); \ 29061.1Skamil} 29071.1Skamil 29081.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29091.51Skamil tracee_sees_its_original_parent_getppid, 29101.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29111.51Skamil "getppid(2)"); 29121.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29131.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29141.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29151.51Skamil "sysctl(3) and kinfo_proc2"); 29161.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29171.51Skamil tracee_sees_its_original_parent_procfs_status, 29181.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29191.51Skamil "the status file in procfs"); 29201.1Skamil#endif 29211.1Skamil 29221.51Skamil/// ---------------------------------------------------------------------------- 29231.1Skamil 29241.53Skamilstatic void 29251.53Skamileventmask_preserved(int event) 29261.1Skamil{ 29271.1Skamil const int exitval = 5; 29281.1Skamil const int sigval = SIGSTOP; 29291.1Skamil pid_t child, wpid; 29301.1Skamil#if defined(TWAIT_HAVE_STATUS) 29311.1Skamil int status; 29321.1Skamil#endif 29331.1Skamil ptrace_event_t set_event, get_event; 29341.1Skamil const int len = sizeof(ptrace_event_t); 29351.1Skamil 29361.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29371.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29381.1Skamil if (child == 0) { 29391.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29401.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29411.1Skamil 29421.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29431.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29441.1Skamil 29451.13Schristos DPRINTF("Before exiting of the child process\n"); 29461.1Skamil _exit(exitval); 29471.1Skamil } 29481.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29491.1Skamil 29501.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29511.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29521.1Skamil 29531.1Skamil validate_status_stopped(status, sigval); 29541.1Skamil 29551.53Skamil set_event.pe_set_event = event; 29561.61Skre SYSCALL_REQUIRE( 29571.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29581.61Skre SYSCALL_REQUIRE( 29591.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29601.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29611.125Skamil get_event.pe_set_event); 29621.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29631.1Skamil 29641.13Schristos DPRINTF("Before resuming the child process where it left off and " 29651.1Skamil "without signal to be sent\n"); 29661.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29671.1Skamil 29681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29691.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29701.1Skamil 29711.1Skamil validate_status_exited(status, exitval); 29721.1Skamil 29731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29741.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29751.1Skamil} 29761.1Skamil 29771.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29781.61SkreATF_TC(test); \ 29791.61SkreATF_TC_HEAD(test, tc) \ 29801.61Skre{ \ 29811.61Skre atf_tc_set_md_var(tc, "descr", \ 29821.61Skre "Verify that eventmask " #event " is preserved"); \ 29831.61Skre} \ 29841.61Skre \ 29851.61SkreATF_TC_BODY(test, tc) \ 29861.61Skre{ \ 29871.61Skre \ 29881.61Skre eventmask_preserved(event); \ 29891.1Skamil} 29901.1Skamil 29911.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29921.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29931.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29941.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29951.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29961.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29971.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 29981.1Skamil 29991.53Skamil/// ---------------------------------------------------------------------------- 30001.1Skamil 30011.28Skamilstatic void 30021.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 30031.105Skamil bool trackvforkdone) 30041.1Skamil{ 30051.1Skamil const int exitval = 5; 30061.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30071.1Skamil const int sigval = SIGSTOP; 30081.31Skamil pid_t child, child2 = 0, wpid; 30091.1Skamil#if defined(TWAIT_HAVE_STATUS) 30101.1Skamil int status; 30111.1Skamil#endif 30121.1Skamil ptrace_state_t state; 30131.1Skamil const int slen = sizeof(state); 30141.1Skamil ptrace_event_t event; 30151.1Skamil const int elen = sizeof(event); 30161.1Skamil 30171.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30181.124Skamil 30191.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30201.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30211.1Skamil if (child == 0) { 30221.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30231.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30241.1Skamil 30251.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30261.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30271.1Skamil 30281.125Skamil if (strcmp(fn, "spawn") == 0) { 30291.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30301.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30311.125Skamil } else { 30321.125Skamil if (strcmp(fn, "fork") == 0) { 30331.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30341.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30351.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30361.125Skamil } 30371.1Skamil 30381.124Skamil if (child2 == 0) 30391.124Skamil _exit(exitval2); 30401.124Skamil } 30411.1Skamil FORKEE_REQUIRE_SUCCESS 30421.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30431.1Skamil 30441.1Skamil forkee_status_exited(status, exitval2); 30451.1Skamil 30461.13Schristos DPRINTF("Before exiting of the child process\n"); 30471.1Skamil _exit(exitval); 30481.1Skamil } 30491.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30501.1Skamil 30511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30531.1Skamil 30541.1Skamil validate_status_stopped(status, sigval); 30551.1Skamil 30561.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30571.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30581.61Skre trackfork ? "|PTRACE_FORK" : "", 30591.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30601.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30611.30Skamil event.pe_set_event = 0; 30621.125Skamil if (trackspawn) 30631.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30641.30Skamil if (trackfork) 30651.30Skamil event.pe_set_event |= PTRACE_FORK; 30661.30Skamil if (trackvfork) 30671.30Skamil event.pe_set_event |= PTRACE_VFORK; 30681.30Skamil if (trackvforkdone) 30691.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30701.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30711.1Skamil 30721.13Schristos DPRINTF("Before resuming the child process where it left off and " 30731.1Skamil "without signal to be sent\n"); 30741.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30751.1Skamil 30761.29Skamil#if defined(TWAIT_HAVE_PID) 30771.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 30781.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 30791.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 30801.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30811.61Skre child); 30821.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30831.61Skre child); 30841.1Skamil 30851.29Skamil validate_status_stopped(status, SIGTRAP); 30861.1Skamil 30871.61Skre SYSCALL_REQUIRE( 30881.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30891.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 30901.125Skamil ATF_REQUIRE_EQ( 30911.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 30921.125Skamil PTRACE_POSIX_SPAWN); 30931.125Skamil } 30941.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 30951.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30961.30Skamil PTRACE_FORK); 30971.30Skamil } 30981.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 30991.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31001.30Skamil PTRACE_VFORK); 31011.30Skamil } 31021.29Skamil 31031.29Skamil child2 = state.pe_other_pid; 31041.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31051.29Skamil 31061.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31071.61Skre "%d\n", TWAIT_FNAME, child2, child); 31081.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31091.29Skamil child2); 31101.1Skamil 31111.29Skamil validate_status_stopped(status, SIGTRAP); 31121.1Skamil 31131.61Skre SYSCALL_REQUIRE( 31141.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31151.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31161.125Skamil ATF_REQUIRE_EQ( 31171.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31181.125Skamil PTRACE_POSIX_SPAWN); 31191.125Skamil } 31201.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31211.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31221.30Skamil PTRACE_FORK); 31231.30Skamil } 31241.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31251.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31261.30Skamil PTRACE_VFORK); 31271.30Skamil } 31281.30Skamil 31291.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31301.29Skamil 31311.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31321.29Skamil "and without signal to be sent\n"); 31331.61Skre SYSCALL_REQUIRE( 31341.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31351.29Skamil 31361.29Skamil DPRINTF("Before resuming the child process where it left off " 31371.61Skre "and without signal to be sent\n"); 31381.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31391.30Skamil } 31401.30Skamil#endif 31411.30Skamil 31421.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31431.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31441.61Skre child); 31451.61Skre TWAIT_REQUIRE_SUCCESS( 31461.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31471.30Skamil 31481.30Skamil validate_status_stopped(status, SIGTRAP); 31491.30Skamil 31501.61Skre SYSCALL_REQUIRE( 31511.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31521.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31531.30Skamil 31541.30Skamil child2 = state.pe_other_pid; 31551.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31561.61Skre child2); 31571.30Skamil 31581.30Skamil DPRINTF("Before resuming the child process where it left off " 31591.61Skre "and without signal to be sent\n"); 31601.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31611.30Skamil } 31621.29Skamil 31631.30Skamil#if defined(TWAIT_HAVE_PID) 31641.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31651.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31661.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31671.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31681.61Skre "\n", TWAIT_FNAME); 31691.61Skre TWAIT_REQUIRE_SUCCESS( 31701.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31711.29Skamil 31721.29Skamil validate_status_exited(status, exitval2); 31731.29Skamil 31741.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31751.61Skre "process\n", TWAIT_FNAME); 31761.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31771.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31781.29Skamil } 31791.29Skamil#endif 31801.1Skamil 31811.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31821.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31841.1Skamil 31851.1Skamil validate_status_stopped(status, SIGCHLD); 31861.1Skamil 31871.13Schristos DPRINTF("Before resuming the child process where it left off and " 31881.1Skamil "without signal to be sent\n"); 31891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31901.1Skamil 31911.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31921.1Skamil TWAIT_FNAME); 31931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31941.1Skamil 31951.1Skamil validate_status_exited(status, exitval); 31961.1Skamil 31971.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31981.1Skamil TWAIT_FNAME); 31991.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32001.1Skamil} 32011.28Skamil 32021.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 32031.61SkreATF_TC(name); \ 32041.61SkreATF_TC_HEAD(name, tc) \ 32051.61Skre{ \ 32061.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32071.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32081.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32091.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32101.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32111.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32121.61Skre} \ 32131.61Skre \ 32141.61SkreATF_TC_BODY(name, tc) \ 32151.61Skre{ \ 32161.61Skre \ 32171.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32181.32Skamil} 32191.32Skamil 32201.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32211.31Skamil#if defined(TWAIT_HAVE_PID) 32221.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32231.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32241.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32251.31Skamil#endif 32261.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32271.31Skamil#if defined(TWAIT_HAVE_PID) 32281.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32291.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32301.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32311.125Skamil#endif 32321.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32331.125Skamil#if defined(TWAIT_HAVE_PID) 32341.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32351.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32361.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32371.125Skamil#endif 32381.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32391.125Skamil#if defined(TWAIT_HAVE_PID) 32401.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32411.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32421.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32431.31Skamil#endif 32441.1Skamil 32451.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32461.31Skamil#if defined(TWAIT_HAVE_PID) 32471.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32481.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32491.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32501.31Skamil#endif 32511.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32521.31Skamil#if defined(TWAIT_HAVE_PID) 32531.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32541.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32551.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32561.31Skamil#endif 32571.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32581.125Skamil#if defined(TWAIT_HAVE_PID) 32591.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32601.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32611.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32621.110Skamil#endif 32631.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32641.124Skamil#if defined(TWAIT_HAVE_PID) 32651.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32661.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32671.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32681.124Skamil#endif 32691.125Skamil 32701.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32711.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32721.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32731.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32741.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32751.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32761.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32771.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 32781.124Skamil#if defined(TWAIT_HAVE_PID) 32791.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 32801.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 32811.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 32821.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 32831.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 32841.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 32851.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 32861.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 32871.124Skamil#endif 32881.124Skamil 32891.54Skamil/// ---------------------------------------------------------------------------- 32901.31Skamil 32911.116Skamil#if defined(TWAIT_HAVE_PID) 32921.116Skamilstatic void 32931.149Skamilunrelated_tracer_fork_body(const char *fn, bool trackspawn, bool trackfork, 32941.149Skamil bool trackvfork, bool trackvforkdone) 32951.149Skamil{ 32961.149Skamil const int sigval = SIGSTOP; 32971.149Skamil struct msg_fds parent_tracee, parent_tracer; 32981.149Skamil const int exitval = 10; 32991.149Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 33001.149Skamil pid_t tracee, tracer, wpid; 33011.149Skamil pid_t tracee2 = 0; 33021.149Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 33031.149Skamil#if defined(TWAIT_HAVE_STATUS) 33041.149Skamil int status; 33051.149Skamil#endif 33061.149Skamil 33071.149Skamil struct ptrace_siginfo info; 33081.149Skamil ptrace_state_t state; 33091.149Skamil const int slen = sizeof(state); 33101.149Skamil ptrace_event_t event; 33111.149Skamil const int elen = sizeof(event); 33121.149Skamil 33131.149Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33141.149Skamil 33151.149Skamil DPRINTF("Spawn tracee\n"); 33161.149Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 33171.149Skamil tracee = atf_utils_fork(); 33181.149Skamil if (tracee == 0) { 33191.149Skamil // Wait for parent to let us crash 33201.149Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 33211.149Skamil 33221.149Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33231.149Skamil FORKEE_ASSERT(raise(sigval) == 0); 33241.149Skamil 33251.149Skamil if (strcmp(fn, "spawn") == 0) { 33261.149Skamil FORKEE_ASSERT_EQ(posix_spawn(&tracee2, 33271.149Skamil arg[0], NULL, NULL, arg, NULL), 0); 33281.149Skamil } else { 33291.149Skamil if (strcmp(fn, "fork") == 0) { 33301.149Skamil FORKEE_ASSERT((tracee2 = fork()) != -1); 33311.149Skamil } else if (strcmp(fn, "vfork") == 0) { 33321.149Skamil FORKEE_ASSERT((tracee2 = vfork()) != -1); 33331.149Skamil } 33341.149Skamil 33351.149Skamil if (tracee2 == 0) 33361.149Skamil _exit(exitval2); 33371.149Skamil } 33381.149Skamil FORKEE_REQUIRE_SUCCESS 33391.149Skamil (wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 33401.149Skamil 33411.149Skamil forkee_status_exited(status, exitval2); 33421.149Skamil 33431.149Skamil DPRINTF("Before exiting of the child process\n"); 33441.149Skamil _exit(exitval); 33451.149Skamil } 33461.149Skamil 33471.149Skamil DPRINTF("Spawn debugger\n"); 33481.149Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 33491.149Skamil tracer = atf_utils_fork(); 33501.149Skamil if (tracer == 0) { 33511.149Skamil /* Fork again and drop parent to reattach to PID 1 */ 33521.149Skamil tracer = atf_utils_fork(); 33531.149Skamil if (tracer != 0) 33541.149Skamil _exit(exitval); 33551.149Skamil 33561.149Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 33571.149Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 33581.149Skamil 33591.149Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 33601.149Skamil FORKEE_REQUIRE_SUCCESS( 33611.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 33621.149Skamil 33631.149Skamil forkee_status_stopped(status, SIGSTOP); 33641.149Skamil 33651.149Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 33661.149Skamil "traced process\n"); 33671.149Skamil SYSCALL_REQUIRE( 33681.149Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 33691.149Skamil 33701.149Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 33711.149Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 33721.149Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 33731.149Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 33741.149Skamil 33751.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 33761.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 33771.149Skamil 33781.149Skamil /* Resume tracee with PT_CONTINUE */ 33791.149Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 33801.149Skamil 33811.149Skamil /* Inform parent that tracer has attached to tracee */ 33821.149Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 33831.149Skamil 33841.149Skamil /* Wait for parent to tell use that tracee should have exited */ 33851.149Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 33861.149Skamil 33871.149Skamil /* Wait for tracee and assert that it exited */ 33881.149Skamil FORKEE_REQUIRE_SUCCESS( 33891.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 33901.149Skamil 33911.149Skamil forkee_status_stopped(status, sigval); 33921.149Skamil 33931.149Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 33941.149Skamil "traced process\n"); 33951.149Skamil SYSCALL_REQUIRE( 33961.149Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 33971.149Skamil 33981.149Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 33991.149Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 34001.149Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 34011.149Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 34021.149Skamil 34031.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 34041.149Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 34051.149Skamil 34061.149Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 34071.149Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 34081.149Skamil trackfork ? "|PTRACE_FORK" : "", 34091.149Skamil trackvfork ? "|PTRACE_VFORK" : "", 34101.149Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", tracee); 34111.149Skamil event.pe_set_event = 0; 34121.149Skamil if (trackspawn) 34131.149Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 34141.149Skamil if (trackfork) 34151.149Skamil event.pe_set_event |= PTRACE_FORK; 34161.149Skamil if (trackvfork) 34171.149Skamil event.pe_set_event |= PTRACE_VFORK; 34181.149Skamil if (trackvforkdone) 34191.149Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 34201.149Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, tracee, &event, elen) 34211.149Skamil != -1); 34221.149Skamil 34231.149Skamil DPRINTF("Before resuming the child process where it left off " 34241.149Skamil "and without signal to be sent\n"); 34251.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 34261.149Skamil 34271.149Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 34281.149Skamil (trackfork && strcmp(fn, "fork") == 0) || 34291.149Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 34301.149Skamil DPRINTF("Before calling %s() for the tracee %d\n", TWAIT_FNAME, 34311.149Skamil tracee); 34321.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), 34331.149Skamil tracee); 34341.149Skamil 34351.149Skamil validate_status_stopped(status, SIGTRAP); 34361.149Skamil 34371.149Skamil SYSCALL_REQUIRE( 34381.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 34391.149Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 34401.149Skamil ATF_REQUIRE_EQ( 34411.149Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 34421.149Skamil PTRACE_POSIX_SPAWN); 34431.149Skamil } 34441.149Skamil if (trackfork && strcmp(fn, "fork") == 0) { 34451.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 34461.149Skamil PTRACE_FORK); 34471.149Skamil } 34481.149Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 34491.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 34501.149Skamil PTRACE_VFORK); 34511.149Skamil } 34521.149Skamil 34531.149Skamil tracee2 = state.pe_other_pid; 34541.149Skamil DPRINTF("Reported ptrace event with forkee %d\n", tracee2); 34551.149Skamil 34561.149Skamil DPRINTF("Before calling %s() for the forkee %d of the tracee " 34571.149Skamil "%d\n", TWAIT_FNAME, tracee2, tracee); 34581.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), 34591.149Skamil tracee2); 34601.149Skamil 34611.149Skamil validate_status_stopped(status, SIGTRAP); 34621.149Skamil 34631.149Skamil SYSCALL_REQUIRE( 34641.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee2, &state, slen) != -1); 34651.149Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 34661.149Skamil ATF_REQUIRE_EQ( 34671.149Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 34681.149Skamil PTRACE_POSIX_SPAWN); 34691.149Skamil } 34701.149Skamil if (trackfork && strcmp(fn, "fork") == 0) { 34711.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 34721.149Skamil PTRACE_FORK); 34731.149Skamil } 34741.149Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 34751.149Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 34761.149Skamil PTRACE_VFORK); 34771.149Skamil } 34781.149Skamil 34791.149Skamil ATF_REQUIRE_EQ(state.pe_other_pid, tracee); 34801.149Skamil 34811.149Skamil DPRINTF("Before resuming the forkee process where it left off " 34821.149Skamil "and without signal to be sent\n"); 34831.149Skamil SYSCALL_REQUIRE( 34841.149Skamil ptrace(PT_CONTINUE, tracee2, (void *)1, 0) != -1); 34851.149Skamil 34861.149Skamil DPRINTF("Before resuming the tracee process where it left off " 34871.149Skamil "and without signal to be sent\n"); 34881.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 34891.149Skamil } 34901.149Skamil 34911.149Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 34921.149Skamil DPRINTF("Before calling %s() for the tracee %d\n", TWAIT_FNAME, 34931.149Skamil tracee); 34941.149Skamil TWAIT_REQUIRE_SUCCESS( 34951.149Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 34961.149Skamil 34971.149Skamil validate_status_stopped(status, SIGTRAP); 34981.149Skamil 34991.149Skamil SYSCALL_REQUIRE( 35001.149Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 35011.149Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 35021.149Skamil 35031.149Skamil tracee2 = state.pe_other_pid; 35041.149Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 35051.149Skamil tracee2); 35061.149Skamil 35071.149Skamil DPRINTF("Before resuming the tracee process where it left off " 35081.149Skamil "and without signal to be sent\n"); 35091.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 35101.149Skamil } 35111.149Skamil 35121.149Skamil 35131.149Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 35141.149Skamil (trackfork && strcmp(fn, "fork") == 0) || 35151.149Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 35161.149Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 35171.149Skamil "\n", TWAIT_FNAME); 35181.149Skamil TWAIT_REQUIRE_SUCCESS( 35191.149Skamil wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 35201.149Skamil 35211.149Skamil validate_status_exited(status, exitval2); 35221.149Skamil 35231.149Skamil DPRINTF("Before calling %s() for the forkee - expected no " 35241.149Skamil "process\n", TWAIT_FNAME); 35251.149Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 35261.149Skamil wpid = TWAIT_GENERIC(tracee2, &status, 0)); 35271.149Skamil } 35281.149Skamil 35291.149Skamil DPRINTF("Before calling %s() for the tracee - expected stopped " 35301.149Skamil "SIGCHLD\n", TWAIT_FNAME); 35311.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35321.149Skamil 35331.149Skamil validate_status_stopped(status, SIGCHLD); 35341.149Skamil 35351.149Skamil DPRINTF("Before resuming the tracee process where it left off and " 35361.149Skamil "without signal to be sent\n"); 35371.149Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 35381.149Skamil 35391.149Skamil DPRINTF("Before calling %s() for the tracee - expected exited\n", 35401.149Skamil TWAIT_FNAME); 35411.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35421.149Skamil 35431.149Skamil validate_status_exited(status, exitval); 35441.149Skamil 35451.149Skamil /* Inform parent that tracer is exiting normally */ 35461.149Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 35471.149Skamil 35481.149Skamil DPRINTF("Before exiting of the tracer process\n"); 35491.149Skamil _exit(0 /* collect by initproc */); 35501.149Skamil } 35511.149Skamil 35521.149Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 35531.149Skamil "calling %s()\n", TWAIT_FNAME); 35541.149Skamil TWAIT_REQUIRE_SUCCESS( 35551.149Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 35561.149Skamil 35571.149Skamil validate_status_exited(status, exitval); 35581.149Skamil 35591.149Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 35601.149Skamil TWAIT_FNAME); 35611.149Skamil TWAIT_REQUIRE_SUCCESS( 35621.149Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 35631.149Skamil 35641.149Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 35651.149Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 35661.149Skamil 35671.149Skamil DPRINTF("Resume the tracee and let it crash\n"); 35681.149Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 35691.149Skamil 35701.149Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 35711.149Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 35721.149Skamil 35731.149Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 35741.149Skamil TWAIT_FNAME); 35751.149Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35761.149Skamil 35771.149Skamil validate_status_exited(status, exitval); 35781.149Skamil 35791.149Skamil DPRINTF("Await normal exit of tracer\n"); 35801.149Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 35811.149Skamil 35821.149Skamil msg_close(&parent_tracer); 35831.149Skamil msg_close(&parent_tracee); 35841.149Skamil} 35851.149Skamil 35861.149Skamil#define UNRELATED_TRACER_FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone)\ 35871.149SkamilATF_TC(name); \ 35881.149SkamilATF_TC_HEAD(name, tc) \ 35891.149Skamil{ \ 35901.149Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 35911.149Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 35921.149Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 35931.149Skamil tfork ? "|PTRACE_FORK" : "", \ 35941.149Skamil tvfork ? "|PTRACE_VFORK" : "", \ 35951.149Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 35961.149Skamil} \ 35971.149Skamil \ 35981.149SkamilATF_TC_BODY(name, tc) \ 35991.149Skamil{ \ 36001.149Skamil \ 36011.149Skamil unrelated_tracer_fork_body(fun, tspawn, tfork, tvfork, \ 36021.149Skamil tvforkdone); \ 36031.149Skamil} 36041.149Skamil 36051.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork1, "fork", false, false, false, false) 36061.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork2, "fork", false, true, false, false) 36071.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork3, "fork", false, false, true, false) 36081.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork4, "fork", false, true, true, false) 36091.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork5, "fork", false, false, false, true) 36101.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork6, "fork", false, true, false, true) 36111.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork7, "fork", false, false, true, true) 36121.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork8, "fork", false, true, true, true) 36131.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork9, "fork", true, false, false, false) 36141.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork10, "fork", true, true, false, false) 36151.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork11, "fork", true, false, true, false) 36161.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork12, "fork", true, true, true, false) 36171.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork13, "fork", true, false, false, true) 36181.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork14, "fork", true, true, false, true) 36191.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork15, "fork", true, false, true, true) 36201.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_fork16, "fork", true, true, true, true) 36211.149Skamil 36221.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork1, "vfork", false, false, false, false) 36231.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork2, "vfork", false, true, false, false) 36241.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork3, "vfork", false, false, true, false) 36251.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork4, "vfork", false, true, true, false) 36261.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork5, "vfork", false, false, false, true) 36271.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork6, "vfork", false, true, false, true) 36281.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork7, "vfork", false, false, true, true) 36291.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork8, "vfork", false, true, true, true) 36301.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork9, "vfork", true, false, false, false) 36311.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork10, "vfork", true, true, false, false) 36321.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork11, "vfork", true, false, true, false) 36331.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork12, "vfork", true, true, true, false) 36341.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork13, "vfork", true, false, false, true) 36351.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork14, "vfork", true, true, false, true) 36361.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork15, "vfork", true, false, true, true) 36371.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_vfork16, "vfork", true, true, true, true) 36381.149Skamil 36391.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn1, "spawn", false, false, false, false) 36401.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn2, "spawn", false, true, false, false) 36411.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn3, "spawn", false, false, true, false) 36421.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn4, "spawn", false, true, true, false) 36431.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn5, "spawn", false, false, false, true) 36441.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn6, "spawn", false, true, false, true) 36451.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn7, "spawn", false, false, true, true) 36461.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn8, "spawn", false, true, true, true) 36471.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn9, "spawn", true, false, false, false) 36481.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn10, "spawn", true, true, false, false) 36491.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn11, "spawn", true, false, true, false) 36501.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn12, "spawn", true, true, true, false) 36511.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn13, "spawn", true, false, false, true) 36521.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn14, "spawn", true, true, false, true) 36531.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn15, "spawn", true, false, true, true) 36541.149SkamilUNRELATED_TRACER_FORK_TEST(unrelated_tracer_posix_spawn16, "spawn", true, true, true, true) 36551.149Skamil#endif 36561.149Skamil 36571.149Skamil/// ---------------------------------------------------------------------------- 36581.149Skamil 36591.149Skamil#if defined(TWAIT_HAVE_PID) 36601.149Skamilstatic void 36611.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 36621.116Skamil{ 36631.116Skamil const int exitval = 5; 36641.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 36651.116Skamil const int sigval = SIGSTOP; 36661.116Skamil pid_t child, child2 = 0, wpid; 36671.116Skamil#if defined(TWAIT_HAVE_STATUS) 36681.116Skamil int status; 36691.116Skamil#endif 36701.116Skamil ptrace_state_t state; 36711.116Skamil const int slen = sizeof(state); 36721.116Skamil ptrace_event_t event; 36731.116Skamil const int elen = sizeof(event); 36741.116Skamil 36751.116Skamil int op; 36761.116Skamil 36771.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 36781.116Skamil 36791.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 36801.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 36811.116Skamil if (child == 0) { 36821.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36831.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36841.116Skamil 36851.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 36861.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 36871.116Skamil 36881.126Skamil if (strcmp(fn, "spawn") == 0) { 36891.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 36901.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 36911.126Skamil } else { 36921.126Skamil if (strcmp(fn, "fork") == 0) { 36931.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 36941.126Skamil } else { 36951.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 36961.126Skamil } 36971.116Skamil 36981.126Skamil if (child2 == 0) 36991.126Skamil _exit(exitval2); 37001.126Skamil } 37011.116Skamil 37021.116Skamil FORKEE_REQUIRE_SUCCESS 37031.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 37041.116Skamil 37051.116Skamil forkee_status_exited(status, exitval2); 37061.116Skamil 37071.116Skamil DPRINTF("Before exiting of the child process\n"); 37081.116Skamil _exit(exitval); 37091.116Skamil } 37101.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37111.116Skamil 37121.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37131.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37141.116Skamil 37151.116Skamil validate_status_stopped(status, sigval); 37161.116Skamil 37171.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 37181.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 37191.126Skamil | PTRACE_VFORK_DONE; 37201.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 37211.116Skamil 37221.116Skamil DPRINTF("Before resuming the child process where it left off and " 37231.116Skamil "without signal to be sent\n"); 37241.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 37251.116Skamil 37261.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 37271.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37281.116Skamil 37291.116Skamil validate_status_stopped(status, SIGTRAP); 37301.116Skamil 37311.116Skamil SYSCALL_REQUIRE( 37321.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 37331.126Skamil 37341.126Skamil if (strcmp(fn, "spawn") == 0) 37351.126Skamil op = PTRACE_POSIX_SPAWN; 37361.126Skamil else if (strcmp(fn, "fork") == 0) 37371.126Skamil op = PTRACE_FORK; 37381.126Skamil else 37391.126Skamil op = PTRACE_VFORK; 37401.126Skamil 37411.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 37421.116Skamil 37431.116Skamil child2 = state.pe_other_pid; 37441.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 37451.116Skamil 37461.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 37471.126Skamil strcmp(fn, "vfork") == 0) 37481.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 37491.116Skamil else 37501.116Skamil op = PT_CONTINUE; 37511.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 37521.116Skamil 37531.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 37541.116Skamil TWAIT_FNAME, child2, child); 37551.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 37561.116Skamil 37571.116Skamil validate_status_stopped(status, SIGTRAP); 37581.116Skamil 37591.116Skamil SYSCALL_REQUIRE( 37601.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 37611.126Skamil if (strcmp(fn, "spawn") == 0) 37621.126Skamil op = PTRACE_POSIX_SPAWN; 37631.126Skamil else if (strcmp(fn, "fork") == 0) 37641.126Skamil op = PTRACE_FORK; 37651.126Skamil else 37661.126Skamil op = PTRACE_VFORK; 37671.126Skamil 37681.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 37691.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 37701.116Skamil 37711.116Skamil DPRINTF("Before resuming the forkee process where it left off " 37721.116Skamil "and without signal to be sent\n"); 37731.116Skamil SYSCALL_REQUIRE( 37741.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 37751.116Skamil 37761.126Skamil if (strcmp(fn, "vforkdone") == 0) { 37771.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 37781.116Skamil child); 37791.116Skamil TWAIT_REQUIRE_SUCCESS( 37801.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 37811.116Skamil 37821.116Skamil validate_status_stopped(status, SIGTRAP); 37831.116Skamil 37841.116Skamil SYSCALL_REQUIRE( 37851.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 37861.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 37871.116Skamil 37881.116Skamil child2 = state.pe_other_pid; 37891.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 37901.116Skamil child2); 37911.116Skamil 37921.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 37931.116Skamil DPRINTF("Before resuming the child process where it left off " 37941.116Skamil "and without signal to be sent\n"); 37951.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 37961.116Skamil } 37971.116Skamil 37981.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 37991.116Skamil TWAIT_FNAME); 38001.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 38011.116Skamil 38021.116Skamil validate_status_exited(status, exitval2); 38031.116Skamil 38041.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 38051.116Skamil TWAIT_FNAME); 38061.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 38071.116Skamil 38081.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 38091.116Skamil TWAIT_FNAME); 38101.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38111.116Skamil 38121.116Skamil if (kill_process) { 38131.116Skamil validate_status_signaled(status, SIGKILL, 0); 38141.116Skamil } else { 38151.116Skamil validate_status_exited(status, exitval); 38161.116Skamil } 38171.116Skamil 38181.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 38191.116Skamil TWAIT_FNAME); 38201.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 38211.116Skamil} 38221.116Skamil 38231.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 38241.116SkamilATF_TC(name); \ 38251.116SkamilATF_TC_HEAD(name, tc) \ 38261.116Skamil{ \ 38271.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 38281.126Skamil kprocess ? "killed" : "detached"); \ 38291.116Skamil} \ 38301.116Skamil \ 38311.116SkamilATF_TC_BODY(name, tc) \ 38321.116Skamil{ \ 38331.116Skamil \ 38341.126Skamil fork_detach_forker_body(event, kprocess); \ 38351.116Skamil} 38361.116Skamil 38371.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 38381.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 38391.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 38401.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 38411.126Skamil 38421.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 38431.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 38441.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 38451.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 38461.116Skamil#endif 38471.116Skamil 38481.116Skamil/// ---------------------------------------------------------------------------- 38491.116Skamil 38501.150Skamil#if defined(TWAIT_HAVE_PID) 38511.150Skamilstatic void 38521.150Skamilunrelated_tracer_fork_detach_forker_body(const char *fn, bool kill_process) 38531.150Skamil{ 38541.150Skamil const int sigval = SIGSTOP; 38551.150Skamil struct msg_fds parent_tracee, parent_tracer; 38561.150Skamil const int exitval = 10; 38571.150Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 38581.150Skamil pid_t tracee, tracer, wpid; 38591.150Skamil pid_t tracee2 = 0; 38601.150Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 38611.150Skamil#if defined(TWAIT_HAVE_STATUS) 38621.150Skamil int status; 38631.150Skamil#endif 38641.150Skamil int op; 38651.150Skamil 38661.150Skamil struct ptrace_siginfo info; 38671.150Skamil ptrace_state_t state; 38681.150Skamil const int slen = sizeof(state); 38691.150Skamil ptrace_event_t event; 38701.150Skamil const int elen = sizeof(event); 38711.150Skamil 38721.150Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 38731.150Skamil 38741.150Skamil DPRINTF("Spawn tracee\n"); 38751.150Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 38761.150Skamil tracee = atf_utils_fork(); 38771.150Skamil if (tracee == 0) { 38781.150Skamil // Wait for parent to let us crash 38791.150Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 38801.150Skamil 38811.150Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 38821.150Skamil FORKEE_ASSERT(raise(sigval) == 0); 38831.150Skamil 38841.150Skamil if (strcmp(fn, "spawn") == 0) { 38851.150Skamil FORKEE_ASSERT_EQ(posix_spawn(&tracee2, 38861.150Skamil arg[0], NULL, NULL, arg, NULL), 0); 38871.150Skamil } else { 38881.150Skamil if (strcmp(fn, "fork") == 0) { 38891.150Skamil FORKEE_ASSERT((tracee2 = fork()) != -1); 38901.150Skamil } else { 38911.150Skamil FORKEE_ASSERT((tracee2 = vfork()) != -1); 38921.150Skamil } 38931.150Skamil 38941.150Skamil if (tracee2 == 0) 38951.150Skamil _exit(exitval2); 38961.150Skamil } 38971.150Skamil 38981.150Skamil FORKEE_REQUIRE_SUCCESS 38991.150Skamil (wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 39001.150Skamil 39011.150Skamil forkee_status_exited(status, exitval2); 39021.150Skamil 39031.150Skamil DPRINTF("Before exiting of the child process\n"); 39041.150Skamil _exit(exitval); 39051.150Skamil } 39061.150Skamil 39071.150Skamil DPRINTF("Spawn debugger\n"); 39081.150Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 39091.150Skamil tracer = atf_utils_fork(); 39101.150Skamil if (tracer == 0) { 39111.150Skamil /* Fork again and drop parent to reattach to PID 1 */ 39121.150Skamil tracer = atf_utils_fork(); 39131.150Skamil if (tracer != 0) 39141.150Skamil _exit(exitval); 39151.150Skamil 39161.150Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 39171.150Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 39181.150Skamil 39191.150Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 39201.150Skamil FORKEE_REQUIRE_SUCCESS( 39211.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 39221.150Skamil 39231.150Skamil forkee_status_stopped(status, SIGSTOP); 39241.150Skamil 39251.150Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 39261.150Skamil "traced process\n"); 39271.150Skamil SYSCALL_REQUIRE( 39281.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 39291.150Skamil 39301.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39311.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39321.150Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 39331.150Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 39341.150Skamil 39351.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 39361.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 39371.150Skamil 39381.150Skamil /* Resume tracee with PT_CONTINUE */ 39391.150Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 39401.150Skamil 39411.150Skamil /* Inform parent that tracer has attached to tracee */ 39421.150Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 39431.150Skamil 39441.150Skamil /* Wait for parent to tell use that tracee should have exited */ 39451.150Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 39461.150Skamil 39471.150Skamil /* Wait for tracee and assert that it exited */ 39481.150Skamil FORKEE_REQUIRE_SUCCESS( 39491.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 39501.150Skamil 39511.150Skamil forkee_status_stopped(status, sigval); 39521.150Skamil 39531.150Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 39541.150Skamil "traced process\n"); 39551.150Skamil SYSCALL_REQUIRE( 39561.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 39571.150Skamil 39581.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39591.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39601.150Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 39611.150Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 39621.150Skamil 39631.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 39641.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 39651.150Skamil 39661.150Skamil DPRINTF("Set EVENT_MASK for the child %d\n", tracee); 39671.150Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 39681.150Skamil | PTRACE_VFORK_DONE; 39691.150Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, tracee, &event, elen) != -1); 39701.150Skamil 39711.150Skamil DPRINTF("Before resuming the child process where it left off and " 39721.150Skamil "without signal to be sent\n"); 39731.150Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 39741.150Skamil 39751.150Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, tracee); 39761.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 39771.150Skamil 39781.150Skamil validate_status_stopped(status, SIGTRAP); 39791.150Skamil 39801.150Skamil SYSCALL_REQUIRE( 39811.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 39821.150Skamil 39831.150Skamil if (strcmp(fn, "spawn") == 0) 39841.150Skamil op = PTRACE_POSIX_SPAWN; 39851.150Skamil else if (strcmp(fn, "fork") == 0) 39861.150Skamil op = PTRACE_FORK; 39871.150Skamil else 39881.150Skamil op = PTRACE_VFORK; 39891.150Skamil 39901.150Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 39911.150Skamil 39921.150Skamil tracee2 = state.pe_other_pid; 39931.150Skamil DPRINTF("Reported ptrace event with forkee %d\n", tracee2); 39941.150Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 39951.150Skamil strcmp(fn, "vfork") == 0) 39961.150Skamil op = kill_process ? PT_KILL : PT_DETACH; 39971.150Skamil else 39981.150Skamil op = PT_CONTINUE; 39991.150Skamil SYSCALL_REQUIRE(ptrace(op, tracee, (void *)1, 0) != -1); 40001.150Skamil 40011.150Skamil DPRINTF("Before calling %s() for the forkee %d of the tracee %d\n", 40021.150Skamil TWAIT_FNAME, tracee2, tracee); 40031.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 40041.150Skamil 40051.150Skamil validate_status_stopped(status, SIGTRAP); 40061.150Skamil 40071.150Skamil SYSCALL_REQUIRE( 40081.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee2, &state, slen) != -1); 40091.150Skamil if (strcmp(fn, "spawn") == 0) 40101.150Skamil op = PTRACE_POSIX_SPAWN; 40111.150Skamil else if (strcmp(fn, "fork") == 0) 40121.150Skamil op = PTRACE_FORK; 40131.150Skamil else 40141.150Skamil op = PTRACE_VFORK; 40151.150Skamil 40161.150Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 40171.150Skamil ATF_REQUIRE_EQ(state.pe_other_pid, tracee); 40181.150Skamil 40191.150Skamil DPRINTF("Before resuming the forkee process where it left off " 40201.150Skamil "and without signal to be sent\n"); 40211.150Skamil SYSCALL_REQUIRE( 40221.150Skamil ptrace(PT_CONTINUE, tracee2, (void *)1, 0) != -1); 40231.150Skamil 40241.150Skamil if (strcmp(fn, "vforkdone") == 0) { 40251.150Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 40261.150Skamil tracee); 40271.150Skamil TWAIT_REQUIRE_SUCCESS( 40281.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40291.150Skamil 40301.150Skamil validate_status_stopped(status, SIGTRAP); 40311.150Skamil 40321.150Skamil SYSCALL_REQUIRE( 40331.150Skamil ptrace(PT_GET_PROCESS_STATE, tracee, &state, slen) != -1); 40341.150Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 40351.150Skamil 40361.150Skamil tracee2 = state.pe_other_pid; 40371.150Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 40381.150Skamil tracee2); 40391.150Skamil 40401.150Skamil op = kill_process ? PT_KILL : PT_DETACH; 40411.150Skamil DPRINTF("Before resuming the child process where it left off " 40421.150Skamil "and without signal to be sent\n"); 40431.150Skamil SYSCALL_REQUIRE(ptrace(op, tracee, (void *)1, 0) != -1); 40441.150Skamil } 40451.150Skamil 40461.150Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 40471.150Skamil TWAIT_FNAME); 40481.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee2, &status, 0), tracee2); 40491.150Skamil 40501.150Skamil validate_status_exited(status, exitval2); 40511.150Skamil 40521.150Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 40531.150Skamil TWAIT_FNAME); 40541.150Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(tracee2, &status, 0)); 40551.150Skamil 40561.150Skamil if (kill_process) { 40571.150Skamil DPRINTF("Before calling %s() for the forkee - expected signaled\n", 40581.150Skamil TWAIT_FNAME); 40591.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40601.150Skamil 40611.150Skamil validate_status_signaled(status, SIGKILL, 0); 40621.150Skamil } 40631.150Skamil 40641.150Skamil /* Inform parent that tracer is exiting normally */ 40651.150Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 40661.150Skamil 40671.150Skamil DPRINTF("Before exiting of the tracer process\n"); 40681.150Skamil _exit(0 /* collect by initproc */); 40691.150Skamil } 40701.150Skamil 40711.150Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 40721.150Skamil "calling %s()\n", TWAIT_FNAME); 40731.150Skamil TWAIT_REQUIRE_SUCCESS( 40741.150Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 40751.150Skamil 40761.150Skamil validate_status_exited(status, exitval); 40771.150Skamil 40781.150Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 40791.150Skamil TWAIT_FNAME); 40801.150Skamil TWAIT_REQUIRE_SUCCESS( 40811.150Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 40821.150Skamil 40831.150Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 40841.150Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 40851.150Skamil 40861.150Skamil DPRINTF("Resume the tracee and let it crash\n"); 40871.150Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 40881.150Skamil 40891.150Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 40901.150Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 40911.150Skamil 40921.150Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 40931.150Skamil TWAIT_FNAME); 40941.150Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 40951.150Skamil 40961.150Skamil if (kill_process) { 40971.150Skamil validate_status_signaled(status, SIGKILL, 0); 40981.150Skamil } else { 40991.150Skamil validate_status_exited(status, exitval); 41001.150Skamil } 41011.150Skamil 41021.150Skamil DPRINTF("Await normal exit of tracer\n"); 41031.150Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 41041.150Skamil 41051.150Skamil msg_close(&parent_tracer); 41061.150Skamil msg_close(&parent_tracee); 41071.150Skamil} 41081.150Skamil 41091.150Skamil#define UNRELATED_TRACER_FORK_DETACH_FORKER(name,event,kprocess) \ 41101.150SkamilATF_TC(name); \ 41111.150SkamilATF_TC_HEAD(name, tc) \ 41121.150Skamil{ \ 41131.150Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 41141.150Skamil kprocess ? "killed" : "detached"); \ 41151.150Skamil} \ 41161.150Skamil \ 41171.150SkamilATF_TC_BODY(name, tc) \ 41181.150Skamil{ \ 41191.150Skamil \ 41201.150Skamil unrelated_tracer_fork_detach_forker_body(event, kprocess); \ 41211.150Skamil} 41221.150Skamil 41231.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_posix_spawn_detach_spawner, "spawn", false) 41241.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_fork_detach_forker, "fork", false) 41251.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_detach_vforker, "vfork", false) 41261.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_detach_vforkerdone, "vforkdone", false) 41271.150Skamil 41281.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_posix_spawn_kill_spawner, "spawn", true) 41291.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_fork_kill_forker, "fork", true) 41301.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_kill_vforker, "vfork", true) 41311.150SkamilUNRELATED_TRACER_FORK_DETACH_FORKER(unrelated_tracer_vfork_kill_vforkerdone, "vforkdone", true) 41321.150Skamil#endif 41331.150Skamil 41341.150Skamil/// ---------------------------------------------------------------------------- 41351.150Skamil 41361.108Skamilstatic void 41371.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 41381.108Skamil{ 41391.108Skamil const int exitval = 5; 41401.108Skamil const int exitval2 = 15; 41411.108Skamil pid_t child, child2 = 0, wpid; 41421.108Skamil#if defined(TWAIT_HAVE_STATUS) 41431.108Skamil int status; 41441.108Skamil#endif 41451.108Skamil 41461.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 41471.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 41481.108Skamil if (child == 0) { 41491.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41501.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41511.108Skamil 41521.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 41531.108Skamil 41541.108Skamil if (child2 == 0) 41551.108Skamil _exit(exitval2); 41561.108Skamil 41571.108Skamil FORKEE_REQUIRE_SUCCESS 41581.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 41591.108Skamil 41601.108Skamil forkee_status_exited(status, exitval2); 41611.108Skamil 41621.108Skamil DPRINTF("Before exiting of the child process\n"); 41631.108Skamil _exit(exitval); 41641.108Skamil } 41651.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41661.108Skamil 41671.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 41681.108Skamil TWAIT_FNAME); 41691.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41701.108Skamil 41711.108Skamil validate_status_exited(status, exitval); 41721.108Skamil 41731.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 41741.108Skamil TWAIT_FNAME); 41751.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41761.108Skamil} 41771.108Skamil 41781.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 41791.108SkamilATF_TC(name); \ 41801.108SkamilATF_TC_HEAD(name, tc) \ 41811.108Skamil{ \ 41821.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 41831.108Skamil "called from vfork(2)ed child"); \ 41841.108Skamil} \ 41851.108Skamil \ 41861.108SkamilATF_TC_BODY(name, tc) \ 41871.108Skamil{ \ 41881.108Skamil \ 41891.108Skamil traceme_vfork_fork_body(fun); \ 41901.108Skamil} 41911.108Skamil 41921.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 41931.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 41941.108Skamil 41951.108Skamil/// ---------------------------------------------------------------------------- 41961.108Skamil 41971.54Skamilenum bytes_transfer_type { 41981.54Skamil BYTES_TRANSFER_DATA, 41991.54Skamil BYTES_TRANSFER_DATAIO, 42001.54Skamil BYTES_TRANSFER_TEXT, 42011.54Skamil BYTES_TRANSFER_TEXTIO, 42021.54Skamil BYTES_TRANSFER_AUXV 42031.54Skamil}; 42041.31Skamil 42051.54Skamilstatic int __used 42061.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 42071.54Skamil{ 42081.54Skamil int e, f, g, h; 42091.1Skamil 42101.54Skamil a *= 4; 42111.54Skamil b += 3; 42121.54Skamil c -= 2; 42131.54Skamil d /= 1; 42141.1Skamil 42151.54Skamil e = strtol("10", NULL, 10); 42161.54Skamil f = strtol("20", NULL, 10); 42171.54Skamil g = strtol("30", NULL, 10); 42181.54Skamil h = strtol("40", NULL, 10); 42191.1Skamil 42201.54Skamil return (a + b * c - d) + (e * f - g / h); 42211.1Skamil} 42221.1Skamil 42231.54Skamilstatic void 42241.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 42251.1Skamil{ 42261.1Skamil const int exitval = 5; 42271.1Skamil const int sigval = SIGSTOP; 42281.1Skamil pid_t child, wpid; 42291.54Skamil bool skip = false; 42301.1Skamil 42311.54Skamil int lookup_me = 0; 42321.54Skamil uint8_t lookup_me8 = 0; 42331.54Skamil uint16_t lookup_me16 = 0; 42341.54Skamil uint32_t lookup_me32 = 0; 42351.54Skamil uint64_t lookup_me64 = 0; 42361.1Skamil 42371.54Skamil int magic = 0x13579246; 42381.54Skamil uint8_t magic8 = 0xab; 42391.54Skamil uint16_t magic16 = 0x1234; 42401.54Skamil uint32_t magic32 = 0x98765432; 42411.54Skamil uint64_t magic64 = 0xabcdef0123456789; 42421.1Skamil 42431.54Skamil struct ptrace_io_desc io; 42441.1Skamil#if defined(TWAIT_HAVE_STATUS) 42451.1Skamil int status; 42461.1Skamil#endif 42471.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 42481.60Skre AuxInfo ai[513], *aip; 42491.55Schristos 42501.55Schristos ATF_REQUIRE(size < sizeof(ai)); 42511.1Skamil 42521.54Skamil /* Prepare variables for .TEXT transfers */ 42531.54Skamil switch (type) { 42541.54Skamil case BYTES_TRANSFER_TEXT: 42551.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 42561.54Skamil break; 42571.54Skamil case BYTES_TRANSFER_TEXTIO: 42581.54Skamil switch (size) { 42591.54Skamil case 8: 42601.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 42611.54Skamil break; 42621.54Skamil case 16: 42631.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 42641.54Skamil break; 42651.54Skamil case 32: 42661.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 42671.54Skamil break; 42681.54Skamil case 64: 42691.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 42701.54Skamil break; 42711.54Skamil } 42721.54Skamil break; 42731.54Skamil default: 42741.54Skamil break; 42751.54Skamil } 42761.1Skamil 42771.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 42781.54Skamil switch (type) { 42791.54Skamil case BYTES_TRANSFER_TEXTIO: 42801.54Skamil case BYTES_TRANSFER_DATAIO: 42811.54Skamil io.piod_op = operation; 42821.54Skamil switch (size) { 42831.54Skamil case 8: 42841.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 42851.54Skamil (void *)bytes_transfer_dummy : 42861.54Skamil &lookup_me8; 42871.54Skamil io.piod_addr = &lookup_me8; 42881.54Skamil io.piod_len = sizeof(lookup_me8); 42891.54Skamil break; 42901.54Skamil case 16: 42911.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 42921.54Skamil (void *)bytes_transfer_dummy : 42931.54Skamil &lookup_me16; 42941.54Skamil io.piod_addr = &lookup_me16; 42951.54Skamil io.piod_len = sizeof(lookup_me16); 42961.54Skamil break; 42971.54Skamil case 32: 42981.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 42991.54Skamil (void *)bytes_transfer_dummy : 43001.54Skamil &lookup_me32; 43011.54Skamil io.piod_addr = &lookup_me32; 43021.54Skamil io.piod_len = sizeof(lookup_me32); 43031.54Skamil break; 43041.54Skamil case 64: 43051.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 43061.54Skamil (void *)bytes_transfer_dummy : 43071.54Skamil &lookup_me64; 43081.54Skamil io.piod_addr = &lookup_me64; 43091.54Skamil io.piod_len = sizeof(lookup_me64); 43101.54Skamil break; 43111.54Skamil default: 43121.54Skamil break; 43131.54Skamil } 43141.54Skamil break; 43151.54Skamil case BYTES_TRANSFER_AUXV: 43161.54Skamil io.piod_op = operation; 43171.54Skamil io.piod_offs = 0; 43181.54Skamil io.piod_addr = ai; 43191.54Skamil io.piod_len = size; 43201.54Skamil break; 43211.54Skamil default: 43221.54Skamil break; 43231.1Skamil } 43241.1Skamil 43251.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43261.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43271.1Skamil if (child == 0) { 43281.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43291.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 43301.1Skamil 43311.54Skamil switch (type) { 43321.54Skamil case BYTES_TRANSFER_DATA: 43331.54Skamil switch (operation) { 43341.54Skamil case PT_READ_D: 43351.54Skamil case PT_READ_I: 43361.54Skamil lookup_me = magic; 43371.54Skamil break; 43381.54Skamil default: 43391.54Skamil break; 43401.54Skamil } 43411.54Skamil break; 43421.54Skamil case BYTES_TRANSFER_DATAIO: 43431.54Skamil switch (operation) { 43441.54Skamil case PIOD_READ_D: 43451.54Skamil case PIOD_READ_I: 43461.54Skamil switch (size) { 43471.54Skamil case 8: 43481.54Skamil lookup_me8 = magic8; 43491.54Skamil break; 43501.54Skamil case 16: 43511.54Skamil lookup_me16 = magic16; 43521.54Skamil break; 43531.54Skamil case 32: 43541.54Skamil lookup_me32 = magic32; 43551.54Skamil break; 43561.54Skamil case 64: 43571.54Skamil lookup_me64 = magic64; 43581.54Skamil break; 43591.54Skamil default: 43601.54Skamil break; 43611.54Skamil } 43621.54Skamil break; 43631.54Skamil default: 43641.54Skamil break; 43651.54Skamil } 43661.54Skamil default: 43671.54Skamil break; 43681.54Skamil } 43691.54Skamil 43701.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 43711.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 43721.1Skamil 43731.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 43741.54Skamil switch (type) { 43751.54Skamil case BYTES_TRANSFER_DATA: 43761.54Skamil switch (operation) { 43771.54Skamil case PT_WRITE_D: 43781.54Skamil case PT_WRITE_I: 43791.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 43801.54Skamil break; 43811.54Skamil default: 43821.54Skamil break; 43831.54Skamil } 43841.54Skamil break; 43851.54Skamil case BYTES_TRANSFER_DATAIO: 43861.54Skamil switch (operation) { 43871.54Skamil case PIOD_WRITE_D: 43881.54Skamil case PIOD_WRITE_I: 43891.54Skamil switch (size) { 43901.54Skamil case 8: 43911.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 43921.54Skamil break; 43931.54Skamil case 16: 43941.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 43951.54Skamil break; 43961.54Skamil case 32: 43971.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 43981.54Skamil break; 43991.54Skamil case 64: 44001.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 44011.54Skamil break; 44021.54Skamil default: 44031.54Skamil break; 44041.54Skamil } 44051.54Skamil break; 44061.54Skamil default: 44071.54Skamil break; 44081.54Skamil } 44091.54Skamil break; 44101.54Skamil case BYTES_TRANSFER_TEXT: 44111.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 44121.54Skamil sizeof(magic)) == 0); 44131.54Skamil break; 44141.54Skamil case BYTES_TRANSFER_TEXTIO: 44151.54Skamil switch (size) { 44161.54Skamil case 8: 44171.54Skamil FORKEE_ASSERT(memcmp(&magic8, 44181.54Skamil bytes_transfer_dummy, 44191.54Skamil sizeof(magic8)) == 0); 44201.54Skamil break; 44211.54Skamil case 16: 44221.54Skamil FORKEE_ASSERT(memcmp(&magic16, 44231.54Skamil bytes_transfer_dummy, 44241.54Skamil sizeof(magic16)) == 0); 44251.54Skamil break; 44261.54Skamil case 32: 44271.54Skamil FORKEE_ASSERT(memcmp(&magic32, 44281.54Skamil bytes_transfer_dummy, 44291.54Skamil sizeof(magic32)) == 0); 44301.54Skamil break; 44311.54Skamil case 64: 44321.54Skamil FORKEE_ASSERT(memcmp(&magic64, 44331.54Skamil bytes_transfer_dummy, 44341.54Skamil sizeof(magic64)) == 0); 44351.54Skamil break; 44361.54Skamil } 44371.54Skamil break; 44381.54Skamil default: 44391.54Skamil break; 44401.54Skamil } 44411.54Skamil 44421.13Schristos DPRINTF("Before exiting of the child process\n"); 44431.1Skamil _exit(exitval); 44441.1Skamil } 44451.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44461.1Skamil 44471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44491.1Skamil 44501.1Skamil validate_status_stopped(status, sigval); 44511.1Skamil 44521.54Skamil /* Check PaX MPROTECT */ 44531.54Skamil if (!can_we_write_to_text(child)) { 44541.54Skamil switch (type) { 44551.54Skamil case BYTES_TRANSFER_TEXTIO: 44561.54Skamil switch (operation) { 44571.54Skamil case PIOD_WRITE_D: 44581.54Skamil case PIOD_WRITE_I: 44591.54Skamil skip = true; 44601.54Skamil break; 44611.54Skamil default: 44621.54Skamil break; 44631.54Skamil } 44641.54Skamil break; 44651.54Skamil case BYTES_TRANSFER_TEXT: 44661.54Skamil switch (operation) { 44671.54Skamil case PT_WRITE_D: 44681.54Skamil case PT_WRITE_I: 44691.54Skamil skip = true; 44701.54Skamil break; 44711.54Skamil default: 44721.54Skamil break; 44731.54Skamil } 44741.54Skamil break; 44751.54Skamil default: 44761.54Skamil break; 44771.54Skamil } 44781.54Skamil } 44791.1Skamil 44801.54Skamil /* Bailout cleanly killing the child process */ 44811.54Skamil if (skip) { 44821.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 44831.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44841.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 44851.54Skamil child); 44861.1Skamil 44871.54Skamil validate_status_signaled(status, SIGKILL, 0); 44881.1Skamil 44891.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 44901.54Skamil } 44911.1Skamil 44921.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 44931.54Skamil "parent=%d\n", child, getpid()); 44941.1Skamil 44951.54Skamil switch (type) { 44961.54Skamil case BYTES_TRANSFER_TEXTIO: 44971.54Skamil case BYTES_TRANSFER_DATAIO: 44981.54Skamil case BYTES_TRANSFER_AUXV: 44991.54Skamil switch (operation) { 45001.54Skamil case PIOD_WRITE_D: 45011.54Skamil case PIOD_WRITE_I: 45021.54Skamil switch (size) { 45031.54Skamil case 8: 45041.54Skamil lookup_me8 = magic8; 45051.54Skamil break; 45061.54Skamil case 16: 45071.54Skamil lookup_me16 = magic16; 45081.54Skamil break; 45091.54Skamil case 32: 45101.54Skamil lookup_me32 = magic32; 45111.54Skamil break; 45121.54Skamil case 64: 45131.54Skamil lookup_me64 = magic64; 45141.54Skamil break; 45151.54Skamil default: 45161.54Skamil break; 45171.54Skamil } 45181.54Skamil break; 45191.54Skamil default: 45201.54Skamil break; 45211.54Skamil } 45221.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 45231.54Skamil switch (operation) { 45241.54Skamil case PIOD_READ_D: 45251.54Skamil case PIOD_READ_I: 45261.54Skamil switch (size) { 45271.54Skamil case 8: 45281.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 45291.54Skamil break; 45301.54Skamil case 16: 45311.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 45321.54Skamil break; 45331.54Skamil case 32: 45341.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 45351.54Skamil break; 45361.54Skamil case 64: 45371.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 45381.54Skamil break; 45391.54Skamil default: 45401.54Skamil break; 45411.54Skamil } 45421.54Skamil break; 45431.54Skamil case PIOD_READ_AUXV: 45441.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 45451.54Skamil io.piod_len); 45461.54Skamil ATF_REQUIRE(io.piod_len > 0); 45471.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 45481.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 45491.54Skamil (long long int)aip->a_type, 45501.54Skamil (long long int)aip->a_v); 45511.54Skamil break; 45521.54Skamil default: 45531.54Skamil break; 45541.54Skamil } 45551.54Skamil break; 45561.54Skamil case BYTES_TRANSFER_TEXT: 45571.54Skamil switch (operation) { 45581.54Skamil case PT_READ_D: 45591.54Skamil case PT_READ_I: 45601.54Skamil errno = 0; 45611.54Skamil lookup_me = ptrace(operation, child, 45621.54Skamil bytes_transfer_dummy, 0); 45631.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 45641.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 45651.54Skamil break; 45661.54Skamil case PT_WRITE_D: 45671.54Skamil case PT_WRITE_I: 45681.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 45691.54Skamil bytes_transfer_dummy, magic) 45701.54Skamil != -1); 45711.54Skamil break; 45721.54Skamil default: 45731.54Skamil break; 45741.54Skamil } 45751.54Skamil break; 45761.54Skamil case BYTES_TRANSFER_DATA: 45771.54Skamil switch (operation) { 45781.54Skamil case PT_READ_D: 45791.54Skamil case PT_READ_I: 45801.54Skamil errno = 0; 45811.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 45821.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 45831.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 45841.54Skamil break; 45851.54Skamil case PT_WRITE_D: 45861.54Skamil case PT_WRITE_I: 45871.54Skamil lookup_me = magic; 45881.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 45891.54Skamil magic) != -1); 45901.54Skamil break; 45911.54Skamil default: 45921.54Skamil break; 45931.54Skamil } 45941.54Skamil break; 45951.54Skamil default: 45961.54Skamil break; 45971.54Skamil } 45981.1Skamil 45991.13Schristos DPRINTF("Before resuming the child process where it left off and " 46001.1Skamil "without signal to be sent\n"); 46011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46021.1Skamil 46031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46051.1Skamil 46061.1Skamil validate_status_exited(status, exitval); 46071.1Skamil 46081.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46091.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46101.1Skamil} 46111.1Skamil 46121.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 46131.61SkreATF_TC(test); \ 46141.61SkreATF_TC_HEAD(test, tc) \ 46151.61Skre{ \ 46161.61Skre atf_tc_set_md_var(tc, "descr", \ 46171.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 46181.61Skre " of type " #type); \ 46191.61Skre} \ 46201.61Skre \ 46211.61SkreATF_TC_BODY(test, tc) \ 46221.61Skre{ \ 46231.61Skre \ 46241.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 46251.1Skamil} 46261.1Skamil 46271.54Skamil// DATA 46281.1Skamil 46291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 46301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 46311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 46321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 46331.54Skamil 46341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 46351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 46361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 46371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 46381.54Skamil 46391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 46401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 46411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 46421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 46431.54Skamil 46441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 46451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 46461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 46471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 46481.54Skamil 46491.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 46501.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 46511.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 46521.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 46531.54Skamil 46541.54Skamil// TEXT 46551.54Skamil 46561.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 46571.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 46581.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 46591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 46601.54Skamil 46611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 46621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 46631.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 46641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 46651.54Skamil 46661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 46671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 46681.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 46691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 46701.54Skamil 46711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 46721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 46731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 46741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 46751.54Skamil 46761.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 46771.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 46781.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 46791.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 46801.1Skamil 46811.54Skamil// AUXV 46821.1Skamil 46831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 46841.1Skamil 46851.54Skamil/// ---------------------------------------------------------------------------- 46861.1Skamil 46871.101Skamilstatic void 46881.101Skamilbytes_transfer_alignment(const char *operation) 46891.101Skamil{ 46901.101Skamil const int exitval = 5; 46911.101Skamil const int sigval = SIGSTOP; 46921.101Skamil pid_t child, wpid; 46931.101Skamil#if defined(TWAIT_HAVE_STATUS) 46941.101Skamil int status; 46951.101Skamil#endif 46961.101Skamil char *buffer; 46971.101Skamil int vector; 46981.101Skamil size_t len; 46991.101Skamil size_t i; 47001.101Skamil int op; 47011.101Skamil 47021.101Skamil struct ptrace_io_desc io; 47031.101Skamil struct ptrace_siginfo info; 47041.101Skamil 47051.101Skamil memset(&io, 0, sizeof(io)); 47061.101Skamil memset(&info, 0, sizeof(info)); 47071.101Skamil 47081.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 47091.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 47101.101Skamil buffer = malloc(len); 47111.101Skamil ATF_REQUIRE(buffer != NULL); 47121.101Skamil 47131.101Skamil /* Initialize the buffer with random data */ 47141.101Skamil for (i = 0; i < len; i++) 47151.101Skamil buffer[i] = i & 0xff; 47161.101Skamil 47171.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 47181.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 47191.101Skamil if (child == 0) { 47201.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47211.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47221.101Skamil 47231.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47241.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 47251.101Skamil 47261.101Skamil DPRINTF("Before exiting of the child process\n"); 47271.101Skamil _exit(exitval); 47281.101Skamil } 47291.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47301.101Skamil 47311.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47321.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47331.101Skamil 47341.101Skamil validate_status_stopped(status, sigval); 47351.101Skamil 47361.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 47371.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 47381.101Skamil != -1); 47391.101Skamil 47401.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47411.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 47421.101Skamil "si_errno=%#x\n", 47431.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47441.101Skamil info.psi_siginfo.si_errno); 47451.101Skamil 47461.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 47471.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 47481.101Skamil 47491.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 47501.101Skamil strcmp(operation, "PT_READ_D") == 0) { 47511.101Skamil if (strcmp(operation, "PT_READ_I")) 47521.101Skamil op = PT_READ_I; 47531.101Skamil else 47541.101Skamil op = PT_READ_D; 47551.101Skamil 47561.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 47571.101Skamil errno = 0; 47581.101Skamil vector = ptrace(op, child, buffer + i, 0); 47591.101Skamil ATF_REQUIRE_EQ(errno, 0); 47601.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 47611.101Skamil } 47621.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 47631.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 47641.101Skamil if (strcmp(operation, "PT_WRITE_I")) 47651.101Skamil op = PT_WRITE_I; 47661.101Skamil else 47671.101Skamil op = PT_WRITE_D; 47681.101Skamil 47691.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 47701.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 47711.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 47721.101Skamil != -1); 47731.101Skamil } 47741.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 47751.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 47761.101Skamil if (strcmp(operation, "PIOD_READ_I")) 47771.101Skamil op = PIOD_READ_I; 47781.101Skamil else 47791.101Skamil op = PIOD_READ_D; 47801.101Skamil 47811.101Skamil io.piod_op = op; 47821.101Skamil io.piod_addr = &vector; 47831.101Skamil io.piod_len = sizeof(int); 47841.101Skamil 47851.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 47861.101Skamil io.piod_offs = buffer + i; 47871.101Skamil 47881.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 47891.101Skamil != -1); 47901.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 47911.101Skamil } 47921.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 47931.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 47941.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 47951.101Skamil op = PIOD_WRITE_I; 47961.101Skamil else 47971.101Skamil op = PIOD_WRITE_D; 47981.101Skamil 47991.101Skamil io.piod_op = op; 48001.101Skamil io.piod_addr = &vector; 48011.101Skamil io.piod_len = sizeof(int); 48021.101Skamil 48031.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 48041.101Skamil io.piod_offs = buffer + i; 48051.101Skamil 48061.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 48071.101Skamil != -1); 48081.101Skamil } 48091.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 48101.101Skamil io.piod_op = PIOD_READ_AUXV; 48111.101Skamil io.piod_addr = &vector; 48121.101Skamil io.piod_len = sizeof(int); 48131.101Skamil 48141.101Skamil errno = 0; 48151.101Skamil i = 0; 48161.101Skamil /* Read the whole AUXV vector, it has no clear length */ 48171.120Skamil while (io.piod_len > 0) { 48181.101Skamil io.piod_offs = (void *)(intptr_t)i; 48191.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 48201.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 48211.101Skamil ++i; 48221.101Skamil } 48231.101Skamil } 48241.101Skamil 48251.101Skamil DPRINTF("Before resuming the child process where it left off " 48261.101Skamil "and without signal to be sent\n"); 48271.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48281.101Skamil 48291.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48301.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 48311.101Skamil child); 48321.101Skamil 48331.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48341.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48351.101Skamil} 48361.101Skamil 48371.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 48381.101SkamilATF_TC(test); \ 48391.101SkamilATF_TC_HEAD(test, tc) \ 48401.101Skamil{ \ 48411.101Skamil atf_tc_set_md_var(tc, "descr", \ 48421.101Skamil "Verify bytes transfer for potentially misaligned " \ 48431.101Skamil "operation " operation); \ 48441.101Skamil} \ 48451.101Skamil \ 48461.101SkamilATF_TC_BODY(test, tc) \ 48471.101Skamil{ \ 48481.101Skamil \ 48491.101Skamil bytes_transfer_alignment(operation); \ 48501.101Skamil} 48511.101Skamil 48521.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 48531.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 48541.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 48551.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 48561.101Skamil 48571.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 48581.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 48591.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 48601.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 48611.101Skamil 48621.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 48631.101Skamil 48641.101Skamil/// ---------------------------------------------------------------------------- 48651.101Skamil 48661.115Skamilstatic void 48671.115Skamilbytes_transfer_eof(const char *operation) 48681.115Skamil{ 48691.115Skamil const int exitval = 5; 48701.115Skamil const int sigval = SIGSTOP; 48711.115Skamil pid_t child, wpid; 48721.115Skamil#if defined(TWAIT_HAVE_STATUS) 48731.115Skamil int status; 48741.115Skamil#endif 48751.115Skamil FILE *fp; 48761.115Skamil char *p; 48771.115Skamil int vector; 48781.115Skamil int op; 48791.115Skamil 48801.115Skamil struct ptrace_io_desc io; 48811.115Skamil struct ptrace_siginfo info; 48821.115Skamil 48831.115Skamil memset(&io, 0, sizeof(io)); 48841.115Skamil memset(&info, 0, sizeof(info)); 48851.115Skamil 48861.115Skamil vector = 0; 48871.115Skamil 48881.115Skamil fp = tmpfile(); 48891.115Skamil ATF_REQUIRE(fp != NULL); 48901.115Skamil 48911.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 48921.115Skamil ATF_REQUIRE(p != MAP_FAILED); 48931.115Skamil 48941.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 48951.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 48961.115Skamil if (child == 0) { 48971.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48981.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48991.115Skamil 49001.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49011.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 49021.115Skamil 49031.115Skamil DPRINTF("Before exiting of the child process\n"); 49041.115Skamil _exit(exitval); 49051.115Skamil } 49061.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 49071.115Skamil 49081.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49091.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49101.115Skamil 49111.115Skamil validate_status_stopped(status, sigval); 49121.115Skamil 49131.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 49141.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 49151.115Skamil != -1); 49161.115Skamil 49171.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49181.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49191.115Skamil "si_errno=%#x\n", 49201.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49211.115Skamil info.psi_siginfo.si_errno); 49221.115Skamil 49231.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 49241.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 49251.115Skamil 49261.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 49271.115Skamil strcmp(operation, "PT_READ_D") == 0) { 49281.115Skamil if (strcmp(operation, "PT_READ_I")) 49291.115Skamil op = PT_READ_I; 49301.115Skamil else 49311.115Skamil op = PT_READ_D; 49321.115Skamil 49331.115Skamil errno = 0; 49341.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 49351.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49361.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 49371.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 49381.115Skamil if (strcmp(operation, "PT_WRITE_I")) 49391.115Skamil op = PT_WRITE_I; 49401.115Skamil else 49411.115Skamil op = PT_WRITE_D; 49421.115Skamil 49431.115Skamil errno = 0; 49441.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 49451.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49461.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 49471.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 49481.115Skamil if (strcmp(operation, "PIOD_READ_I")) 49491.115Skamil op = PIOD_READ_I; 49501.115Skamil else 49511.115Skamil op = PIOD_READ_D; 49521.115Skamil 49531.115Skamil io.piod_op = op; 49541.115Skamil io.piod_addr = &vector; 49551.115Skamil io.piod_len = sizeof(int); 49561.115Skamil io.piod_offs = p; 49571.115Skamil 49581.115Skamil errno = 0; 49591.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 49601.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49611.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 49621.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 49631.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 49641.115Skamil op = PIOD_WRITE_I; 49651.115Skamil else 49661.115Skamil op = PIOD_WRITE_D; 49671.115Skamil 49681.115Skamil io.piod_op = op; 49691.115Skamil io.piod_addr = &vector; 49701.115Skamil io.piod_len = sizeof(int); 49711.115Skamil io.piod_offs = p; 49721.115Skamil 49731.115Skamil errno = 0; 49741.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 49751.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 49761.115Skamil } 49771.115Skamil 49781.115Skamil DPRINTF("Before resuming the child process where it left off " 49791.115Skamil "and without signal to be sent\n"); 49801.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 49811.115Skamil 49821.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49831.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 49841.115Skamil child); 49851.115Skamil 49861.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49871.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49881.115Skamil} 49891.115Skamil 49901.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 49911.115SkamilATF_TC(test); \ 49921.115SkamilATF_TC_HEAD(test, tc) \ 49931.115Skamil{ \ 49941.115Skamil atf_tc_set_md_var(tc, "descr", \ 49951.115Skamil "Verify bytes EOF byte transfer for the " operation \ 49961.115Skamil " operation"); \ 49971.115Skamil} \ 49981.115Skamil \ 49991.115SkamilATF_TC_BODY(test, tc) \ 50001.115Skamil{ \ 50011.115Skamil \ 50021.115Skamil bytes_transfer_eof(operation); \ 50031.115Skamil} 50041.115Skamil 50051.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 50061.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 50071.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 50081.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 50091.115Skamil 50101.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 50111.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 50121.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 50131.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 50141.115Skamil 50151.115Skamil/// ---------------------------------------------------------------------------- 50161.115Skamil 50171.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 50181.72Skamilstatic void 50191.72Skamilaccess_regs(const char *regset, const char *aux) 50201.1Skamil{ 50211.1Skamil const int exitval = 5; 50221.1Skamil const int sigval = SIGSTOP; 50231.1Skamil pid_t child, wpid; 50241.1Skamil#if defined(TWAIT_HAVE_STATUS) 50251.1Skamil int status; 50261.1Skamil#endif 50271.72Skamil#if defined(HAVE_GPREGS) 50281.72Skamil struct reg gpr; 50291.76Sscole register_t rgstr; 50301.1Skamil#endif 50311.72Skamil#if defined(HAVE_FPREGS) 50321.72Skamil struct fpreg fpr; 50331.1Skamil#endif 50341.76Sscole 50351.72Skamil#if !defined(HAVE_GPREGS) 50361.72Skamil if (strcmp(regset, "regs") == 0) 50371.72Skamil atf_tc_fail("Impossible test scenario!"); 50381.1Skamil#endif 50391.1Skamil 50401.72Skamil#if !defined(HAVE_FPREGS) 50411.72Skamil if (strcmp(regset, "fpregs") == 0) 50421.72Skamil atf_tc_fail("Impossible test scenario!"); 50431.1Skamil#endif 50441.1Skamil 50451.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 50461.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 50471.1Skamil if (child == 0) { 50481.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 50491.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 50501.1Skamil 50511.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 50521.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 50531.1Skamil 50541.13Schristos DPRINTF("Before exiting of the child process\n"); 50551.1Skamil _exit(exitval); 50561.1Skamil } 50571.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 50581.1Skamil 50591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50611.1Skamil 50621.1Skamil validate_status_stopped(status, sigval); 50631.1Skamil 50641.1Skamil#if defined(HAVE_GPREGS) 50651.72Skamil if (strcmp(regset, "regs") == 0) { 50661.72Skamil DPRINTF("Call GETREGS for the child process\n"); 50671.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 50681.72Skamil 50691.72Skamil if (strcmp(aux, "none") == 0) { 50701.72Skamil DPRINTF("Retrieved registers\n"); 50711.72Skamil } else if (strcmp(aux, "pc") == 0) { 50721.72Skamil rgstr = PTRACE_REG_PC(&gpr); 50731.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 50741.147Skamil } else if (strstr(aux, "set_pc") != NULL) { 50751.72Skamil rgstr = PTRACE_REG_PC(&gpr); 50761.147Skamil DPRINTF("Retrieved PC %" PRIxREGISTER "\n", rgstr); 50771.147Skamil if (strstr(aux, "0x1") != NULL) { 50781.147Skamil rgstr |= 0x1; 50791.147Skamil } else if (strstr(aux, "0x3") != NULL) { 50801.147Skamil rgstr |= 0x3; 50811.147Skamil } else if (strstr(aux, "0x7") != NULL) { 50821.147Skamil rgstr |= 0x7; 50831.147Skamil } 50841.147Skamil DPRINTF("Set PC %" PRIxREGISTER "\n", rgstr); 50851.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 50861.147Skamil if (strcmp(aux, "set_pc") != 0) { 50871.147Skamil /* This call can fail with EINVAL or similar. */ 50881.147Skamil ptrace(PT_SETREGS, child, &gpr, 0); 50891.147Skamil } 50901.72Skamil } else if (strcmp(aux, "sp") == 0) { 50911.72Skamil rgstr = PTRACE_REG_SP(&gpr); 50921.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 50931.72Skamil } else if (strcmp(aux, "intrv") == 0) { 50941.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 50951.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 50961.72Skamil } else if (strcmp(aux, "setregs") == 0) { 50971.72Skamil DPRINTF("Call SETREGS for the child process\n"); 50981.72Skamil SYSCALL_REQUIRE( 50991.147Skamil ptrace(PT_SETREGS, child, &gpr, 0) != -1); 51001.72Skamil } 51011.72Skamil } 51021.1Skamil#endif 51031.1Skamil 51041.72Skamil#if defined(HAVE_FPREGS) 51051.72Skamil if (strcmp(regset, "fpregs") == 0) { 51061.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 51071.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 51081.72Skamil 51091.72Skamil if (strcmp(aux, "getfpregs") == 0) { 51101.72Skamil DPRINTF("Retrieved FP registers\n"); 51111.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 51121.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 51131.72Skamil SYSCALL_REQUIRE( 51141.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 51151.72Skamil } 51161.1Skamil } 51171.1Skamil#endif 51181.1Skamil 51191.13Schristos DPRINTF("Before resuming the child process where it left off and " 51201.1Skamil "without signal to be sent\n"); 51211.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 51221.1Skamil 51231.147Skamil if (strstr(aux, "unaligned") != NULL) { 51241.147Skamil DPRINTF("Before resuming the child process where it left off " 51251.147Skamil "and without signal to be sent\n"); 51261.147Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 51271.147Skamil 51281.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51291.147Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 51301.147Skamil child); 51311.147Skamil 51321.147Skamil validate_status_signaled(status, SIGKILL, 0); 51331.147Skamil 51341.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51351.147Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 51361.147Skamil wpid = TWAIT_GENERIC(child, &status, 0)); 51371.147Skamil } else { 51381.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51391.147Skamil TWAIT_REQUIRE_SUCCESS( 51401.147Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 51411.1Skamil 51421.147Skamil validate_status_exited(status, exitval); 51431.1Skamil 51441.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51451.147Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 51461.147Skamil wpid = TWAIT_GENERIC(child, &status, 0)); 51471.147Skamil } 51481.1Skamil} 51491.1Skamil 51501.72Skamil#define ACCESS_REGS(test, regset, aux) \ 51511.72SkamilATF_TC(test); \ 51521.72SkamilATF_TC_HEAD(test, tc) \ 51531.72Skamil{ \ 51541.72Skamil atf_tc_set_md_var(tc, "descr", \ 51551.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 51561.72Skamil} \ 51571.72Skamil \ 51581.72SkamilATF_TC_BODY(test, tc) \ 51591.72Skamil{ \ 51601.72Skamil \ 51611.72Skamil access_regs(regset, aux); \ 51621.1Skamil} 51631.1Skamil#endif 51641.1Skamil 51651.72Skamil#if defined(HAVE_GPREGS) 51661.72SkamilACCESS_REGS(access_regs1, "regs", "none") 51671.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 51681.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 51691.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 51701.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 51711.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 51721.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x1, "regs", "set_pc+unaligned+0x1") 51731.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x3, "regs", "set_pc+unaligned+0x3") 51741.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x7, "regs", "set_pc+unaligned+0x7") 51751.1Skamil#endif 51761.1Skamil#if defined(HAVE_FPREGS) 51771.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 51781.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 51791.1Skamil#endif 51801.1Skamil 51811.72Skamil/// ---------------------------------------------------------------------------- 51821.1Skamil 51831.1Skamil#if defined(PT_STEP) 51841.1Skamilstatic void 51851.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 51861.1Skamil{ 51871.1Skamil const int exitval = 5; 51881.1Skamil const int sigval = SIGSTOP; 51891.1Skamil pid_t child, wpid; 51901.1Skamil#if defined(TWAIT_HAVE_STATUS) 51911.1Skamil int status; 51921.1Skamil#endif 51931.1Skamil int happy; 51941.95Skamil struct sigaction sa; 51951.81Skamil struct ptrace_siginfo info; 51961.95Skamil sigset_t intmask; 51971.95Skamil struct kinfo_proc2 kp; 51981.95Skamil size_t len = sizeof(kp); 51991.95Skamil 52001.95Skamil int name[6]; 52011.95Skamil const size_t namelen = __arraycount(name); 52021.95Skamil ki_sigset_t kp_sigmask; 52031.95Skamil ki_sigset_t kp_sigignore; 52041.1Skamil 52051.1Skamil#if defined(__arm__) 52061.1Skamil /* PT_STEP not supported on arm 32-bit */ 52071.1Skamil atf_tc_expect_fail("PR kern/52119"); 52081.1Skamil#endif 52091.1Skamil 52101.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52111.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52121.1Skamil if (child == 0) { 52131.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 52141.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 52151.1Skamil 52161.95Skamil if (masked) { 52171.95Skamil sigemptyset(&intmask); 52181.95Skamil sigaddset(&intmask, SIGTRAP); 52191.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 52201.95Skamil } 52211.95Skamil 52221.95Skamil if (ignored) { 52231.95Skamil memset(&sa, 0, sizeof(sa)); 52241.95Skamil sa.sa_handler = SIG_IGN; 52251.95Skamil sigemptyset(&sa.sa_mask); 52261.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 52271.95Skamil } 52281.95Skamil 52291.1Skamil happy = check_happy(999); 52301.1Skamil 52311.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 52321.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 52331.1Skamil 52341.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 52351.1Skamil 52361.13Schristos DPRINTF("Before exiting of the child process\n"); 52371.1Skamil _exit(exitval); 52381.1Skamil } 52391.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52401.1Skamil 52411.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52431.1Skamil 52441.1Skamil validate_status_stopped(status, sigval); 52451.1Skamil 52461.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52471.81Skamil SYSCALL_REQUIRE( 52481.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52491.81Skamil 52501.81Skamil DPRINTF("Before checking siginfo_t\n"); 52511.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 52521.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 52531.81Skamil 52541.95Skamil name[0] = CTL_KERN, 52551.95Skamil name[1] = KERN_PROC2, 52561.95Skamil name[2] = KERN_PROC_PID; 52571.95Skamil name[3] = child; 52581.95Skamil name[4] = sizeof(kp); 52591.95Skamil name[5] = 1; 52601.95Skamil 52611.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52621.95Skamil 52631.95Skamil if (masked) 52641.95Skamil kp_sigmask = kp.p_sigmask; 52651.95Skamil 52661.95Skamil if (ignored) 52671.95Skamil kp_sigignore = kp.p_sigignore; 52681.95Skamil 52691.1Skamil while (N --> 0) { 52701.2Skamil if (setstep) { 52711.13Schristos DPRINTF("Before resuming the child process where it " 52721.2Skamil "left off and without signal to be sent (use " 52731.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 52741.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 52751.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 52761.2Skamil != -1); 52771.2Skamil } else { 52781.13Schristos DPRINTF("Before resuming the child process where it " 52791.2Skamil "left off and without signal to be sent (use " 52801.2Skamil "PT_STEP)\n"); 52811.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 52821.2Skamil != -1); 52831.2Skamil } 52841.1Skamil 52851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 52871.1Skamil child); 52881.1Skamil 52891.1Skamil validate_status_stopped(status, SIGTRAP); 52901.2Skamil 52911.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52921.81Skamil SYSCALL_REQUIRE( 52931.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52941.81Skamil 52951.81Skamil DPRINTF("Before checking siginfo_t\n"); 52961.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 52971.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 52981.81Skamil 52991.2Skamil if (setstep) { 53001.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 53011.2Skamil } 53021.95Skamil 53031.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53041.95Skamil 53051.95Skamil if (masked) { 53061.95Skamil DPRINTF("kp_sigmask=" 53071.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53081.95Skamil PRIx32 "\n", 53091.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53101.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53111.95Skamil 53121.95Skamil DPRINTF("kp.p_sigmask=" 53131.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53141.95Skamil PRIx32 "\n", 53151.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53161.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53171.95Skamil 53181.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53191.95Skamil sizeof(kp_sigmask))); 53201.95Skamil } 53211.95Skamil 53221.95Skamil if (ignored) { 53231.95Skamil DPRINTF("kp_sigignore=" 53241.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53251.95Skamil PRIx32 "\n", 53261.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53271.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53281.95Skamil 53291.95Skamil DPRINTF("kp.p_sigignore=" 53301.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 53311.95Skamil PRIx32 "\n", 53321.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53331.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53341.95Skamil 53351.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53361.95Skamil sizeof(kp_sigignore))); 53371.95Skamil } 53381.1Skamil } 53391.1Skamil 53401.13Schristos DPRINTF("Before resuming the child process where it left off and " 53411.1Skamil "without signal to be sent\n"); 53421.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53431.1Skamil 53441.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53451.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53461.1Skamil 53471.1Skamil validate_status_exited(status, exitval); 53481.1Skamil 53491.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53501.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53511.1Skamil} 53521.1Skamil 53531.73Skamil#define PTRACE_STEP(test, N, setstep) \ 53541.73SkamilATF_TC(test); \ 53551.73SkamilATF_TC_HEAD(test, tc) \ 53561.73Skamil{ \ 53571.73Skamil atf_tc_set_md_var(tc, "descr", \ 53581.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 53591.73Skamil} \ 53601.73Skamil \ 53611.73SkamilATF_TC_BODY(test, tc) \ 53621.73Skamil{ \ 53631.73Skamil \ 53641.95Skamil ptrace_step(N, setstep, false, false); \ 53651.1Skamil} 53661.1Skamil 53671.73SkamilPTRACE_STEP(step1, 1, 0) 53681.73SkamilPTRACE_STEP(step2, 2, 0) 53691.73SkamilPTRACE_STEP(step3, 3, 0) 53701.73SkamilPTRACE_STEP(step4, 4, 0) 53711.73SkamilPTRACE_STEP(setstep1, 1, 1) 53721.73SkamilPTRACE_STEP(setstep2, 2, 1) 53731.73SkamilPTRACE_STEP(setstep3, 3, 1) 53741.73SkamilPTRACE_STEP(setstep4, 4, 1) 53751.95Skamil 53761.95SkamilATF_TC(step_signalmasked); 53771.95SkamilATF_TC_HEAD(step_signalmasked, tc) 53781.95Skamil{ 53791.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 53801.95Skamil} 53811.95Skamil 53821.95SkamilATF_TC_BODY(step_signalmasked, tc) 53831.95Skamil{ 53841.95Skamil 53851.95Skamil ptrace_step(1, 0, true, false); 53861.95Skamil} 53871.95Skamil 53881.95SkamilATF_TC(step_signalignored); 53891.95SkamilATF_TC_HEAD(step_signalignored, tc) 53901.95Skamil{ 53911.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 53921.95Skamil} 53931.95Skamil 53941.95SkamilATF_TC_BODY(step_signalignored, tc) 53951.95Skamil{ 53961.95Skamil 53971.95Skamil ptrace_step(1, 0, false, true); 53981.95Skamil} 53991.1Skamil#endif 54001.1Skamil 54011.73Skamil/// ---------------------------------------------------------------------------- 54021.1Skamil 54031.75Skamilstatic void 54041.75Skamilptrace_kill(const char *type) 54051.1Skamil{ 54061.75Skamil const int sigval = SIGSTOP; 54071.1Skamil pid_t child, wpid; 54081.1Skamil#if defined(TWAIT_HAVE_STATUS) 54091.1Skamil int status; 54101.1Skamil#endif 54111.1Skamil 54121.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54131.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54141.1Skamil if (child == 0) { 54151.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54161.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54171.1Skamil 54181.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54191.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54201.1Skamil 54211.1Skamil /* NOTREACHED */ 54221.1Skamil FORKEE_ASSERTX(0 && 54231.1Skamil "Child should be terminated by a signal from its parent"); 54241.1Skamil } 54251.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54261.1Skamil 54271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54291.1Skamil 54301.1Skamil validate_status_stopped(status, sigval); 54311.1Skamil 54321.75Skamil DPRINTF("Before killing the child process with %s\n", type); 54331.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 54341.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 54351.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 54361.75Skamil kill(child, SIGKILL); 54371.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 54381.75Skamil setpgid(child, 0); 54391.75Skamil killpg(getpgid(child), SIGKILL); 54401.75Skamil } 54411.1Skamil 54421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54441.1Skamil 54451.75Skamil validate_status_signaled(status, SIGKILL, 0); 54461.1Skamil 54471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54481.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54491.1Skamil} 54501.1Skamil 54511.75Skamil#define PTRACE_KILL(test, type) \ 54521.75SkamilATF_TC(test); \ 54531.75SkamilATF_TC_HEAD(test, tc) \ 54541.75Skamil{ \ 54551.75Skamil atf_tc_set_md_var(tc, "descr", \ 54561.75Skamil "Verify killing the child with " type); \ 54571.75Skamil} \ 54581.75Skamil \ 54591.75SkamilATF_TC_BODY(test, tc) \ 54601.75Skamil{ \ 54611.75Skamil \ 54621.75Skamil ptrace_kill(type); \ 54631.1Skamil} 54641.1Skamil 54651.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 54661.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 54671.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 54681.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 54691.1Skamil 54701.75Skamil/// ---------------------------------------------------------------------------- 54711.1Skamil 54721.143Skamilstatic int lwpinfo_thread_sigmask[] = {SIGXCPU, SIGPIPE, SIGALRM, SIGURG}; 54731.143Skamil 54741.143Skamilstatic pthread_mutex_t lwpinfo_thread_mtx = PTHREAD_MUTEX_INITIALIZER; 54751.143Skamilstatic pthread_cond_t lwpinfo_thread_cnd = PTHREAD_COND_INITIALIZER; 54761.143Skamilstatic volatile size_t lwpinfo_thread_done; 54771.143Skamil 54781.143Skamilstatic void * 54791.143Skamillwpinfo_thread(void *arg) 54801.143Skamil{ 54811.143Skamil sigset_t s; 54821.143Skamil volatile void **tcb; 54831.143Skamil 54841.143Skamil tcb = (volatile void **)arg; 54851.143Skamil 54861.145Skamil *tcb = _lwp_getprivate(); 54871.143Skamil DPRINTF("Storing tcb[] = %p from thread %d\n", *tcb, _lwp_self()); 54881.143Skamil 54891.143Skamil pthread_setname_np(pthread_self(), "thread %d", 54901.143Skamil (void *)(intptr_t)_lwp_self()); 54911.143Skamil 54921.143Skamil sigemptyset(&s); 54931.143Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 54941.143Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 54951.143Skamil lwpinfo_thread_done++; 54961.143Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 54971.143Skamil pthread_cond_signal(&lwpinfo_thread_cnd); 54981.143Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 54991.143Skamil 55001.143Skamil return infinite_thread(NULL); 55011.143Skamil} 55021.143Skamil 55031.77Skamilstatic void 55041.143Skamiltraceme_lwpinfo(const size_t threads, const char *iter) 55051.1Skamil{ 55061.1Skamil const int sigval = SIGSTOP; 55071.77Skamil const int sigval2 = SIGINT; 55081.1Skamil pid_t child, wpid; 55091.1Skamil#if defined(TWAIT_HAVE_STATUS) 55101.1Skamil int status; 55111.1Skamil#endif 55121.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 55131.143Skamil struct ptrace_lwpstatus lwpstatus = {0}; 55141.77Skamil struct ptrace_siginfo info; 55151.143Skamil void *private; 55161.143Skamil char *name; 55171.143Skamil char namebuf[PL_LNAMELEN]; 55181.143Skamil volatile void *tcb[4]; 55191.143Skamil bool found; 55201.143Skamil sigset_t s; 55211.77Skamil 55221.77Skamil /* Maximum number of supported threads in this test */ 55231.143Skamil pthread_t t[__arraycount(tcb) - 1]; 55241.143Skamil size_t n, m; 55251.143Skamil int rv; 55261.143Skamil size_t bytes_read; 55271.143Skamil 55281.143Skamil struct ptrace_io_desc io; 55291.143Skamil sigset_t sigmask; 55301.77Skamil 55311.143Skamil ATF_REQUIRE(__arraycount(t) >= threads); 55321.143Skamil memset(tcb, 0, sizeof(tcb)); 55331.1Skamil 55341.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 55351.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 55361.1Skamil if (child == 0) { 55371.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 55381.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55391.1Skamil 55401.145Skamil tcb[0] = _lwp_getprivate(); 55411.143Skamil DPRINTF("Storing tcb[0] = %p\n", tcb[0]); 55421.143Skamil 55431.143Skamil pthread_setname_np(pthread_self(), "thread %d", 55441.143Skamil (void *)(intptr_t)_lwp_self()); 55451.143Skamil 55461.143Skamil sigemptyset(&s); 55471.143Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 55481.143Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 55491.143Skamil 55501.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 55511.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 55521.1Skamil 55531.77Skamil for (n = 0; n < threads; n++) { 55541.143Skamil rv = pthread_create(&t[n], NULL, lwpinfo_thread, 55551.143Skamil &tcb[n + 1]); 55561.77Skamil FORKEE_ASSERT(rv == 0); 55571.77Skamil } 55581.77Skamil 55591.143Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 55601.143Skamil while (lwpinfo_thread_done < threads) { 55611.143Skamil pthread_cond_wait(&lwpinfo_thread_cnd, 55621.143Skamil &lwpinfo_thread_mtx); 55631.143Skamil } 55641.143Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 55651.143Skamil 55661.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 55671.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 55681.77Skamil 55691.77Skamil /* NOTREACHED */ 55701.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 55711.1Skamil } 55721.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55731.1Skamil 55741.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55751.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55761.1Skamil 55771.1Skamil validate_status_stopped(status, sigval); 55781.1Skamil 55791.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 55801.77Skamil SYSCALL_REQUIRE( 55811.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55821.77Skamil 55831.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55841.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55851.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55861.77Skamil info.psi_siginfo.si_errno); 55871.77Skamil 55881.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55891.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55901.77Skamil 55911.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 55921.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 55931.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 55941.143Skamil != -1); 55951.1Skamil 55961.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 55971.143Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 55981.1Skamil 55991.143Skamil DPRINTF("Assert that lwp thread %d received event " 56001.143Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 56011.143Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 56021.143Skamil 56031.143Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 56041.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPSTATUS " 56051.143Skamil "for child\n"); 56061.143Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 56071.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, &lwpstatus, 56081.143Skamil sizeof(lwpstatus)) != -1); 56091.143Skamil } 56101.1Skamil 56111.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 56121.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 56131.143Skamil != -1); 56141.1Skamil 56151.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 56161.143Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 56171.143Skamil } else { 56181.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 56191.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 56201.143Skamil sizeof(lwpstatus)) != -1); 56211.143Skamil 56221.143Skamil DPRINTF("Assert that there exists a single thread only %d\n", lwpstatus.pl_lwpid); 56231.143Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 56241.143Skamil 56251.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 56261.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 56271.143Skamil sizeof(lwpstatus)) != -1); 56281.143Skamil 56291.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 56301.143Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 56311.143Skamil } 56321.1Skamil 56331.13Schristos DPRINTF("Before resuming the child process where it left off and " 56341.1Skamil "without signal to be sent\n"); 56351.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56361.1Skamil 56371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56391.1Skamil 56401.77Skamil validate_status_stopped(status, sigval2); 56411.77Skamil 56421.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 56431.77Skamil SYSCALL_REQUIRE( 56441.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56451.77Skamil 56461.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 56471.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 56481.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 56491.77Skamil info.psi_siginfo.si_errno); 56501.77Skamil 56511.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 56521.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 56531.77Skamil 56541.77Skamil memset(&lwp, 0, sizeof(lwp)); 56551.143Skamil memset(&lwpstatus, 0, sizeof(lwpstatus)); 56561.143Skamil 56571.143Skamil memset(&io, 0, sizeof(io)); 56581.143Skamil 56591.143Skamil bytes_read = 0; 56601.143Skamil io.piod_op = PIOD_READ_D; 56611.143Skamil io.piod_len = sizeof(tcb); 56621.143Skamil 56631.143Skamil do { 56641.143Skamil io.piod_addr = (char *)&tcb + bytes_read; 56651.143Skamil io.piod_offs = io.piod_addr; 56661.143Skamil 56671.143Skamil rv = ptrace(PT_IO, child, &io, sizeof(io)); 56681.143Skamil ATF_REQUIRE(rv != -1 && io.piod_len != 0); 56691.143Skamil 56701.143Skamil bytes_read += io.piod_len; 56711.143Skamil io.piod_len = sizeof(tcb) - bytes_read; 56721.143Skamil } while (bytes_read < sizeof(tcb)); 56731.77Skamil 56741.77Skamil for (n = 0; n <= threads; n++) { 56751.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 56761.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 56771.143Skamil "child\n"); 56781.143Skamil SYSCALL_REQUIRE( 56791.143Skamil ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 56801.143Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 56811.143Skamil 56821.143Skamil DPRINTF("Assert that the thread exists\n"); 56831.143Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 56841.143Skamil 56851.143Skamil DPRINTF("Assert that lwp thread %d received expected " 56861.143Skamil "event\n", lwp.pl_lwpid); 56871.143Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 56881.143Skamil info.psi_lwpid == lwp.pl_lwpid ? 56891.143Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 56901.143Skamil 56911.143Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 56921.143Skamil DPRINTF("Before calling ptrace(2) with " 56931.143Skamil "PT_LWPSTATUS for child\n"); 56941.143Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 56951.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, 56961.143Skamil &lwpstatus, sizeof(lwpstatus)) != -1); 56971.143Skamil 56981.143Skamil goto check_lwpstatus; 56991.143Skamil } 57001.143Skamil } else { 57011.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for " 57021.143Skamil "child\n"); 57031.143Skamil SYSCALL_REQUIRE( 57041.143Skamil ptrace(PT_LWPNEXT, child, &lwpstatus, 57051.143Skamil sizeof(lwpstatus)) != -1); 57061.143Skamil DPRINTF("LWP=%d\n", lwpstatus.pl_lwpid); 57071.143Skamil 57081.143Skamil DPRINTF("Assert that the thread exists\n"); 57091.143Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 57101.143Skamil 57111.143Skamil check_lwpstatus: 57121.143Skamil 57131.143Skamil if (strstr(iter, "pl_sigmask") != NULL) { 57141.143Skamil sigmask = lwpstatus.pl_sigmask; 57151.143Skamil 57161.143Skamil DPRINTF("Retrieved sigmask: " 57171.143Skamil "%02x%02x%02x%02x\n", 57181.143Skamil sigmask.__bits[0], sigmask.__bits[1], 57191.143Skamil sigmask.__bits[2], sigmask.__bits[3]); 57201.143Skamil 57211.143Skamil found = false; 57221.143Skamil for (m = 0; 57231.143Skamil m < __arraycount(lwpinfo_thread_sigmask); 57241.143Skamil m++) { 57251.143Skamil if (sigismember(&sigmask, 57261.143Skamil lwpinfo_thread_sigmask[m])) { 57271.143Skamil found = true; 57281.143Skamil lwpinfo_thread_sigmask[m] = 0; 57291.143Skamil break; 57301.143Skamil } 57311.143Skamil } 57321.143Skamil ATF_REQUIRE(found == true); 57331.143Skamil } else if (strstr(iter, "pl_name") != NULL) { 57341.143Skamil name = lwpstatus.pl_name; 57351.143Skamil 57361.143Skamil DPRINTF("Retrieved thread name: " 57371.143Skamil "%s\n", name); 57381.143Skamil 57391.143Skamil snprintf(namebuf, sizeof namebuf, "thread %d", 57401.143Skamil lwpstatus.pl_lwpid); 57411.143Skamil 57421.143Skamil ATF_REQUIRE(strcmp(name, namebuf) == 0); 57431.143Skamil } else if (strstr(iter, "pl_private") != NULL) { 57441.143Skamil private = lwpstatus.pl_private; 57451.143Skamil 57461.143Skamil DPRINTF("Retrieved thread private pointer: " 57471.143Skamil "%p\n", private); 57481.143Skamil 57491.143Skamil found = false; 57501.143Skamil for (m = 0; m < __arraycount(tcb); m++) { 57511.143Skamil DPRINTF("Comparing %p and %p\n", 57521.143Skamil private, tcb[m]); 57531.143Skamil if (private == tcb[m]) { 57541.143Skamil found = true; 57551.143Skamil break; 57561.143Skamil } 57571.143Skamil } 57581.143Skamil ATF_REQUIRE(found == true); 57591.143Skamil } 57601.143Skamil } 57611.143Skamil } 57621.143Skamil 57631.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 57641.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 57651.143Skamil "child\n"); 57661.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 57671.143Skamil != -1); 57681.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 57691.77Skamil 57701.143Skamil DPRINTF("Assert that there are no more threads\n"); 57711.143Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 57721.143Skamil } else { 57731.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 57741.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 57751.143Skamil sizeof(lwpstatus)) != -1); 57761.77Skamil 57771.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 57781.143Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 57791.143Skamil } 57801.77Skamil 57811.77Skamil DPRINTF("Before resuming the child process where it left off and " 57821.77Skamil "without signal to be sent\n"); 57831.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 57841.77Skamil 57851.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57861.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57871.77Skamil 57881.77Skamil validate_status_signaled(status, SIGKILL, 0); 57891.1Skamil 57901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57911.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57921.1Skamil} 57931.1Skamil 57941.143Skamil#define TRACEME_LWPINFO(test, threads, iter) \ 57951.77SkamilATF_TC(test); \ 57961.77SkamilATF_TC_HEAD(test, tc) \ 57971.77Skamil{ \ 57981.77Skamil atf_tc_set_md_var(tc, "descr", \ 57991.143Skamil "Verify " iter " with the child with " #threads \ 58001.77Skamil " spawned extra threads"); \ 58011.77Skamil} \ 58021.77Skamil \ 58031.77SkamilATF_TC_BODY(test, tc) \ 58041.77Skamil{ \ 58051.77Skamil \ 58061.143Skamil traceme_lwpinfo(threads, iter); \ 58071.1Skamil} 58081.1Skamil 58091.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0, "LWPINFO") 58101.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1, "LWPINFO") 58111.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2, "LWPINFO") 58121.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3, "LWPINFO") 58131.143Skamil 58141.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus, 0, "LWPINFO+LWPSTATUS") 58151.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus, 1, "LWPINFO+LWPSTATUS") 58161.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus, 2, "LWPINFO+LWPSTATUS") 58171.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus, 3, "LWPINFO+LWPSTATUS") 58181.143Skamil 58191.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_sigmask, 0, 58201.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58211.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_sigmask, 1, 58221.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58231.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_sigmask, 2, 58241.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58251.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_sigmask, 3, 58261.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 58271.143Skamil 58281.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_name, 0, 58291.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58301.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_name, 1, 58311.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58321.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_name, 2, 58331.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58341.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_name, 3, 58351.143Skamil "LWPINFO+LWPSTATUS+pl_name") 58361.143Skamil 58371.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_private, 0, 58381.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58391.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_private, 1, 58401.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58411.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_private, 2, 58421.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58431.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_private, 3, 58441.143Skamil "LWPINFO+LWPSTATUS+pl_private") 58451.143Skamil 58461.143SkamilTRACEME_LWPINFO(traceme_lwpnext0, 0, "LWPNEXT") 58471.143SkamilTRACEME_LWPINFO(traceme_lwpnext1, 1, "LWPNEXT") 58481.143SkamilTRACEME_LWPINFO(traceme_lwpnext2, 2, "LWPNEXT") 58491.143SkamilTRACEME_LWPINFO(traceme_lwpnext3, 3, "LWPNEXT") 58501.143Skamil 58511.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_sigmask, 0, "LWPNEXT+pl_sigmask") 58521.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_sigmask, 1, "LWPNEXT+pl_sigmask") 58531.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_sigmask, 2, "LWPNEXT+pl_sigmask") 58541.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_sigmask, 3, "LWPNEXT+pl_sigmask") 58551.143Skamil 58561.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_name, 0, "LWPNEXT+pl_name") 58571.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_name, 1, "LWPNEXT+pl_name") 58581.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_name, 2, "LWPNEXT+pl_name") 58591.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_name, 3, "LWPNEXT+pl_name") 58601.143Skamil 58611.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_private, 0, "LWPNEXT+pl_private") 58621.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_private, 1, "LWPNEXT+pl_private") 58631.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_private, 2, "LWPNEXT+pl_private") 58641.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_private, 3, "LWPNEXT+pl_private") 58651.77Skamil 58661.77Skamil/// ---------------------------------------------------------------------------- 58671.77Skamil 58681.77Skamil#if defined(TWAIT_HAVE_PID) 58691.77Skamilstatic void 58701.77Skamilattach_lwpinfo(const int threads) 58711.1Skamil{ 58721.77Skamil const int sigval = SIGINT; 58731.1Skamil struct msg_fds parent_tracee, parent_tracer; 58741.1Skamil const int exitval_tracer = 10; 58751.1Skamil pid_t tracee, tracer, wpid; 58761.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 58771.1Skamil#if defined(TWAIT_HAVE_STATUS) 58781.1Skamil int status; 58791.1Skamil#endif 58801.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 58811.77Skamil struct ptrace_siginfo info; 58821.77Skamil 58831.77Skamil /* Maximum number of supported threads in this test */ 58841.77Skamil pthread_t t[3]; 58851.77Skamil int n, rv; 58861.1Skamil 58871.13Schristos DPRINTF("Spawn tracee\n"); 58881.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 58891.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 58901.1Skamil tracee = atf_utils_fork(); 58911.1Skamil if (tracee == 0) { 58921.1Skamil /* Wait for message from the parent */ 58931.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 58941.1Skamil 58951.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 58961.77Skamil 58971.77Skamil for (n = 0; n < threads; n++) { 58981.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 58991.77Skamil FORKEE_ASSERT(rv == 0); 59001.77Skamil } 59011.77Skamil 59021.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 59031.77Skamil 59041.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 59051.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 59061.77Skamil 59071.77Skamil /* NOTREACHED */ 59081.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 59091.1Skamil } 59101.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 59111.1Skamil 59121.13Schristos DPRINTF("Spawn debugger\n"); 59131.1Skamil tracer = atf_utils_fork(); 59141.1Skamil if (tracer == 0) { 59151.1Skamil /* No IPC to communicate with the child */ 59161.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 59171.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 59181.1Skamil 59191.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 59201.1Skamil FORKEE_REQUIRE_SUCCESS( 59211.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 59221.1Skamil 59231.1Skamil forkee_status_stopped(status, SIGSTOP); 59241.1Skamil 59251.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 59261.77Skamil "tracee"); 59271.77Skamil FORKEE_ASSERT( 59281.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 59291.77Skamil 59301.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 59311.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 59321.77Skamil "si_errno=%#x\n", 59331.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 59341.77Skamil info.psi_siginfo.si_errno); 59351.77Skamil 59361.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 59371.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 59381.77Skamil 59391.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 59401.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 59411.1Skamil != -1); 59421.1Skamil 59431.13Schristos DPRINTF("Assert that there exists a thread\n"); 59441.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 59451.1Skamil 59461.13Schristos DPRINTF("Assert that lwp thread %d received event " 59471.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 59481.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 59491.1Skamil 59501.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 59511.77Skamil "tracee\n"); 59521.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 59531.1Skamil != -1); 59541.1Skamil 59551.77Skamil DPRINTF("Assert that there are no more lwp threads in " 59561.77Skamil "tracee\n"); 59571.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 59581.1Skamil 59591.1Skamil /* Resume tracee with PT_CONTINUE */ 59601.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 59611.1Skamil 59621.1Skamil /* Inform parent that tracer has attached to tracee */ 59631.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 59641.77Skamil 59651.1Skamil /* Wait for parent */ 59661.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 59671.1Skamil 59681.77Skamil /* Wait for tracee and assert that it raised a signal */ 59691.77Skamil FORKEE_REQUIRE_SUCCESS( 59701.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 59711.77Skamil 59721.77Skamil forkee_status_stopped(status, SIGINT); 59731.77Skamil 59741.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 59751.77Skamil "child"); 59761.77Skamil FORKEE_ASSERT( 59771.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 59781.77Skamil 59791.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 59801.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 59811.77Skamil "si_errno=%#x\n", 59821.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 59831.77Skamil info.psi_siginfo.si_errno); 59841.77Skamil 59851.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 59861.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 59871.77Skamil 59881.77Skamil memset(&lwp, 0, sizeof(lwp)); 59891.77Skamil 59901.77Skamil for (n = 0; n <= threads; n++) { 59911.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 59921.77Skamil "child\n"); 59931.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 59941.77Skamil sizeof(lwp)) != -1); 59951.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 59961.77Skamil 59971.77Skamil DPRINTF("Assert that the thread exists\n"); 59981.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 59991.77Skamil 60001.77Skamil DPRINTF("Assert that lwp thread %d received expected " 60011.77Skamil "event\n", lwp.pl_lwpid); 60021.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 60031.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 60041.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 60051.77Skamil } 60061.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 60071.77Skamil "tracee\n"); 60081.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 60091.77Skamil != -1); 60101.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 60111.77Skamil 60121.77Skamil DPRINTF("Assert that there are no more threads\n"); 60131.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 60141.77Skamil 60151.77Skamil DPRINTF("Before resuming the child process where it left off " 60161.77Skamil "and without signal to be sent\n"); 60171.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 60181.77Skamil != -1); 60191.77Skamil 60201.1Skamil /* Wait for tracee and assert that it exited */ 60211.1Skamil FORKEE_REQUIRE_SUCCESS( 60221.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 60231.1Skamil 60241.77Skamil forkee_status_signaled(status, SIGKILL, 0); 60251.1Skamil 60261.13Schristos DPRINTF("Before exiting of the tracer process\n"); 60271.1Skamil _exit(exitval_tracer); 60281.1Skamil } 60291.1Skamil 60301.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 60311.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 60321.1Skamil 60331.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 60341.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 60351.77Skamil 60361.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 60371.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 60381.1Skamil 60391.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 60401.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 60411.1Skamil 60421.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 60431.1Skamil TWAIT_FNAME); 60441.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 60451.1Skamil tracer); 60461.1Skamil 60471.1Skamil validate_status_exited(status, exitval_tracer); 60481.1Skamil 60491.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 60501.1Skamil TWAIT_FNAME); 60511.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 60521.1Skamil tracee); 60531.1Skamil 60541.77Skamil validate_status_signaled(status, SIGKILL, 0); 60551.1Skamil 60561.1Skamil msg_close(&parent_tracer); 60571.1Skamil msg_close(&parent_tracee); 60581.1Skamil} 60591.77Skamil 60601.77Skamil#define ATTACH_LWPINFO(test, threads) \ 60611.77SkamilATF_TC(test); \ 60621.77SkamilATF_TC_HEAD(test, tc) \ 60631.77Skamil{ \ 60641.77Skamil atf_tc_set_md_var(tc, "descr", \ 60651.77Skamil "Verify LWPINFO with the child with " #threads \ 60661.77Skamil " spawned extra threads (tracer is not the original " \ 60671.77Skamil "parent)"); \ 60681.77Skamil} \ 60691.77Skamil \ 60701.77SkamilATF_TC_BODY(test, tc) \ 60711.77Skamil{ \ 60721.77Skamil \ 60731.77Skamil attach_lwpinfo(threads); \ 60741.77Skamil} 60751.77Skamil 60761.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 60771.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 60781.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 60791.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 60801.1Skamil#endif 60811.1Skamil 60821.77Skamil/// ---------------------------------------------------------------------------- 60831.77Skamil 60841.1Skamilstatic void 60851.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 60861.1Skamil{ 60871.1Skamil const int exitval = 5; 60881.1Skamil const int sigval = SIGINT; 60891.1Skamil const int sigfaked = SIGTRAP; 60901.1Skamil const int sicodefaked = TRAP_BRKPT; 60911.1Skamil pid_t child, wpid; 60921.1Skamil struct sigaction sa; 60931.1Skamil#if defined(TWAIT_HAVE_STATUS) 60941.1Skamil int status; 60951.1Skamil#endif 60961.1Skamil struct ptrace_siginfo info; 60971.1Skamil memset(&info, 0, sizeof(info)); 60981.1Skamil 60991.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61001.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61011.1Skamil if (child == 0) { 61021.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61031.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61041.1Skamil 61051.79Skamil sa.sa_sigaction = sah; 61061.1Skamil sa.sa_flags = SA_SIGINFO; 61071.1Skamil sigemptyset(&sa.sa_mask); 61081.1Skamil 61091.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 61101.79Skamil != -1); 61111.1Skamil 61121.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61131.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61141.1Skamil 61151.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 61161.1Skamil 61171.13Schristos DPRINTF("Before exiting of the child process\n"); 61181.1Skamil _exit(exitval); 61191.1Skamil } 61201.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61211.1Skamil 61221.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61231.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61241.1Skamil 61251.1Skamil validate_status_stopped(status, sigval); 61261.1Skamil 61271.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 61281.61Skre SYSCALL_REQUIRE( 61291.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 61301.1Skamil 61311.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 61321.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 61331.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 61341.1Skamil info.psi_siginfo.si_errno); 61351.1Skamil 61361.79Skamil if (faked) { 61371.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 61381.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 61391.79Skamil info.psi_siginfo.si_signo = sigfaked; 61401.79Skamil info.psi_siginfo.si_code = sicodefaked; 61411.79Skamil } 61421.1Skamil 61431.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 61441.61Skre SYSCALL_REQUIRE( 61451.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 61461.1Skamil 61471.79Skamil if (faked) { 61481.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 61491.79Skamil "child\n"); 61501.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 61511.79Skamil sizeof(info)) != -1); 61521.1Skamil 61531.79Skamil DPRINTF("Before checking siginfo_t\n"); 61541.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 61551.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 61561.79Skamil } 61571.1Skamil 61581.13Schristos DPRINTF("Before resuming the child process where it left off and " 61591.1Skamil "without signal to be sent\n"); 61601.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 61611.79Skamil faked ? sigfaked : sigval) != -1); 61621.1Skamil 61631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61651.1Skamil 61661.1Skamil validate_status_exited(status, exitval); 61671.1Skamil 61681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 61701.1Skamil} 61711.1Skamil 61721.79Skamil#define PTRACE_SIGINFO(test, faked) \ 61731.79SkamilATF_TC(test); \ 61741.79SkamilATF_TC_HEAD(test, tc) \ 61751.79Skamil{ \ 61761.79Skamil atf_tc_set_md_var(tc, "descr", \ 61771.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 61781.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 61791.79Skamil} \ 61801.79Skamil \ 61811.79Skamilstatic int test##_caught = 0; \ 61821.79Skamil \ 61831.79Skamilstatic void \ 61841.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 61851.79Skamil{ \ 61861.79Skamil if (faked) { \ 61871.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 61881.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 61891.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 61901.79Skamil } else { \ 61911.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 61921.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 61931.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 61941.79Skamil } \ 61951.79Skamil \ 61961.79Skamil ++ test##_caught; \ 61971.79Skamil} \ 61981.79Skamil \ 61991.79SkamilATF_TC_BODY(test, tc) \ 62001.79Skamil{ \ 62011.79Skamil \ 62021.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 62031.79Skamil} 62041.79Skamil 62051.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 62061.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 62071.79Skamil 62081.79Skamil/// ---------------------------------------------------------------------------- 62091.79Skamil 62101.97Skamilstatic void 62111.97Skamiltraceme_exec(bool masked, bool ignored) 62121.1Skamil{ 62131.1Skamil const int sigval = SIGTRAP; 62141.1Skamil pid_t child, wpid; 62151.1Skamil#if defined(TWAIT_HAVE_STATUS) 62161.1Skamil int status; 62171.1Skamil#endif 62181.97Skamil struct sigaction sa; 62191.97Skamil struct ptrace_siginfo info; 62201.97Skamil sigset_t intmask; 62211.97Skamil struct kinfo_proc2 kp; 62221.97Skamil size_t len = sizeof(kp); 62231.97Skamil 62241.97Skamil int name[6]; 62251.97Skamil const size_t namelen = __arraycount(name); 62261.97Skamil ki_sigset_t kp_sigmask; 62271.97Skamil ki_sigset_t kp_sigignore; 62281.1Skamil 62291.1Skamil memset(&info, 0, sizeof(info)); 62301.1Skamil 62311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62331.1Skamil if (child == 0) { 62341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62361.1Skamil 62371.97Skamil if (masked) { 62381.97Skamil sigemptyset(&intmask); 62391.97Skamil sigaddset(&intmask, sigval); 62401.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62411.97Skamil } 62421.97Skamil 62431.97Skamil if (ignored) { 62441.97Skamil memset(&sa, 0, sizeof(sa)); 62451.97Skamil sa.sa_handler = SIG_IGN; 62461.97Skamil sigemptyset(&sa.sa_mask); 62471.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 62481.97Skamil } 62491.97Skamil 62501.13Schristos DPRINTF("Before calling execve(2) from child\n"); 62511.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 62521.1Skamil 62531.1Skamil FORKEE_ASSERT(0 && "Not reached"); 62541.1Skamil } 62551.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62561.1Skamil 62571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62581.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62591.1Skamil 62601.1Skamil validate_status_stopped(status, sigval); 62611.1Skamil 62621.97Skamil name[0] = CTL_KERN, 62631.97Skamil name[1] = KERN_PROC2, 62641.97Skamil name[2] = KERN_PROC_PID; 62651.97Skamil name[3] = getpid(); 62661.97Skamil name[4] = sizeof(kp); 62671.97Skamil name[5] = 1; 62681.97Skamil 62691.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 62701.97Skamil 62711.97Skamil if (masked) 62721.97Skamil kp_sigmask = kp.p_sigmask; 62731.97Skamil 62741.97Skamil if (ignored) 62751.97Skamil kp_sigignore = kp.p_sigignore; 62761.97Skamil 62771.97Skamil name[3] = getpid(); 62781.97Skamil 62791.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 62801.97Skamil 62811.97Skamil if (masked) { 62821.97Skamil DPRINTF("kp_sigmask=" 62831.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 62841.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 62851.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 62861.97Skamil 62871.97Skamil DPRINTF("kp.p_sigmask=" 62881.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 62891.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 62901.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 62911.97Skamil 62921.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 62931.97Skamil sizeof(kp_sigmask))); 62941.97Skamil } 62951.97Skamil 62961.97Skamil if (ignored) { 62971.97Skamil DPRINTF("kp_sigignore=" 62981.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 62991.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 63001.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 63011.97Skamil 63021.97Skamil DPRINTF("kp.p_sigignore=" 63031.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 63041.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 63051.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 63061.97Skamil 63071.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 63081.97Skamil sizeof(kp_sigignore))); 63091.97Skamil } 63101.97Skamil 63111.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 63121.61Skre SYSCALL_REQUIRE( 63131.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 63141.1Skamil 63151.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 63161.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 63171.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 63181.1Skamil info.psi_siginfo.si_errno); 63191.1Skamil 63201.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 63211.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 63221.1Skamil 63231.13Schristos DPRINTF("Before resuming the child process where it left off and " 63241.1Skamil "without signal to be sent\n"); 63251.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63261.1Skamil 63271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63291.1Skamil 63301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63311.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63321.1Skamil} 63331.1Skamil 63341.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 63351.97SkamilATF_TC(test); \ 63361.97SkamilATF_TC_HEAD(test, tc) \ 63371.97Skamil{ \ 63381.97Skamil atf_tc_set_md_var(tc, "descr", \ 63391.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 63401.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 63411.97Skamil masked ? " with ignored signal" : ""); \ 63421.97Skamil} \ 63431.97Skamil \ 63441.97SkamilATF_TC_BODY(test, tc) \ 63451.97Skamil{ \ 63461.97Skamil \ 63471.97Skamil traceme_exec(masked, ignored); \ 63481.97Skamil} 63491.97Skamil 63501.97SkamilTRACEME_EXEC(traceme_exec, false, false) 63511.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 63521.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 63531.97Skamil 63541.82Skamil/// ---------------------------------------------------------------------------- 63551.82Skamil 63561.135Skamil#define TRACE_THREADS_NUM 100 63571.135Skamil 63581.83Skamilstatic volatile int done; 63591.137Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER; 63601.1Skamil 63611.83Skamilstatic void * 63621.83Skamiltrace_threads_cb(void *arg __unused) 63631.1Skamil{ 63641.1Skamil 63651.137Skamil pthread_mutex_lock(&trace_threads_mtx); 63661.83Skamil done++; 63671.137Skamil pthread_mutex_unlock(&trace_threads_mtx); 63681.83Skamil 63691.135Skamil while (done < TRACE_THREADS_NUM) 63701.135Skamil sched_yield(); 63711.83Skamil 63721.83Skamil return NULL; 63731.1Skamil} 63741.1Skamil 63751.83Skamilstatic void 63761.153Skamiltrace_threads(bool trace_create, bool trace_exit, bool masked) 63771.1Skamil{ 63781.1Skamil const int sigval = SIGSTOP; 63791.1Skamil pid_t child, wpid; 63801.1Skamil#if defined(TWAIT_HAVE_STATUS) 63811.1Skamil int status; 63821.1Skamil#endif 63831.1Skamil ptrace_state_t state; 63841.1Skamil const int slen = sizeof(state); 63851.1Skamil ptrace_event_t event; 63861.1Skamil const int elen = sizeof(event); 63871.83Skamil struct ptrace_siginfo info; 63881.83Skamil 63891.153Skamil sigset_t intmask; 63901.153Skamil 63911.135Skamil pthread_t t[TRACE_THREADS_NUM]; 63921.83Skamil int rv; 63931.83Skamil size_t n; 63941.1Skamil lwpid_t lid; 63951.83Skamil 63961.83Skamil /* Track created and exited threads */ 63971.141Skamil struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}}; 63981.83Skamil 63991.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64001.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64011.1Skamil if (child == 0) { 64021.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64031.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64041.1Skamil 64051.153Skamil if (masked) { 64061.153Skamil sigemptyset(&intmask); 64071.153Skamil sigaddset(&intmask, SIGTRAP); 64081.153Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 64091.153Skamil } 64101.153Skamil 64111.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64121.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64131.1Skamil 64141.83Skamil for (n = 0; n < __arraycount(t); n++) { 64151.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 64161.83Skamil NULL); 64171.83Skamil FORKEE_ASSERT(rv == 0); 64181.83Skamil } 64191.1Skamil 64201.83Skamil for (n = 0; n < __arraycount(t); n++) { 64211.83Skamil rv = pthread_join(t[n], NULL); 64221.83Skamil FORKEE_ASSERT(rv == 0); 64231.83Skamil } 64241.1Skamil 64251.83Skamil /* 64261.83Skamil * There is race between _exit() and pthread_join() detaching 64271.83Skamil * a thread. For simplicity kill the process after detecting 64281.83Skamil * LWP events. 64291.83Skamil */ 64301.83Skamil while (true) 64311.83Skamil continue; 64321.1Skamil 64331.83Skamil FORKEE_ASSERT(0 && "Not reached"); 64341.1Skamil } 64351.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64361.1Skamil 64371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64391.1Skamil 64401.1Skamil validate_status_stopped(status, sigval); 64411.1Skamil 64421.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 64431.83Skamil SYSCALL_REQUIRE( 64441.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 64451.1Skamil 64461.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 64471.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 64481.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 64491.83Skamil info.psi_siginfo.si_errno); 64501.1Skamil 64511.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 64521.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 64531.1Skamil 64541.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 64551.83Skamil memset(&event, 0, sizeof(event)); 64561.83Skamil if (trace_create) 64571.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 64581.83Skamil if (trace_exit) 64591.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 64601.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 64611.1Skamil 64621.13Schristos DPRINTF("Before resuming the child process where it left off and " 64631.1Skamil "without signal to be sent\n"); 64641.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64651.1Skamil 64661.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 64671.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 64681.83Skamil "SIGTRAP\n", TWAIT_FNAME); 64691.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 64701.83Skamil child); 64711.1Skamil 64721.83Skamil validate_status_stopped(status, SIGTRAP); 64731.1Skamil 64741.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 64751.83Skamil "child\n"); 64761.83Skamil SYSCALL_REQUIRE( 64771.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 64781.1Skamil 64791.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 64801.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 64811.83Skamil "si_errno=%#x\n", 64821.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 64831.83Skamil info.psi_siginfo.si_errno); 64841.1Skamil 64851.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 64861.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 64871.1Skamil 64881.83Skamil SYSCALL_REQUIRE( 64891.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 64901.1Skamil 64911.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 64921.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 64931.1Skamil 64941.83Skamil lid = state.pe_lwp; 64951.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 64961.1Skamil 64971.141Skamil *FIND_EVENT_COUNT(traced_lwps, lid) += 1; 64981.1Skamil 64991.83Skamil DPRINTF("Before resuming the child process where it left off " 65001.83Skamil "and without signal to be sent\n"); 65011.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65021.83Skamil } 65031.1Skamil 65041.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 65051.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 65061.83Skamil "SIGTRAP\n", TWAIT_FNAME); 65071.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 65081.83Skamil child); 65091.1Skamil 65101.83Skamil validate_status_stopped(status, SIGTRAP); 65111.1Skamil 65121.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 65131.83Skamil "child\n"); 65141.83Skamil SYSCALL_REQUIRE( 65151.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 65161.1Skamil 65171.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 65181.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 65191.83Skamil "si_errno=%#x\n", 65201.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 65211.83Skamil info.psi_siginfo.si_errno); 65221.1Skamil 65231.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 65241.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 65251.1Skamil 65261.83Skamil SYSCALL_REQUIRE( 65271.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 65281.1Skamil 65291.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 65301.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 65311.1Skamil 65321.83Skamil lid = state.pe_lwp; 65331.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 65341.1Skamil 65351.83Skamil if (trace_create) { 65361.141Skamil int *count = FIND_EVENT_COUNT(traced_lwps, lid); 65371.141Skamil ATF_REQUIRE_EQ(*count, 1); 65381.141Skamil *count = 0; 65391.83Skamil } 65401.1Skamil 65411.83Skamil DPRINTF("Before resuming the child process where it left off " 65421.83Skamil "and without signal to be sent\n"); 65431.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65441.83Skamil } 65451.1Skamil 65461.83Skamil kill(child, SIGKILL); 65471.1Skamil 65481.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65491.1Skamil TWAIT_FNAME); 65501.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65511.1Skamil 65521.83Skamil validate_status_signaled(status, SIGKILL, 0); 65531.1Skamil 65541.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65551.1Skamil TWAIT_FNAME); 65561.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65571.1Skamil} 65581.1Skamil 65591.153Skamil#define TRACE_THREADS(test, trace_create, trace_exit, mask) \ 65601.83SkamilATF_TC(test); \ 65611.83SkamilATF_TC_HEAD(test, tc) \ 65621.83Skamil{ \ 65631.83Skamil atf_tc_set_md_var(tc, "descr", \ 65641.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 65651.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 65661.83Skamil trace_exit ? "" : "out"); \ 65671.83Skamil} \ 65681.83Skamil \ 65691.83SkamilATF_TC_BODY(test, tc) \ 65701.83Skamil{ \ 65711.83Skamil \ 65721.153Skamil trace_threads(trace_create, trace_exit, mask); \ 65731.83Skamil} 65741.83Skamil 65751.153SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false, false) 65761.153SkamilTRACE_THREADS(trace_thread_lwpexit, false, true, false) 65771.153SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false, false) 65781.153SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true, false) 65791.153Skamil 65801.153SkamilTRACE_THREADS(trace_thread_lwpexit_masked_sigtrap, false, true, true) 65811.153SkamilTRACE_THREADS(trace_thread_lwpcreate_masked_sigtrap, true, false, true) 65821.153SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit_masked_sigtrap, true, true, true) 65831.83Skamil 65841.83Skamil/// ---------------------------------------------------------------------------- 65851.83Skamil 65861.84SkamilATF_TC(signal_mask_unrelated); 65871.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 65881.1Skamil{ 65891.1Skamil atf_tc_set_md_var(tc, "descr", 65901.1Skamil "Verify that masking single unrelated signal does not stop tracer " 65911.1Skamil "from catching other signals"); 65921.1Skamil} 65931.1Skamil 65941.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 65951.1Skamil{ 65961.1Skamil const int exitval = 5; 65971.1Skamil const int sigval = SIGSTOP; 65981.1Skamil const int sigmasked = SIGTRAP; 65991.1Skamil const int signotmasked = SIGINT; 66001.1Skamil pid_t child, wpid; 66011.1Skamil#if defined(TWAIT_HAVE_STATUS) 66021.1Skamil int status; 66031.1Skamil#endif 66041.1Skamil sigset_t intmask; 66051.1Skamil 66061.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66071.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66081.1Skamil if (child == 0) { 66091.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66101.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66111.1Skamil 66121.1Skamil sigemptyset(&intmask); 66131.1Skamil sigaddset(&intmask, sigmasked); 66141.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 66151.1Skamil 66161.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66171.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66181.1Skamil 66191.13Schristos DPRINTF("Before raising %s from child\n", 66201.1Skamil strsignal(signotmasked)); 66211.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 66221.1Skamil 66231.13Schristos DPRINTF("Before exiting of the child process\n"); 66241.1Skamil _exit(exitval); 66251.1Skamil } 66261.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66271.1Skamil 66281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66301.1Skamil 66311.1Skamil validate_status_stopped(status, sigval); 66321.1Skamil 66331.13Schristos DPRINTF("Before resuming the child process where it left off and " 66341.1Skamil "without signal to be sent\n"); 66351.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66361.1Skamil 66371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66391.1Skamil 66401.1Skamil validate_status_stopped(status, signotmasked); 66411.1Skamil 66421.13Schristos DPRINTF("Before resuming the child process where it left off and " 66431.1Skamil "without signal to be sent\n"); 66441.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66451.1Skamil 66461.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66481.1Skamil 66491.1Skamil validate_status_exited(status, exitval); 66501.1Skamil 66511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66521.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66531.1Skamil} 66541.1Skamil 66551.84Skamil/// ---------------------------------------------------------------------------- 66561.84Skamil 66571.1Skamil#if defined(TWAIT_HAVE_PID) 66581.99Skamilstatic void 66591.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 66601.1Skamil{ 66611.1Skamil const int exitval = 5; 66621.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 66631.1Skamil const int sigval = SIGSTOP; 66641.99Skamil pid_t child, child2 = 0, wpid; 66651.1Skamil#if defined(TWAIT_HAVE_STATUS) 66661.1Skamil int status; 66671.1Skamil#endif 66681.1Skamil ptrace_state_t state; 66691.1Skamil const int slen = sizeof(state); 66701.1Skamil ptrace_event_t event; 66711.1Skamil const int elen = sizeof(event); 66721.99Skamil struct sigaction sa; 66731.99Skamil struct ptrace_siginfo info; 66741.99Skamil sigset_t intmask; 66751.99Skamil struct kinfo_proc2 kp; 66761.99Skamil size_t len = sizeof(kp); 66771.99Skamil 66781.99Skamil int name[6]; 66791.99Skamil const size_t namelen = __arraycount(name); 66801.99Skamil ki_sigset_t kp_sigmask; 66811.99Skamil ki_sigset_t kp_sigignore; 66821.1Skamil 66831.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 66841.14Schristos 66851.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66861.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66871.1Skamil if (child == 0) { 66881.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66891.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66901.1Skamil 66911.99Skamil if (masked) { 66921.99Skamil sigemptyset(&intmask); 66931.99Skamil sigaddset(&intmask, SIGTRAP); 66941.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 66951.99Skamil } 66961.99Skamil 66971.99Skamil if (ignored) { 66981.99Skamil memset(&sa, 0, sizeof(sa)); 66991.99Skamil sa.sa_handler = SIG_IGN; 67001.99Skamil sigemptyset(&sa.sa_mask); 67011.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 67021.99Skamil } 67031.1Skamil 67041.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67051.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67061.1Skamil 67071.126Skamil if (strcmp(fn, "spawn") == 0) { 67081.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 67091.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 67101.126Skamil } else { 67111.126Skamil if (strcmp(fn, "fork") == 0) { 67121.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 67131.126Skamil } else { 67141.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 67151.126Skamil } 67161.126Skamil if (child2 == 0) 67171.126Skamil _exit(exitval2); 67181.126Skamil } 67191.1Skamil 67201.1Skamil FORKEE_REQUIRE_SUCCESS 67211.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 67221.1Skamil 67231.1Skamil forkee_status_exited(status, exitval2); 67241.1Skamil 67251.13Schristos DPRINTF("Before exiting of the child process\n"); 67261.1Skamil _exit(exitval); 67271.1Skamil } 67281.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67291.1Skamil 67301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67311.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67321.1Skamil 67331.1Skamil validate_status_stopped(status, sigval); 67341.1Skamil 67351.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67361.99Skamil SYSCALL_REQUIRE( 67371.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67381.99Skamil 67391.99Skamil DPRINTF("Before checking siginfo_t\n"); 67401.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 67411.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 67421.1Skamil 67431.99Skamil name[0] = CTL_KERN, 67441.99Skamil name[1] = KERN_PROC2, 67451.99Skamil name[2] = KERN_PROC_PID; 67461.99Skamil name[3] = child; 67471.99Skamil name[4] = sizeof(kp); 67481.99Skamil name[5] = 1; 67491.1Skamil 67501.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 67511.1Skamil 67521.99Skamil if (masked) 67531.99Skamil kp_sigmask = kp.p_sigmask; 67541.1Skamil 67551.99Skamil if (ignored) 67561.99Skamil kp_sigignore = kp.p_sigignore; 67571.1Skamil 67581.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 67591.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 67601.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 67611.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 67621.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 67631.99Skamil event.pe_set_event = 0; 67641.126Skamil if (strcmp(fn, "spawn") == 0) 67651.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 67661.126Skamil if (strcmp(fn, "fork") == 0) 67671.99Skamil event.pe_set_event |= PTRACE_FORK; 67681.126Skamil if (strcmp(fn, "vfork") == 0) 67691.99Skamil event.pe_set_event |= PTRACE_VFORK; 67701.126Skamil if (strcmp(fn, "vforkdone") == 0) 67711.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 67721.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 67731.1Skamil 67741.99Skamil DPRINTF("Before resuming the child process where it left off and " 67751.99Skamil "without signal to be sent\n"); 67761.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67771.1Skamil 67781.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 67791.126Skamil strcmp(fn, "vfork") == 0) { 67801.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 67811.99Skamil child); 67821.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 67831.99Skamil child); 67841.1Skamil 67851.99Skamil validate_status_stopped(status, SIGTRAP); 67861.1Skamil 67871.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 67881.1Skamil 67891.99Skamil if (masked) { 67901.99Skamil DPRINTF("kp_sigmask=" 67911.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 67921.99Skamil PRIx32 "\n", 67931.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 67941.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 67951.1Skamil 67961.99Skamil DPRINTF("kp.p_sigmask=" 67971.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 67981.99Skamil PRIx32 "\n", 67991.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 68001.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 68011.1Skamil 68021.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 68031.99Skamil sizeof(kp_sigmask))); 68041.99Skamil } 68051.1Skamil 68061.99Skamil if (ignored) { 68071.99Skamil DPRINTF("kp_sigignore=" 68081.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68091.99Skamil PRIx32 "\n", 68101.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 68111.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 68121.1Skamil 68131.99Skamil DPRINTF("kp.p_sigignore=" 68141.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68151.99Skamil PRIx32 "\n", 68161.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 68171.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 68181.1Skamil 68191.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 68201.99Skamil sizeof(kp_sigignore))); 68211.99Skamil } 68221.1Skamil 68231.99Skamil SYSCALL_REQUIRE( 68241.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68251.126Skamil if (strcmp(fn, "spawn") == 0) { 68261.126Skamil ATF_REQUIRE_EQ( 68271.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 68281.126Skamil PTRACE_POSIX_SPAWN); 68291.126Skamil } 68301.126Skamil if (strcmp(fn, "fork") == 0) { 68311.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68321.99Skamil PTRACE_FORK); 68331.99Skamil } 68341.126Skamil if (strcmp(fn, "vfork") == 0) { 68351.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68361.99Skamil PTRACE_VFORK); 68371.99Skamil } 68381.1Skamil 68391.99Skamil child2 = state.pe_other_pid; 68401.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 68411.1Skamil 68421.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 68431.99Skamil "%d\n", TWAIT_FNAME, child2, child); 68441.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 68451.99Skamil child2); 68461.1Skamil 68471.99Skamil validate_status_stopped(status, SIGTRAP); 68481.1Skamil 68491.99Skamil name[3] = child2; 68501.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 68511.1Skamil 68521.99Skamil if (masked) { 68531.99Skamil DPRINTF("kp_sigmask=" 68541.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68551.99Skamil PRIx32 "\n", 68561.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 68571.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 68581.1Skamil 68591.99Skamil DPRINTF("kp.p_sigmask=" 68601.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68611.99Skamil PRIx32 "\n", 68621.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 68631.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 68641.14Schristos 68651.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 68661.99Skamil sizeof(kp_sigmask))); 68671.99Skamil } 68681.1Skamil 68691.99Skamil if (ignored) { 68701.99Skamil DPRINTF("kp_sigignore=" 68711.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68721.99Skamil PRIx32 "\n", 68731.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 68741.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 68751.1Skamil 68761.99Skamil DPRINTF("kp.p_sigignore=" 68771.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 68781.99Skamil PRIx32 "\n", 68791.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 68801.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 68811.1Skamil 68821.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 68831.99Skamil sizeof(kp_sigignore))); 68841.99Skamil } 68851.1Skamil 68861.99Skamil SYSCALL_REQUIRE( 68871.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 68881.126Skamil if (strcmp(fn, "spawn") == 0) { 68891.126Skamil ATF_REQUIRE_EQ( 68901.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 68911.126Skamil PTRACE_POSIX_SPAWN); 68921.126Skamil } 68931.126Skamil if (strcmp(fn, "fork") == 0) { 68941.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68951.99Skamil PTRACE_FORK); 68961.99Skamil } 68971.126Skamil if (strcmp(fn, "vfork") == 0) { 68981.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68991.99Skamil PTRACE_VFORK); 69001.99Skamil } 69011.1Skamil 69021.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 69031.1Skamil 69041.99Skamil DPRINTF("Before resuming the forkee process where it left off " 69051.99Skamil "and without signal to be sent\n"); 69061.99Skamil SYSCALL_REQUIRE( 69071.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 69081.1Skamil 69091.99Skamil DPRINTF("Before resuming the child process where it left off " 69101.99Skamil "and without signal to be sent\n"); 69111.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69121.1Skamil } 69131.1Skamil 69141.126Skamil if (strcmp(fn, "vforkdone") == 0) { 69151.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69161.99Skamil child); 69171.99Skamil TWAIT_REQUIRE_SUCCESS( 69181.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 69191.1Skamil 69201.99Skamil validate_status_stopped(status, SIGTRAP); 69211.1Skamil 69221.99Skamil name[3] = child; 69231.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 69241.1Skamil 69251.102Skamil /* 69261.102Skamil * SIGCHLD is now pending in the signal queue and 69271.102Skamil * the kernel presents it to userland as a masked signal. 69281.102Skamil */ 69291.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 69301.102Skamil 69311.99Skamil if (masked) { 69321.99Skamil DPRINTF("kp_sigmask=" 69331.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69341.99Skamil PRIx32 "\n", 69351.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 69361.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 69371.1Skamil 69381.99Skamil DPRINTF("kp.p_sigmask=" 69391.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69401.99Skamil PRIx32 "\n", 69411.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 69421.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 69431.1Skamil 69441.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 69451.99Skamil sizeof(kp_sigmask))); 69461.99Skamil } 69471.1Skamil 69481.99Skamil if (ignored) { 69491.99Skamil DPRINTF("kp_sigignore=" 69501.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69511.99Skamil PRIx32 "\n", 69521.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 69531.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 69541.1Skamil 69551.99Skamil DPRINTF("kp.p_sigignore=" 69561.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69571.99Skamil PRIx32 "\n", 69581.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 69591.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 69601.1Skamil 69611.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 69621.99Skamil sizeof(kp_sigignore))); 69631.99Skamil } 69641.1Skamil 69651.99Skamil SYSCALL_REQUIRE( 69661.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69671.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 69681.1Skamil 69691.99Skamil child2 = state.pe_other_pid; 69701.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 69711.99Skamil child2); 69721.1Skamil 69731.99Skamil DPRINTF("Before resuming the child process where it left off " 69741.99Skamil "and without signal to be sent\n"); 69751.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69761.99Skamil } 69771.1Skamil 69781.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 69791.126Skamil strcmp(fn, "vfork") == 0) { 69801.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 69811.99Skamil "\n", TWAIT_FNAME); 69821.99Skamil TWAIT_REQUIRE_SUCCESS( 69831.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 69841.1Skamil 69851.99Skamil validate_status_exited(status, exitval2); 69861.1Skamil 69871.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 69881.99Skamil "process\n", TWAIT_FNAME); 69891.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 69901.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 69911.99Skamil } 69921.1Skamil 69931.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 69941.1Skamil "SIGCHLD\n", TWAIT_FNAME); 69951.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69961.1Skamil 69971.1Skamil validate_status_stopped(status, SIGCHLD); 69981.1Skamil 69991.57Skamil DPRINTF("Before resuming the child process where it left off and " 70001.1Skamil "without signal to be sent\n"); 70011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70021.1Skamil 70031.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 70041.1Skamil TWAIT_FNAME); 70051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70061.1Skamil 70071.1Skamil validate_status_exited(status, exitval); 70081.1Skamil 70091.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 70101.57Skamil TWAIT_FNAME); 70111.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 70121.1Skamil} 70131.1Skamil 70141.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 70151.99SkamilATF_TC(name); \ 70161.99SkamilATF_TC_HEAD(name, tc) \ 70171.99Skamil{ \ 70181.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 70191.99Skamil "regardless of signal %s%s", \ 70201.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 70211.99Skamil} \ 70221.99Skamil \ 70231.99SkamilATF_TC_BODY(name, tc) \ 70241.99Skamil{ \ 70251.99Skamil \ 70261.126Skamil fork2_body(fn, masked, ignored); \ 70271.1Skamil} 70281.1Skamil 70291.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 70301.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 70311.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 70321.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 70331.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 70341.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 70351.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 70361.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 70371.1Skamil#endif 70381.1Skamil 70391.99Skamil/// ---------------------------------------------------------------------------- 70401.1Skamil 70411.151Skamilstatic void * 70421.151Skamilthread_and_exec_thread_cb(void *arg __unused) 70431.151Skamil{ 70441.151Skamil 70451.151Skamil execlp("/bin/echo", "/bin/echo", NULL); 70461.151Skamil 70471.151Skamil abort(); 70481.151Skamil} 70491.151Skamil 70501.151Skamilstatic void 70511.151Skamilthreads_and_exec(void) 70521.151Skamil{ 70531.151Skamil const int sigval = SIGSTOP; 70541.151Skamil pid_t child, wpid; 70551.151Skamil#if defined(TWAIT_HAVE_STATUS) 70561.151Skamil int status; 70571.151Skamil#endif 70581.151Skamil ptrace_state_t state; 70591.151Skamil const int slen = sizeof(state); 70601.151Skamil ptrace_event_t event; 70611.151Skamil const int elen = sizeof(event); 70621.151Skamil struct ptrace_siginfo info; 70631.151Skamil 70641.151Skamil pthread_t t; 70651.151Skamil lwpid_t lid; 70661.151Skamil 70671.151Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 70681.151Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70691.151Skamil if (child == 0) { 70701.151Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70711.151Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70721.151Skamil 70731.151Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70741.151Skamil FORKEE_ASSERT(raise(sigval) == 0); 70751.151Skamil 70761.151Skamil FORKEE_ASSERT(pthread_create(&t, NULL, 70771.151Skamil thread_and_exec_thread_cb, NULL) == 0); 70781.151Skamil 70791.151Skamil for (;;) 70801.151Skamil continue; 70811.151Skamil 70821.151Skamil FORKEE_ASSERT(0 && "Not reached"); 70831.151Skamil } 70841.151Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 70851.151Skamil 70861.151Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 70871.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70881.151Skamil 70891.151Skamil validate_status_stopped(status, sigval); 70901.151Skamil 70911.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 70921.151Skamil SYSCALL_REQUIRE( 70931.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 70941.151Skamil 70951.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 70961.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 70971.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 70981.151Skamil info.psi_siginfo.si_errno); 70991.151Skamil 71001.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 71011.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71021.151Skamil 71031.151Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 71041.151Skamil memset(&event, 0, sizeof(event)); 71051.151Skamil event.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT; 71061.151Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 71071.151Skamil 71081.151Skamil DPRINTF("Before resuming the child process where it left off and " 71091.151Skamil "without signal to be sent\n"); 71101.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71111.151Skamil 71121.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71131.151Skamil "SIGTRAP\n", TWAIT_FNAME); 71141.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71151.151Skamil child); 71161.151Skamil 71171.151Skamil validate_status_stopped(status, SIGTRAP); 71181.151Skamil 71191.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 71201.151Skamil "child\n"); 71211.151Skamil SYSCALL_REQUIRE( 71221.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71231.151Skamil 71241.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71251.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 71261.151Skamil "si_errno=%#x\n", 71271.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71281.151Skamil info.psi_siginfo.si_errno); 71291.151Skamil 71301.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 71311.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 71321.151Skamil 71331.151Skamil SYSCALL_REQUIRE( 71341.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71351.151Skamil 71361.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 71371.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 71381.151Skamil 71391.151Skamil lid = state.pe_lwp; 71401.151Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 71411.151Skamil 71421.151Skamil DPRINTF("Before resuming the child process where it left off " 71431.151Skamil "and without signal to be sent\n"); 71441.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71451.151Skamil 71461.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71471.151Skamil "SIGTRAP\n", TWAIT_FNAME); 71481.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71491.151Skamil child); 71501.151Skamil 71511.151Skamil validate_status_stopped(status, SIGTRAP); 71521.151Skamil 71531.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 71541.151Skamil "child\n"); 71551.151Skamil SYSCALL_REQUIRE( 71561.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71571.151Skamil 71581.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71591.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 71601.151Skamil "si_errno=%#x\n", 71611.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71621.151Skamil info.psi_siginfo.si_errno); 71631.151Skamil 71641.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 71651.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 71661.151Skamil 71671.151Skamil SYSCALL_REQUIRE( 71681.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71691.151Skamil 71701.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 71711.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 71721.151Skamil 71731.151Skamil lid = state.pe_lwp; 71741.151Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 71751.151Skamil 71761.151Skamil DPRINTF("Before resuming the child process where it left off " 71771.151Skamil "and without signal to be sent\n"); 71781.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71791.151Skamil 71801.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71811.151Skamil "SIGTRAP\n", TWAIT_FNAME); 71821.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71831.151Skamil child); 71841.151Skamil 71851.151Skamil validate_status_stopped(status, SIGTRAP); 71861.151Skamil 71871.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 71881.151Skamil "child\n"); 71891.151Skamil SYSCALL_REQUIRE( 71901.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71911.151Skamil 71921.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 71931.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 71941.151Skamil "si_errno=%#x\n", 71951.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 71961.151Skamil info.psi_siginfo.si_errno); 71971.151Skamil 71981.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 71991.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 72001.151Skamil 72011.151Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 72021.151Skamil 72031.151Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 72041.151Skamil TWAIT_FNAME); 72051.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72061.151Skamil 72071.151Skamil validate_status_signaled(status, SIGKILL, 0); 72081.151Skamil 72091.151Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 72101.151Skamil TWAIT_FNAME); 72111.151Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 72121.151Skamil} 72131.151Skamil 72141.151SkamilATF_TC(threads_and_exec); 72151.151SkamilATF_TC_HEAD(threads_and_exec, tc) 72161.151Skamil{ 72171.151Skamil atf_tc_set_md_var(tc, "descr", 72181.151Skamil "Verify that multithreaded application on exec() will report " 72191.151Skamil "LWP_EXIT events"); 72201.151Skamil} 72211.151Skamil 72221.151SkamilATF_TC_BODY(threads_and_exec, tc) 72231.151Skamil{ 72241.151Skamil 72251.151Skamil threads_and_exec(); 72261.151Skamil} 72271.151Skamil 72281.151Skamil/// ---------------------------------------------------------------------------- 72291.151Skamil 72301.154SkamilATF_TC(suspend_no_deadlock); 72311.154SkamilATF_TC_HEAD(suspend_no_deadlock, tc) 72321.1Skamil{ 72331.1Skamil atf_tc_set_md_var(tc, "descr", 72341.1Skamil "Verify that the while the only thread within a process is " 72351.1Skamil "suspended, the whole process cannot be unstopped"); 72361.1Skamil} 72371.1Skamil 72381.154SkamilATF_TC_BODY(suspend_no_deadlock, tc) 72391.1Skamil{ 72401.1Skamil const int exitval = 5; 72411.1Skamil const int sigval = SIGSTOP; 72421.1Skamil pid_t child, wpid; 72431.1Skamil#if defined(TWAIT_HAVE_STATUS) 72441.1Skamil int status; 72451.1Skamil#endif 72461.1Skamil struct ptrace_siginfo psi; 72471.1Skamil 72481.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 72491.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 72501.1Skamil if (child == 0) { 72511.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 72521.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 72531.1Skamil 72541.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 72551.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 72561.1Skamil 72571.13Schristos DPRINTF("Before exiting of the child process\n"); 72581.1Skamil _exit(exitval); 72591.1Skamil } 72601.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 72611.1Skamil 72621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 72631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72641.1Skamil 72651.1Skamil validate_status_stopped(status, sigval); 72661.1Skamil 72671.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 72681.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 72691.1Skamil 72701.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 72711.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 72721.1Skamil 72731.13Schristos DPRINTF("Before resuming the child process where it left off and " 72741.1Skamil "without signal to be sent\n"); 72751.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 72761.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 72771.1Skamil 72781.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 72791.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 72801.1Skamil 72811.13Schristos DPRINTF("Before resuming the child process where it left off and " 72821.1Skamil "without signal to be sent\n"); 72831.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72841.1Skamil 72851.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 72861.1Skamil TWAIT_FNAME); 72871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72881.1Skamil 72891.1Skamil validate_status_exited(status, exitval); 72901.1Skamil 72911.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 72921.1Skamil TWAIT_FNAME); 72931.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 72941.1Skamil} 72951.1Skamil 72961.154Skamil/// ---------------------------------------------------------------------------- 72971.154Skamil 72981.155Skamilstatic pthread_barrier_t barrier1_resume; 72991.155Skamilstatic pthread_barrier_t barrier2_resume; 73001.154Skamil 73011.155Skamilstatic void * 73021.155Skamilresume_thread(void *arg) 73031.154Skamil{ 73041.154Skamil 73051.155Skamil raise(SIGUSR1); 73061.155Skamil 73071.155Skamil pthread_barrier_wait(&barrier1_resume); 73081.155Skamil 73091.155Skamil /* Debugger will suspend the process here */ 73101.155Skamil 73111.155Skamil pthread_barrier_wait(&barrier2_resume); 73121.154Skamil 73131.155Skamil raise(SIGUSR2); 73141.155Skamil 73151.155Skamil return infinite_thread(arg); 73161.154Skamil} 73171.154Skamil 73181.155SkamilATF_TC(resume); 73191.155SkamilATF_TC_HEAD(resume, tc) 73201.1Skamil{ 73211.1Skamil atf_tc_set_md_var(tc, "descr", 73221.1Skamil "Verify that a thread can be suspended by a debugger and later " 73231.1Skamil "resumed by the debugger"); 73241.1Skamil} 73251.1Skamil 73261.155SkamilATF_TC_BODY(resume, tc) 73271.1Skamil{ 73281.1Skamil const int sigval = SIGSTOP; 73291.1Skamil pid_t child, wpid; 73301.1Skamil#if defined(TWAIT_HAVE_STATUS) 73311.1Skamil int status; 73321.1Skamil#endif 73331.1Skamil lwpid_t lid; 73341.1Skamil struct ptrace_siginfo psi; 73351.155Skamil pthread_t t; 73361.1Skamil 73371.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 73381.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 73391.1Skamil if (child == 0) { 73401.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 73411.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 73421.1Skamil 73431.155Skamil pthread_barrier_init(&barrier1_resume, NULL, 2); 73441.155Skamil pthread_barrier_init(&barrier2_resume, NULL, 2); 73451.155Skamil 73461.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 73471.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 73481.1Skamil 73491.155Skamil DPRINTF("Before creating new thread in child\n"); 73501.155Skamil FORKEE_ASSERT(pthread_create(&t, NULL, resume_thread, NULL) == 0); 73511.1Skamil 73521.155Skamil pthread_barrier_wait(&barrier1_resume); 73531.1Skamil 73541.155Skamil pthread_barrier_wait(&barrier2_resume); 73551.1Skamil 73561.155Skamil infinite_thread(NULL); 73571.1Skamil } 73581.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 73591.1Skamil 73601.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 73611.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73621.1Skamil 73631.1Skamil validate_status_stopped(status, sigval); 73641.1Skamil 73651.13Schristos DPRINTF("Before resuming the child process where it left off and " 73661.1Skamil "without signal to be sent\n"); 73671.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73681.1Skamil 73691.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 73701.155Skamil "SIGUSR1\n", TWAIT_FNAME); 73711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73721.1Skamil 73731.155Skamil validate_status_stopped(status, SIGUSR1); 73741.1Skamil 73751.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 73761.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 73771.1Skamil 73781.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 73791.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 73801.1Skamil 73811.155Skamil lid = psi.psi_lwpid; 73821.1Skamil 73831.13Schristos DPRINTF("Before resuming the child process where it left off and " 73841.1Skamil "without signal to be sent\n"); 73851.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73861.1Skamil 73871.155Skamil DPRINTF("Before suspending the parent for 1 second, we expect no signals\n"); 73881.155Skamil SYSCALL_REQUIRE(sleep(1) == 0); 73891.155Skamil 73901.155Skamil#if defined(TWAIT_HAVE_OPTIONS) 73911.155Skamil DPRINTF("Before calling %s() for the child - expected no status\n", 73921.155Skamil TWAIT_FNAME); 73931.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, WNOHANG), 0); 73941.155Skamil#endif 73951.155Skamil 73961.155Skamil DPRINTF("Before resuming the child process where it left off and " 73971.155Skamil "without signal to be sent\n"); 73981.155Skamil SYSCALL_REQUIRE(ptrace(PT_STOP, child, NULL, 0) != -1); 73991.155Skamil 74001.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 74011.155Skamil "SIGSTOP\n", TWAIT_FNAME); 74021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74031.1Skamil 74041.155Skamil validate_status_stopped(status, SIGSTOP); 74051.1Skamil 74061.155Skamil DPRINTF("Before resuming LWP %d\n", lid); 74071.155Skamil SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, lid) != -1); 74081.155Skamil 74091.155Skamil DPRINTF("Before resuming the child process where it left off and " 74101.155Skamil "without signal to be sent\n"); 74111.155Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74121.1Skamil 74131.155Skamil DPRINTF("Before calling %s() for the child - expected stopped " 74141.155Skamil "SIGUSR2\n", TWAIT_FNAME); 74151.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74161.1Skamil 74171.155Skamil validate_status_stopped(status, SIGUSR2); 74181.1Skamil 74191.13Schristos DPRINTF("Before resuming the child process where it left off and " 74201.1Skamil "without signal to be sent\n"); 74211.155Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 74221.1Skamil 74231.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 74241.1Skamil TWAIT_FNAME); 74251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74261.1Skamil 74271.155Skamil validate_status_signaled(status, SIGKILL, 0); 74281.1Skamil 74291.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 74301.1Skamil TWAIT_FNAME); 74311.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74321.155Skamil} 74331.1Skamil 74341.155Skamil/// ---------------------------------------------------------------------------- 74351.1Skamil 74361.167Skamilstatic int test_syscall_caught; 74371.167Skamil 74381.167Skamilstatic void 74391.167Skamilsyscall_sighand(int arg) 74401.167Skamil{ 74411.167Skamil 74421.167Skamil DPRINTF("Caught a signal %d in process %d\n", arg, getpid()); 74431.167Skamil 74441.167Skamil FORKEE_ASSERT_EQ(arg, SIGINFO); 74451.167Skamil 74461.167Skamil ++test_syscall_caught; 74471.167Skamil 74481.167Skamil FORKEE_ASSERT_EQ(test_syscall_caught, 1); 74491.167Skamil} 74501.167Skamil 74511.166Skamilstatic void 74521.167Skamilsyscall_body(const char *op) 74531.1Skamil{ 74541.1Skamil const int exitval = 5; 74551.1Skamil const int sigval = SIGSTOP; 74561.1Skamil pid_t child, wpid; 74571.1Skamil#if defined(TWAIT_HAVE_STATUS) 74581.1Skamil int status; 74591.1Skamil#endif 74601.1Skamil struct ptrace_siginfo info; 74611.167Skamil 74621.1Skamil memset(&info, 0, sizeof(info)); 74631.1Skamil 74641.167Skamil#if defined(TWAIT_HAVE_STATUS) 74651.167Skamil if (strstr(op, "signal") != NULL) { 74661.167Skamil atf_tc_expect_fail("XXX: behavior under investigation"); 74671.167Skamil } 74681.167Skamil#endif 74691.167Skamil 74701.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 74711.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 74721.1Skamil if (child == 0) { 74731.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74741.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74751.1Skamil 74761.167Skamil signal(SIGINFO, syscall_sighand); 74771.167Skamil 74781.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 74791.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 74801.1Skamil 74811.1Skamil syscall(SYS_getpid); 74821.1Skamil 74831.167Skamil if (strstr(op, "signal") != NULL) { 74841.167Skamil FORKEE_ASSERT_EQ(test_syscall_caught, 1); 74851.167Skamil } 74861.167Skamil 74871.13Schristos DPRINTF("Before exiting of the child process\n"); 74881.1Skamil _exit(exitval); 74891.1Skamil } 74901.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74911.1Skamil 74921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74941.1Skamil 74951.1Skamil validate_status_stopped(status, sigval); 74961.1Skamil 74971.13Schristos DPRINTF("Before resuming the child process where it left off and " 74981.1Skamil "without signal to be sent\n"); 74991.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 75001.1Skamil 75011.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75031.1Skamil 75041.1Skamil validate_status_stopped(status, SIGTRAP); 75051.1Skamil 75061.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 75071.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 75081.1Skamil 75091.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 75101.173Skamil ATF_REQUIRE(info.psi_lwpid > 0); 75111.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 75121.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 75131.1Skamil 75141.167Skamil if (strstr(op, "killed") != NULL) { 75151.166Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 75161.166Skamil 75171.166Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75181.166Skamil TWAIT_REQUIRE_SUCCESS( 75191.166Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 75201.166Skamil 75211.166Skamil validate_status_signaled(status, SIGKILL, 0); 75221.166Skamil } else { 75231.167Skamil if (strstr(op, "signal") != NULL) { 75241.167Skamil DPRINTF("Before resuming the child %d and sending a " 75251.167Skamil "signal SIGINFO\n", child); 75261.167Skamil SYSCALL_REQUIRE( 75271.167Skamil ptrace(PT_CONTINUE, child, (void *)1, SIGINFO) 75281.167Skamil != -1); 75291.167Skamil } else if (strstr(op, "detach") != NULL) { 75301.167Skamil DPRINTF("Before detaching the child %d\n", child); 75311.167Skamil SYSCALL_REQUIRE( 75321.167Skamil ptrace(PT_DETACH, child, (void *)1, 0) != -1); 75331.167Skamil } else { 75341.167Skamil DPRINTF("Before resuming the child process where it " 75351.167Skamil "left off and without signal to be sent\n"); 75361.167Skamil SYSCALL_REQUIRE( 75371.167Skamil ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 75381.166Skamil 75391.167Skamil DPRINTF("Before calling %s() for the child\n", 75401.167Skamil TWAIT_FNAME); 75411.167Skamil TWAIT_REQUIRE_SUCCESS( 75421.167Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 75431.1Skamil 75441.167Skamil validate_status_stopped(status, SIGTRAP); 75451.1Skamil 75461.167Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO " 75471.167Skamil "for child\n"); 75481.167Skamil SYSCALL_REQUIRE( 75491.167Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 75501.167Skamil != -1); 75511.1Skamil 75521.167Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 75531.173Skamil ATF_REQUIRE(info.psi_lwpid > 0); 75541.167Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 75551.167Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 75561.1Skamil 75571.167Skamil DPRINTF("Before resuming the child process where it " 75581.167Skamil "left off and without signal to be sent\n"); 75591.167Skamil SYSCALL_REQUIRE( 75601.167Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 75611.167Skamil } 75621.1Skamil 75631.166Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75641.166Skamil TWAIT_REQUIRE_SUCCESS( 75651.166Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 75661.1Skamil 75671.166Skamil validate_status_exited(status, exitval); 75681.166Skamil } 75691.1Skamil 75701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75711.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75721.1Skamil} 75731.1Skamil 75741.167Skamil#define SYSCALL_TEST(name,op) \ 75751.166SkamilATF_TC(name); \ 75761.166SkamilATF_TC_HEAD(name, tc) \ 75771.166Skamil{ \ 75781.170Skamil atf_tc_set_md_var(tc, "timeout", "15"); \ 75791.166Skamil atf_tc_set_md_var(tc, "descr", \ 75801.166Skamil "Verify that getpid(2) can be traced with PT_SYSCALL %s", \ 75811.167Skamil #op ); \ 75821.166Skamil} \ 75831.166Skamil \ 75841.166SkamilATF_TC_BODY(name, tc) \ 75851.166Skamil{ \ 75861.166Skamil \ 75871.167Skamil syscall_body(op); \ 75881.166Skamil} 75891.166Skamil 75901.167SkamilSYSCALL_TEST(syscall, "") 75911.167SkamilSYSCALL_TEST(syscall_killed_on_sce, "and killed") 75921.167SkamilSYSCALL_TEST(syscall_signal_on_sce, "and signaled") 75931.167SkamilSYSCALL_TEST(syscall_detach_on_sce, "and detached") 75941.166Skamil 75951.164Skamil/// ---------------------------------------------------------------------------- 75961.164Skamil 75971.1SkamilATF_TC(syscallemu1); 75981.1SkamilATF_TC_HEAD(syscallemu1, tc) 75991.1Skamil{ 76001.1Skamil atf_tc_set_md_var(tc, "descr", 76011.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 76021.1Skamil} 76031.1Skamil 76041.1SkamilATF_TC_BODY(syscallemu1, tc) 76051.1Skamil{ 76061.1Skamil const int exitval = 5; 76071.1Skamil const int sigval = SIGSTOP; 76081.1Skamil pid_t child, wpid; 76091.1Skamil#if defined(TWAIT_HAVE_STATUS) 76101.1Skamil int status; 76111.1Skamil#endif 76121.1Skamil 76131.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 76141.6Skamil /* syscallemu does not work on sparc (32-bit) */ 76151.6Skamil atf_tc_expect_fail("PR kern/52166"); 76161.6Skamil#endif 76171.6Skamil 76181.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 76191.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 76201.1Skamil if (child == 0) { 76211.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 76221.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 76231.1Skamil 76241.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 76251.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 76261.1Skamil 76271.1Skamil syscall(SYS_exit, 100); 76281.1Skamil 76291.13Schristos DPRINTF("Before exiting of the child process\n"); 76301.1Skamil _exit(exitval); 76311.1Skamil } 76321.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 76331.1Skamil 76341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76361.1Skamil 76371.1Skamil validate_status_stopped(status, sigval); 76381.1Skamil 76391.13Schristos DPRINTF("Before resuming the child process where it left off and " 76401.1Skamil "without signal to be sent\n"); 76411.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 76421.1Skamil 76431.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76441.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76451.1Skamil 76461.1Skamil validate_status_stopped(status, SIGTRAP); 76471.1Skamil 76481.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 76491.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 76501.1Skamil 76511.13Schristos DPRINTF("Before resuming the child process where it left off and " 76521.1Skamil "without signal to be sent\n"); 76531.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 76541.1Skamil 76551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76571.1Skamil 76581.1Skamil validate_status_stopped(status, SIGTRAP); 76591.1Skamil 76601.13Schristos DPRINTF("Before resuming the child process where it left off and " 76611.1Skamil "without signal to be sent\n"); 76621.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 76631.1Skamil 76641.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76651.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76661.1Skamil 76671.1Skamil validate_status_exited(status, exitval); 76681.1Skamil 76691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76701.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76711.1Skamil} 76721.1Skamil 76731.103Skamil/// ---------------------------------------------------------------------------- 76741.103Skamil 76751.106Skamilstatic void 76761.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 76771.106Skamil bool trackvforkdone) 76781.106Skamil{ 76791.106Skamil const int exitval = 5; 76801.106Skamil const int exitval2 = 15; 76811.106Skamil const int sigval = SIGSTOP; 76821.106Skamil pid_t child, child2 = 0, wpid; 76831.106Skamil#if defined(TWAIT_HAVE_STATUS) 76841.106Skamil int status; 76851.106Skamil#endif 76861.106Skamil ptrace_state_t state; 76871.106Skamil const int slen = sizeof(state); 76881.106Skamil ptrace_event_t event; 76891.106Skamil const int elen = sizeof(event); 76901.106Skamil 76911.106Skamil const size_t stack_size = 1024 * 1024; 76921.106Skamil void *stack, *stack_base; 76931.106Skamil 76941.106Skamil stack = malloc(stack_size); 76951.106Skamil ATF_REQUIRE(stack != NULL); 76961.106Skamil 76971.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 76981.106Skamil stack_base = stack; 76991.106Skamil#else 77001.106Skamil stack_base = (char *)stack + stack_size; 77011.106Skamil#endif 77021.106Skamil 77031.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 77041.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 77051.106Skamil if (child == 0) { 77061.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 77071.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 77081.106Skamil 77091.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 77101.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 77111.106Skamil 77121.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 77131.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 77141.106Skamil 77151.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 77161.106Skamil child2); 77171.106Skamil 77181.106Skamil // XXX WALLSIG? 77191.106Skamil FORKEE_REQUIRE_SUCCESS 77201.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 77211.106Skamil 77221.106Skamil forkee_status_exited(status, exitval2); 77231.106Skamil 77241.106Skamil DPRINTF("Before exiting of the child process\n"); 77251.106Skamil _exit(exitval); 77261.106Skamil } 77271.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 77281.106Skamil 77291.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77301.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77311.106Skamil 77321.106Skamil validate_status_stopped(status, sigval); 77331.106Skamil 77341.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 77351.106Skamil trackfork ? "|PTRACE_FORK" : "", 77361.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 77371.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 77381.106Skamil event.pe_set_event = 0; 77391.106Skamil if (trackfork) 77401.106Skamil event.pe_set_event |= PTRACE_FORK; 77411.106Skamil if (trackvfork) 77421.106Skamil event.pe_set_event |= PTRACE_VFORK; 77431.106Skamil if (trackvforkdone) 77441.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 77451.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 77461.106Skamil 77471.106Skamil DPRINTF("Before resuming the child process where it left off and " 77481.106Skamil "without signal to be sent\n"); 77491.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 77501.106Skamil 77511.106Skamil#if defined(TWAIT_HAVE_PID) 77521.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 77531.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 77541.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 77551.106Skamil child); 77561.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 77571.106Skamil child); 77581.106Skamil 77591.106Skamil validate_status_stopped(status, SIGTRAP); 77601.106Skamil 77611.106Skamil SYSCALL_REQUIRE( 77621.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 77631.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 77641.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 77651.106Skamil PTRACE_FORK); 77661.106Skamil } 77671.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 77681.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 77691.106Skamil PTRACE_VFORK); 77701.106Skamil } 77711.106Skamil 77721.106Skamil child2 = state.pe_other_pid; 77731.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 77741.106Skamil 77751.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 77761.106Skamil "%d\n", TWAIT_FNAME, child2, child); 77771.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 77781.106Skamil child2); 77791.106Skamil 77801.106Skamil validate_status_stopped(status, SIGTRAP); 77811.106Skamil 77821.106Skamil SYSCALL_REQUIRE( 77831.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 77841.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 77851.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 77861.106Skamil PTRACE_FORK); 77871.106Skamil } 77881.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 77891.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 77901.106Skamil PTRACE_VFORK); 77911.106Skamil } 77921.106Skamil 77931.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 77941.106Skamil 77951.106Skamil DPRINTF("Before resuming the forkee process where it left off " 77961.106Skamil "and without signal to be sent\n"); 77971.106Skamil SYSCALL_REQUIRE( 77981.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 77991.106Skamil 78001.106Skamil DPRINTF("Before resuming the child process where it left off " 78011.106Skamil "and without signal to be sent\n"); 78021.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78031.106Skamil } 78041.106Skamil#endif 78051.106Skamil 78061.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 78071.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 78081.106Skamil child); 78091.106Skamil TWAIT_REQUIRE_SUCCESS( 78101.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 78111.106Skamil 78121.106Skamil validate_status_stopped(status, SIGTRAP); 78131.106Skamil 78141.106Skamil SYSCALL_REQUIRE( 78151.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 78161.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 78171.106Skamil 78181.106Skamil child2 = state.pe_other_pid; 78191.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 78201.106Skamil child2); 78211.106Skamil 78221.106Skamil DPRINTF("Before resuming the child process where it left off " 78231.106Skamil "and without signal to be sent\n"); 78241.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78251.106Skamil } 78261.106Skamil 78271.103Skamil#if defined(TWAIT_HAVE_PID) 78281.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 78291.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 78301.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 78311.106Skamil "\n", TWAIT_FNAME); 78321.106Skamil TWAIT_REQUIRE_SUCCESS( 78331.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 78341.106Skamil 78351.106Skamil validate_status_exited(status, exitval2); 78361.106Skamil 78371.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 78381.106Skamil "process\n", TWAIT_FNAME); 78391.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 78401.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 78411.106Skamil } 78421.106Skamil#endif 78431.106Skamil 78441.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 78451.106Skamil "SIGCHLD\n", TWAIT_FNAME); 78461.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 78471.106Skamil 78481.106Skamil validate_status_stopped(status, SIGCHLD); 78491.106Skamil 78501.106Skamil DPRINTF("Before resuming the child process where it left off and " 78511.106Skamil "without signal to be sent\n"); 78521.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78531.106Skamil 78541.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 78551.106Skamil TWAIT_FNAME); 78561.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 78571.106Skamil 78581.106Skamil validate_status_exited(status, exitval); 78591.103Skamil 78601.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 78611.106Skamil TWAIT_FNAME); 78621.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 78631.106Skamil} 78641.103Skamil 78651.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 78661.106SkamilATF_TC(name); \ 78671.106SkamilATF_TC_HEAD(name, tc) \ 78681.106Skamil{ \ 78691.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 78701.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 78711.106Skamil #flags, \ 78721.106Skamil tfork ? "|PTRACE_FORK" : "", \ 78731.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 78741.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 78751.106Skamil} \ 78761.106Skamil \ 78771.106SkamilATF_TC_BODY(name, tc) \ 78781.106Skamil{ \ 78791.106Skamil \ 78801.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 78811.103Skamil} 78821.103Skamil 78831.106SkamilCLONE_TEST(clone1, 0, false, false, false) 78841.106Skamil#if defined(TWAIT_HAVE_PID) 78851.106SkamilCLONE_TEST(clone2, 0, true, false, false) 78861.106SkamilCLONE_TEST(clone3, 0, false, true, false) 78871.106SkamilCLONE_TEST(clone4, 0, true, true, false) 78881.106Skamil#endif 78891.106SkamilCLONE_TEST(clone5, 0, false, false, true) 78901.106Skamil#if defined(TWAIT_HAVE_PID) 78911.106SkamilCLONE_TEST(clone6, 0, true, false, true) 78921.106SkamilCLONE_TEST(clone7, 0, false, true, true) 78931.106SkamilCLONE_TEST(clone8, 0, true, true, true) 78941.106Skamil#endif 78951.106Skamil 78961.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 78971.106Skamil#if defined(TWAIT_HAVE_PID) 78981.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 78991.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 79001.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 79011.106Skamil#endif 79021.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 79031.106Skamil#if defined(TWAIT_HAVE_PID) 79041.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 79051.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 79061.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 79071.106Skamil#endif 79081.106Skamil 79091.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 79101.106Skamil#if defined(TWAIT_HAVE_PID) 79111.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 79121.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 79131.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 79141.106Skamil#endif 79151.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 79161.106Skamil#if defined(TWAIT_HAVE_PID) 79171.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 79181.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 79191.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 79201.106Skamil#endif 79211.106Skamil 79221.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 79231.106Skamil#if defined(TWAIT_HAVE_PID) 79241.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 79251.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 79261.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 79271.106Skamil#endif 79281.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 79291.106Skamil#if defined(TWAIT_HAVE_PID) 79301.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 79311.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 79321.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 79331.106Skamil#endif 79341.106Skamil 79351.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 79361.106Skamil#if defined(TWAIT_HAVE_PID) 79371.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 79381.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 79391.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 79401.106Skamil#endif 79411.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 79421.106Skamil#if defined(TWAIT_HAVE_PID) 79431.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 79441.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 79451.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 79461.106Skamil#endif 79471.106Skamil 79481.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 79491.106Skamil#if defined(TWAIT_HAVE_PID) 79501.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 79511.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 79521.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 79531.106Skamil#endif 79541.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 79551.106Skamil#if defined(TWAIT_HAVE_PID) 79561.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 79571.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 79581.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 79591.106Skamil#endif 79601.106Skamil 79611.106Skamil/// ---------------------------------------------------------------------------- 79621.106Skamil 79631.106Skamil#if defined(TWAIT_HAVE_PID) 79641.103Skamilstatic void 79651.106Skamilclone_body2(int flags, bool masked, bool ignored) 79661.103Skamil{ 79671.103Skamil const int exitval = 5; 79681.103Skamil const int exitval2 = 15; 79691.103Skamil const int sigval = SIGSTOP; 79701.103Skamil pid_t child, child2 = 0, wpid; 79711.103Skamil#if defined(TWAIT_HAVE_STATUS) 79721.103Skamil int status; 79731.103Skamil#endif 79741.103Skamil ptrace_state_t state; 79751.103Skamil const int slen = sizeof(state); 79761.103Skamil ptrace_event_t event; 79771.103Skamil const int elen = sizeof(event); 79781.103Skamil struct sigaction sa; 79791.103Skamil struct ptrace_siginfo info; 79801.103Skamil sigset_t intmask; 79811.103Skamil struct kinfo_proc2 kp; 79821.103Skamil size_t len = sizeof(kp); 79831.103Skamil 79841.103Skamil int name[6]; 79851.103Skamil const size_t namelen = __arraycount(name); 79861.103Skamil ki_sigset_t kp_sigmask; 79871.103Skamil ki_sigset_t kp_sigignore; 79881.103Skamil 79891.103Skamil const size_t stack_size = 1024 * 1024; 79901.103Skamil void *stack, *stack_base; 79911.103Skamil 79921.103Skamil stack = malloc(stack_size); 79931.103Skamil ATF_REQUIRE(stack != NULL); 79941.103Skamil 79951.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 79961.103Skamil stack_base = stack; 79971.103Skamil#else 79981.103Skamil stack_base = (char *)stack + stack_size; 79991.103Skamil#endif 80001.103Skamil 80011.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 80021.103Skamil if (child == 0) { 80031.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 80041.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 80051.103Skamil 80061.103Skamil if (masked) { 80071.103Skamil sigemptyset(&intmask); 80081.103Skamil sigaddset(&intmask, SIGTRAP); 80091.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 80101.103Skamil } 80111.103Skamil 80121.103Skamil if (ignored) { 80131.103Skamil memset(&sa, 0, sizeof(sa)); 80141.103Skamil sa.sa_handler = SIG_IGN; 80151.103Skamil sigemptyset(&sa.sa_mask); 80161.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 80171.103Skamil } 80181.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 80191.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 80201.103Skamil 80211.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 80221.103Skamil flags); 80231.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 80241.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 80251.103Skamil 80261.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 80271.103Skamil child2); 80281.103Skamil 80291.103Skamil // XXX WALLSIG? 80301.103Skamil FORKEE_REQUIRE_SUCCESS 80311.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 80321.103Skamil 80331.103Skamil forkee_status_exited(status, exitval2); 80341.103Skamil 80351.103Skamil DPRINTF("Before exiting of the child process\n"); 80361.103Skamil _exit(exitval); 80371.103Skamil } 80381.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 80391.103Skamil 80401.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 80411.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 80421.103Skamil 80431.103Skamil validate_status_stopped(status, sigval); 80441.103Skamil 80451.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 80461.103Skamil SYSCALL_REQUIRE( 80471.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 80481.103Skamil 80491.103Skamil DPRINTF("Before checking siginfo_t\n"); 80501.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 80511.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 80521.103Skamil 80531.103Skamil name[0] = CTL_KERN, 80541.103Skamil name[1] = KERN_PROC2, 80551.103Skamil name[2] = KERN_PROC_PID; 80561.103Skamil name[3] = child; 80571.103Skamil name[4] = sizeof(kp); 80581.103Skamil name[5] = 1; 80591.103Skamil 80601.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 80611.103Skamil 80621.103Skamil if (masked) 80631.103Skamil kp_sigmask = kp.p_sigmask; 80641.103Skamil 80651.103Skamil if (ignored) 80661.103Skamil kp_sigignore = kp.p_sigignore; 80671.103Skamil 80681.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 80691.103Skamil "EVENT_MASK for the child %d\n", child); 80701.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 80711.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 80721.103Skamil 80731.103Skamil DPRINTF("Before resuming the child process where it left off and " 80741.103Skamil "without signal to be sent\n"); 80751.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 80761.103Skamil 80771.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 80781.103Skamil child); 80791.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 80801.103Skamil child); 80811.103Skamil 80821.103Skamil validate_status_stopped(status, SIGTRAP); 80831.103Skamil 80841.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 80851.103Skamil 80861.103Skamil if (masked) { 80871.103Skamil DPRINTF("kp_sigmask=" 80881.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 80891.103Skamil PRIx32 "\n", 80901.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 80911.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 80921.103Skamil 80931.103Skamil DPRINTF("kp.p_sigmask=" 80941.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 80951.103Skamil PRIx32 "\n", 80961.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 80971.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 80981.103Skamil 80991.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 81001.103Skamil sizeof(kp_sigmask))); 81011.103Skamil } 81021.103Skamil 81031.103Skamil if (ignored) { 81041.103Skamil DPRINTF("kp_sigignore=" 81051.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81061.103Skamil PRIx32 "\n", 81071.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 81081.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 81091.103Skamil 81101.103Skamil DPRINTF("kp.p_sigignore=" 81111.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81121.103Skamil PRIx32 "\n", 81131.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 81141.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 81151.103Skamil 81161.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 81171.103Skamil sizeof(kp_sigignore))); 81181.103Skamil } 81191.103Skamil 81201.103Skamil SYSCALL_REQUIRE( 81211.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 81221.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 81231.103Skamil child2); 81241.103Skamil if (!(flags & CLONE_VFORK)) { 81251.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 81261.103Skamil PTRACE_FORK); 81271.103Skamil } else { 81281.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 81291.103Skamil PTRACE_VFORK); 81301.103Skamil } 81311.103Skamil 81321.103Skamil child2 = state.pe_other_pid; 81331.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 81341.103Skamil 81351.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 81361.103Skamil "%d\n", TWAIT_FNAME, child2, child); 81371.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 81381.103Skamil child2); 81391.103Skamil 81401.103Skamil validate_status_stopped(status, SIGTRAP); 81411.103Skamil 81421.103Skamil name[3] = child2; 81431.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 81441.103Skamil 81451.103Skamil if (masked) { 81461.103Skamil DPRINTF("kp_sigmask=" 81471.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81481.103Skamil PRIx32 "\n", 81491.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 81501.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 81511.103Skamil 81521.103Skamil DPRINTF("kp.p_sigmask=" 81531.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81541.103Skamil PRIx32 "\n", 81551.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 81561.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 81571.103Skamil 81581.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 81591.103Skamil sizeof(kp_sigmask))); 81601.103Skamil } 81611.103Skamil 81621.103Skamil if (ignored) { 81631.103Skamil DPRINTF("kp_sigignore=" 81641.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81651.103Skamil PRIx32 "\n", 81661.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 81671.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 81681.103Skamil 81691.103Skamil DPRINTF("kp.p_sigignore=" 81701.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 81711.103Skamil PRIx32 "\n", 81721.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 81731.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 81741.103Skamil 81751.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 81761.103Skamil sizeof(kp_sigignore))); 81771.103Skamil } 81781.103Skamil 81791.103Skamil SYSCALL_REQUIRE( 81801.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 81811.103Skamil if (!(flags & CLONE_VFORK)) { 81821.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 81831.103Skamil PTRACE_FORK); 81841.103Skamil } else { 81851.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 81861.103Skamil PTRACE_VFORK); 81871.103Skamil } 81881.103Skamil 81891.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 81901.103Skamil 81911.103Skamil DPRINTF("Before resuming the forkee process where it left off " 81921.103Skamil "and without signal to be sent\n"); 81931.103Skamil SYSCALL_REQUIRE( 81941.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 81951.103Skamil 81961.103Skamil DPRINTF("Before resuming the child process where it left off " 81971.103Skamil "and without signal to be sent\n"); 81981.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 81991.103Skamil 82001.103Skamil if (flags & CLONE_VFORK) { 82011.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 82021.103Skamil child); 82031.103Skamil TWAIT_REQUIRE_SUCCESS( 82041.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 82051.103Skamil 82061.103Skamil validate_status_stopped(status, SIGTRAP); 82071.103Skamil 82081.103Skamil name[3] = child; 82091.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 82101.103Skamil 82111.103Skamil /* 82121.103Skamil * SIGCHLD is now pending in the signal queue and 82131.103Skamil * the kernel presents it to userland as a masked signal. 82141.103Skamil */ 82151.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 82161.103Skamil 82171.103Skamil if (masked) { 82181.103Skamil DPRINTF("kp_sigmask=" 82191.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 82201.103Skamil PRIx32 "\n", 82211.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 82221.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 82231.103Skamil 82241.103Skamil DPRINTF("kp.p_sigmask=" 82251.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 82261.103Skamil PRIx32 "\n", 82271.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 82281.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 82291.103Skamil 82301.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 82311.103Skamil sizeof(kp_sigmask))); 82321.103Skamil } 82331.103Skamil 82341.103Skamil if (ignored) { 82351.103Skamil DPRINTF("kp_sigignore=" 82361.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 82371.103Skamil PRIx32 "\n", 82381.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 82391.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 82401.103Skamil 82411.103Skamil DPRINTF("kp.p_sigignore=" 82421.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 82431.103Skamil PRIx32 "\n", 82441.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 82451.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 82461.103Skamil 82471.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 82481.103Skamil sizeof(kp_sigignore))); 82491.103Skamil } 82501.103Skamil 82511.103Skamil SYSCALL_REQUIRE( 82521.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 82531.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 82541.103Skamil 82551.103Skamil child2 = state.pe_other_pid; 82561.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 82571.103Skamil child2); 82581.103Skamil 82591.103Skamil DPRINTF("Before resuming the child process where it left off " 82601.103Skamil "and without signal to be sent\n"); 82611.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 82621.103Skamil } 82631.103Skamil 82641.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 82651.103Skamil "\n", TWAIT_FNAME); 82661.103Skamil TWAIT_REQUIRE_SUCCESS( 82671.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 82681.103Skamil 82691.103Skamil validate_status_exited(status, exitval2); 82701.103Skamil 82711.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 82721.103Skamil "process\n", TWAIT_FNAME); 82731.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 82741.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 82751.103Skamil 82761.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 82771.103Skamil "SIGCHLD\n", TWAIT_FNAME); 82781.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 82791.103Skamil 82801.103Skamil validate_status_stopped(status, SIGCHLD); 82811.103Skamil 82821.103Skamil DPRINTF("Before resuming the child process where it left off and " 82831.103Skamil "without signal to be sent\n"); 82841.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 82851.103Skamil 82861.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 82871.103Skamil TWAIT_FNAME); 82881.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 82891.103Skamil 82901.103Skamil validate_status_exited(status, exitval); 82911.103Skamil 82921.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 82931.103Skamil TWAIT_FNAME); 82941.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 82951.103Skamil} 82961.103Skamil 82971.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 82981.103SkamilATF_TC(name); \ 82991.103SkamilATF_TC_HEAD(name, tc) \ 83001.103Skamil{ \ 83011.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 83021.103Skamil " regardless of signal %s%s", \ 83031.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 83041.103Skamil} \ 83051.103Skamil \ 83061.103SkamilATF_TC_BODY(name, tc) \ 83071.103Skamil{ \ 83081.103Skamil \ 83091.106Skamil clone_body2(flags, masked, ignored); \ 83101.103Skamil} 83111.103Skamil 83121.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 83131.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 83141.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 83151.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 83161.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 83171.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 83181.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 83191.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 83201.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 83211.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 83221.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 83231.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 83241.103Skamil#endif 83251.103Skamil 83261.103Skamil/// ---------------------------------------------------------------------------- 83271.103Skamil 83281.107Skamil#if defined(TWAIT_HAVE_PID) 83291.107Skamilstatic void 83301.107Skamiltraceme_vfork_clone_body(int flags) 83311.107Skamil{ 83321.107Skamil const int exitval = 5; 83331.107Skamil const int exitval2 = 15; 83341.107Skamil pid_t child, child2 = 0, wpid; 83351.107Skamil#if defined(TWAIT_HAVE_STATUS) 83361.107Skamil int status; 83371.107Skamil#endif 83381.107Skamil 83391.107Skamil const size_t stack_size = 1024 * 1024; 83401.107Skamil void *stack, *stack_base; 83411.107Skamil 83421.107Skamil stack = malloc(stack_size); 83431.107Skamil ATF_REQUIRE(stack != NULL); 83441.107Skamil 83451.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 83461.107Skamil stack_base = stack; 83471.107Skamil#else 83481.107Skamil stack_base = (char *)stack + stack_size; 83491.107Skamil#endif 83501.107Skamil 83511.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 83521.107Skamil if (child == 0) { 83531.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 83541.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 83551.107Skamil 83561.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 83571.107Skamil flags); 83581.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 83591.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 83601.107Skamil 83611.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 83621.107Skamil child2); 83631.107Skamil 83641.107Skamil // XXX WALLSIG? 83651.107Skamil FORKEE_REQUIRE_SUCCESS 83661.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 83671.107Skamil 83681.107Skamil forkee_status_exited(status, exitval2); 83691.107Skamil 83701.107Skamil DPRINTF("Before exiting of the child process\n"); 83711.107Skamil _exit(exitval); 83721.107Skamil } 83731.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 83741.107Skamil 83751.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 83761.107Skamil TWAIT_FNAME); 83771.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 83781.107Skamil 83791.107Skamil validate_status_exited(status, exitval); 83801.107Skamil 83811.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 83821.107Skamil TWAIT_FNAME); 83831.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 83841.107Skamil} 83851.107Skamil 83861.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 83871.107SkamilATF_TC(name); \ 83881.107SkamilATF_TC_HEAD(name, tc) \ 83891.107Skamil{ \ 83901.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 83911.107Skamil "handled correctly with vfork(2)ed tracer", \ 83921.107Skamil #flags); \ 83931.107Skamil} \ 83941.107Skamil \ 83951.107SkamilATF_TC_BODY(name, tc) \ 83961.107Skamil{ \ 83971.107Skamil \ 83981.107Skamil traceme_vfork_clone_body(flags); \ 83991.107Skamil} 84001.107Skamil 84011.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 84021.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 84031.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 84041.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 84051.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 84061.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 84071.107Skamil#endif 84081.107Skamil 84091.107Skamil/// ---------------------------------------------------------------------------- 84101.107Skamil 84111.122Skamilstatic void 84121.122Skamiluser_va0_disable(int operation) 84131.122Skamil{ 84141.122Skamil pid_t child, wpid; 84151.122Skamil#if defined(TWAIT_HAVE_STATUS) 84161.122Skamil int status; 84171.122Skamil#endif 84181.122Skamil const int sigval = SIGSTOP; 84191.122Skamil int rv; 84201.122Skamil 84211.122Skamil struct ptrace_siginfo info; 84221.122Skamil 84231.122Skamil if (get_user_va0_disable() == 0) 84241.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 84251.122Skamil 84261.122Skamil memset(&info, 0, sizeof(info)); 84271.122Skamil 84281.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 84291.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 84301.122Skamil if (child == 0) { 84311.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 84321.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 84331.122Skamil 84341.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 84351.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 84361.122Skamil 84371.122Skamil /* NOTREACHED */ 84381.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 84391.122Skamil __unreachable(); 84401.122Skamil } 84411.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 84421.122Skamil 84431.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 84441.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 84451.122Skamil 84461.122Skamil validate_status_stopped(status, sigval); 84471.122Skamil 84481.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 84491.122Skamil "child\n"); 84501.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 84511.122Skamil sizeof(info)) != -1); 84521.122Skamil 84531.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 84541.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 84551.122Skamil "si_errno=%#x\n", 84561.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 84571.122Skamil info.psi_siginfo.si_errno); 84581.122Skamil 84591.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 84601.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 84611.122Skamil 84621.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 84631.122Skamil "and without signal to be sent\n"); 84641.122Skamil errno = 0; 84651.122Skamil rv = ptrace(operation, child, (void *)0, 0); 84661.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 84671.122Skamil ATF_REQUIRE_EQ(rv, -1); 84681.122Skamil 84691.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 84701.122Skamil 84711.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 84721.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 84731.122Skamil validate_status_signaled(status, SIGKILL, 0); 84741.122Skamil 84751.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 84761.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 84771.122Skamil} 84781.122Skamil 84791.122Skamil#define USER_VA0_DISABLE(test, operation) \ 84801.122SkamilATF_TC(test); \ 84811.122SkamilATF_TC_HEAD(test, tc) \ 84821.122Skamil{ \ 84831.122Skamil atf_tc_set_md_var(tc, "descr", \ 84841.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 84851.122Skamil} \ 84861.122Skamil \ 84871.122SkamilATF_TC_BODY(test, tc) \ 84881.122Skamil{ \ 84891.122Skamil \ 84901.122Skamil user_va0_disable(operation); \ 84911.122Skamil} 84921.122Skamil 84931.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 84941.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 84951.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 84961.122Skamil 84971.122Skamil/// ---------------------------------------------------------------------------- 84981.122Skamil 84991.130Smgorny/* 85001.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 85011.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 85021.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 85031.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 85041.130Smgorny * found, -1 is returned. 85051.172Sthorpej * 85061.172Sthorpej * If the note_name ends in '*', then we find the first note that matches 85071.172Sthorpej * the note_name prefix up to the '*' character, e.g.: 85081.172Sthorpej * 85091.172Sthorpej * NetBSD-CORE@* 85101.172Sthorpej * 85111.172Sthorpej * finds the first note whose name prefix matches "NetBSD-CORE@". 85121.130Smgorny */ 85131.130Smgornystatic ssize_t core_find_note(const char *core_path, 85141.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 85151.130Smgorny{ 85161.130Smgorny int core_fd; 85171.130Smgorny Elf *core_elf; 85181.130Smgorny size_t core_numhdr, i; 85191.130Smgorny ssize_t ret = -1; 85201.172Sthorpej size_t name_len = strlen(note_name); 85211.172Sthorpej bool prefix_match = false; 85221.172Sthorpej 85231.172Sthorpej if (note_name[name_len - 1] == '*') { 85241.172Sthorpej prefix_match = true; 85251.172Sthorpej name_len--; 85261.172Sthorpej } else { 85271.172Sthorpej /* note: we assume note name will be null-terminated */ 85281.172Sthorpej name_len++; 85291.172Sthorpej } 85301.130Smgorny 85311.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 85321.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 85331.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 85341.130Smgorny 85351.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 85361.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 85371.130Smgorny GElf_Phdr core_hdr; 85381.130Smgorny size_t offset; 85391.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 85401.130Smgorny if (core_hdr.p_type != PT_NOTE) 85411.130Smgorny continue; 85421.130Smgorny 85431.130Smgorny for (offset = core_hdr.p_offset; 85441.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 85451.130Smgorny Elf64_Nhdr note_hdr; 85461.130Smgorny char name_buf[64]; 85471.130Smgorny 85481.130Smgorny switch (gelf_getclass(core_elf)) { 85491.130Smgorny case ELFCLASS64: 85501.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 85511.130Smgorny sizeof(note_hdr), offset) 85521.130Smgorny == sizeof(note_hdr)); 85531.130Smgorny offset += sizeof(note_hdr); 85541.130Smgorny break; 85551.130Smgorny case ELFCLASS32: 85561.130Smgorny { 85571.130Smgorny Elf32_Nhdr tmp_hdr; 85581.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 85591.130Smgorny sizeof(tmp_hdr), offset) 85601.130Smgorny == sizeof(tmp_hdr)); 85611.130Smgorny offset += sizeof(tmp_hdr); 85621.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 85631.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 85641.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 85651.130Smgorny } 85661.130Smgorny break; 85671.130Smgorny } 85681.130Smgorny 85691.130Smgorny /* indicates end of notes */ 85701.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 85711.130Smgorny break; 85721.172Sthorpej if (((prefix_match && 85731.172Sthorpej note_hdr.n_namesz > name_len) || 85741.172Sthorpej (!prefix_match && 85751.172Sthorpej note_hdr.n_namesz == name_len)) && 85761.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 85771.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 85781.130Smgorny note_hdr.n_namesz, offset) 85791.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 85801.130Smgorny 85811.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 85821.130Smgorny note_hdr.n_type == note_type) 85831.130Smgorny ret = note_hdr.n_descsz; 85841.130Smgorny } 85851.130Smgorny 85861.130Smgorny offset += note_hdr.n_namesz; 85871.130Smgorny /* fix to alignment */ 85881.146Smgorny offset = roundup(offset, core_hdr.p_align); 85891.130Smgorny 85901.130Smgorny /* if name & type matched above */ 85911.130Smgorny if (ret != -1) { 85921.130Smgorny ssize_t read_len = MIN(buf_len, 85931.130Smgorny note_hdr.n_descsz); 85941.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 85951.130Smgorny read_len, offset) == read_len); 85961.130Smgorny break; 85971.130Smgorny } 85981.130Smgorny 85991.130Smgorny offset += note_hdr.n_descsz; 86001.146Smgorny /* fix to alignment */ 86011.146Smgorny offset = roundup(offset, core_hdr.p_align); 86021.130Smgorny } 86031.130Smgorny } 86041.130Smgorny 86051.130Smgorny elf_end(core_elf); 86061.130Smgorny close(core_fd); 86071.130Smgorny 86081.130Smgorny return ret; 86091.130Smgorny} 86101.130Smgorny 86111.130SmgornyATF_TC(core_dump_procinfo); 86121.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 86131.130Smgorny{ 86141.130Smgorny atf_tc_set_md_var(tc, "descr", 86151.130Smgorny "Trigger a core dump and verify its contents."); 86161.130Smgorny} 86171.130Smgorny 86181.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 86191.130Smgorny{ 86201.130Smgorny const int exitval = 5; 86211.130Smgorny pid_t child, wpid; 86221.130Smgorny#if defined(TWAIT_HAVE_STATUS) 86231.130Smgorny const int sigval = SIGTRAP; 86241.130Smgorny int status; 86251.130Smgorny#endif 86261.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 86271.130Smgorny int core_fd; 86281.130Smgorny struct netbsd_elfcore_procinfo procinfo; 86291.130Smgorny 86301.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 86311.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 86321.130Smgorny if (child == 0) { 86331.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 86341.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 86351.130Smgorny 86361.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 86371.130Smgorny trigger_trap(); 86381.130Smgorny 86391.130Smgorny DPRINTF("Before exiting of the child process\n"); 86401.130Smgorny _exit(exitval); 86411.130Smgorny } 86421.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 86431.130Smgorny 86441.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 86451.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 86461.130Smgorny 86471.130Smgorny validate_status_stopped(status, sigval); 86481.130Smgorny 86491.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 86501.130Smgorny close(core_fd); 86511.130Smgorny 86521.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 86531.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 86541.130Smgorny != -1); 86551.130Smgorny 86561.130Smgorny DPRINTF("Read core file\n"); 86571.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 86581.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 86591.130Smgorny sizeof(procinfo)); 86601.130Smgorny 86611.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 86621.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 86631.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 86641.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 86651.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 86661.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 86671.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 86681.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 86691.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 86701.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 86711.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 86721.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 86731.173Skamil ATF_CHECK(procinfo.cpi_siglwp > 0); 86741.130Smgorny 86751.130Smgorny unlink(core_path); 86761.130Smgorny 86771.130Smgorny DPRINTF("Before resuming the child process where it left off and " 86781.130Smgorny "without signal to be sent\n"); 86791.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 86801.130Smgorny 86811.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 86821.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 86831.130Smgorny 86841.130Smgorny validate_status_exited(status, exitval); 86851.130Smgorny 86861.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 86871.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 86881.130Smgorny} 86891.130Smgorny 86901.130Smgorny/// ---------------------------------------------------------------------------- 86911.130Smgorny 86921.138Smgorny#if defined(TWAIT_HAVE_STATUS) 86931.138Smgorny 86941.160Smgorny#define THREAD_CONCURRENT_BREAKPOINT_NUM 50 86951.156Smgorny#define THREAD_CONCURRENT_SIGNALS_NUM 50 86961.161Smgorny#define THREAD_CONCURRENT_WATCHPOINT_NUM 50 86971.138Smgorny 86981.138Smgorny/* List of signals to use for the test */ 86991.138Smgornyconst int thread_concurrent_signals_list[] = { 87001.138Smgorny SIGIO, 87011.138Smgorny SIGXCPU, 87021.138Smgorny SIGXFSZ, 87031.138Smgorny SIGVTALRM, 87041.138Smgorny SIGPROF, 87051.138Smgorny SIGWINCH, 87061.138Smgorny SIGINFO, 87071.138Smgorny SIGUSR1, 87081.138Smgorny SIGUSR2 87091.138Smgorny}; 87101.138Smgorny 87111.157Smgornyenum thread_concurrent_signal_handling { 87121.157Smgorny /* the signal is discarded by debugger */ 87131.157Smgorny TCSH_DISCARD, 87141.157Smgorny /* the handler is set to SIG_IGN */ 87151.157Smgorny TCSH_SIG_IGN, 87161.157Smgorny /* an actual handler is used */ 87171.157Smgorny TCSH_HANDLER 87181.157Smgorny}; 87191.157Smgorny 87201.156Smgornystatic pthread_barrier_t thread_concurrent_barrier; 87211.158Smgornystatic pthread_key_t thread_concurrent_key; 87221.161Smgornystatic uint32_t thread_concurrent_watchpoint_var = 0; 87231.138Smgorny 87241.160Smgornystatic void * 87251.160Smgornythread_concurrent_breakpoint_thread(void *arg) 87261.160Smgorny{ 87271.160Smgorny static volatile int watchme = 1; 87281.160Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 87291.160Smgorny DPRINTF("Before entering breakpoint func from LWP %d\n", _lwp_self()); 87301.160Smgorny check_happy(watchme); 87311.160Smgorny return NULL; 87321.160Smgorny} 87331.160Smgorny 87341.157Smgornystatic void 87351.157Smgornythread_concurrent_sig_handler(int sig) 87361.157Smgorny{ 87371.158Smgorny void *tls_val = pthread_getspecific(thread_concurrent_key); 87381.158Smgorny DPRINTF("Before increment, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 87391.158Smgorny FORKEE_ASSERT(pthread_setspecific(thread_concurrent_key, 87401.158Smgorny (void*)((uintptr_t)tls_val + 1)) == 0); 87411.157Smgorny} 87421.157Smgorny 87431.138Smgornystatic void * 87441.138Smgornythread_concurrent_signals_thread(void *arg) 87451.138Smgorny{ 87461.138Smgorny int sigval = thread_concurrent_signals_list[ 87471.138Smgorny _lwp_self() % __arraycount(thread_concurrent_signals_list)]; 87481.158Smgorny enum thread_concurrent_signal_handling *signal_handle = arg; 87491.158Smgorny void *tls_val; 87501.158Smgorny 87511.156Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 87521.138Smgorny DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval), 87531.138Smgorny _lwp_self()); 87541.138Smgorny pthread_kill(pthread_self(), sigval); 87551.158Smgorny if (*signal_handle == TCSH_HANDLER) { 87561.158Smgorny tls_val = pthread_getspecific(thread_concurrent_key); 87571.158Smgorny DPRINTF("After raising, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 87581.158Smgorny FORKEE_ASSERT(tls_val == (void*)1); 87591.158Smgorny } 87601.138Smgorny return NULL; 87611.138Smgorny} 87621.138Smgorny 87631.161Smgornystatic void * 87641.161Smgornythread_concurrent_watchpoint_thread(void *arg) 87651.161Smgorny{ 87661.161Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 87671.161Smgorny DPRINTF("Before modifying var from LWP %d\n", _lwp_self()); 87681.161Smgorny thread_concurrent_watchpoint_var = 1; 87691.161Smgorny return NULL; 87701.161Smgorny} 87711.161Smgorny 87721.160Smgorny#if defined(__i386__) || defined(__x86_64__) 87731.160Smgornyenum thread_concurrent_sigtrap_event { 87741.160Smgorny TCSE_UNKNOWN, 87751.161Smgorny TCSE_BREAKPOINT, 87761.161Smgorny TCSE_WATCHPOINT 87771.160Smgorny}; 87781.160Smgorny 87791.160Smgornystatic void 87801.160Smgornythread_concurrent_lwp_setup(pid_t child, lwpid_t lwpid); 87811.160Smgornystatic enum thread_concurrent_sigtrap_event 87821.160Smgornythread_concurrent_handle_sigtrap(pid_t child, ptrace_siginfo_t *info); 87831.160Smgorny#endif 87841.160Smgorny 87851.156Smgornystatic void 87861.157Smgornythread_concurrent_test(enum thread_concurrent_signal_handling signal_handle, 87871.161Smgorny int breakpoint_threads, int signal_threads, int watchpoint_threads) 87881.138Smgorny{ 87891.138Smgorny const int exitval = 5; 87901.138Smgorny const int sigval = SIGSTOP; 87911.138Smgorny pid_t child, wpid; 87921.138Smgorny int status; 87931.141Skamil struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM] 87941.141Skamil = {{0, 0}}; 87951.160Smgorny struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 87961.160Smgorny = {{0, 0}}; 87971.161Smgorny struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 87981.161Smgorny = {{0, 0}}; 87991.159Smgorny ptrace_event_t event; 88001.156Smgorny int i; 88011.156Smgorny 88021.164Skamil#if defined(HAVE_DBREGS) 88031.164Skamil if (!can_we_set_dbregs()) { 88041.164Skamil atf_tc_skip("Either run this test as root or set sysctl(3) " 88051.164Skamil "security.models.extensions.user_set_dbregs to 1"); 88061.164Skamil } 88071.164Skamil#endif 88081.164Skamil 88091.164Skamil atf_tc_skip("PR kern/54960"); 88101.157Smgorny 88111.156Smgorny /* Protect against out-of-bounds array access. */ 88121.160Smgorny ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM); 88131.156Smgorny ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM); 88141.161Smgorny ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM); 88151.138Smgorny 88161.138Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 88171.138Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 88181.138Smgorny if (child == 0) { 88191.160Smgorny pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM]; 88201.156Smgorny pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM]; 88211.161Smgorny pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM]; 88221.138Smgorny 88231.138Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 88241.138Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 88251.138Smgorny 88261.138Smgorny DPRINTF("Before raising %s from child\n", strsignal(sigval)); 88271.138Smgorny FORKEE_ASSERT(raise(sigval) == 0); 88281.138Smgorny 88291.157Smgorny if (signal_handle != TCSH_DISCARD) { 88301.157Smgorny struct sigaction sa; 88311.157Smgorny unsigned int j; 88321.157Smgorny 88331.157Smgorny memset(&sa, 0, sizeof(sa)); 88341.157Smgorny if (signal_handle == TCSH_SIG_IGN) 88351.157Smgorny sa.sa_handler = SIG_IGN; 88361.157Smgorny else 88371.157Smgorny sa.sa_handler = thread_concurrent_sig_handler; 88381.157Smgorny sigemptyset(&sa.sa_mask); 88391.157Smgorny 88401.157Smgorny for (j = 0; 88411.157Smgorny j < __arraycount(thread_concurrent_signals_list); 88421.157Smgorny j++) 88431.157Smgorny FORKEE_ASSERT(sigaction( 88441.157Smgorny thread_concurrent_signals_list[j], &sa, NULL) 88451.157Smgorny != -1); 88461.157Smgorny } 88471.157Smgorny 88481.138Smgorny DPRINTF("Before starting threads from the child\n"); 88491.138Smgorny FORKEE_ASSERT(pthread_barrier_init( 88501.156Smgorny &thread_concurrent_barrier, NULL, 88511.161Smgorny breakpoint_threads + signal_threads + watchpoint_threads) 88521.161Smgorny == 0); 88531.158Smgorny FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL) 88541.158Smgorny == 0); 88551.138Smgorny 88561.156Smgorny for (i = 0; i < signal_threads; i++) { 88571.156Smgorny FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL, 88581.158Smgorny thread_concurrent_signals_thread, 88591.158Smgorny &signal_handle) == 0); 88601.138Smgorny } 88611.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 88621.160Smgorny FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL, 88631.160Smgorny thread_concurrent_breakpoint_thread, NULL) == 0); 88641.160Smgorny } 88651.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 88661.161Smgorny FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL, 88671.161Smgorny thread_concurrent_watchpoint_thread, NULL) == 0); 88681.161Smgorny } 88691.138Smgorny 88701.138Smgorny DPRINTF("Before joining threads from the child\n"); 88711.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 88721.161Smgorny FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0); 88731.161Smgorny } 88741.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 88751.160Smgorny FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0); 88761.160Smgorny } 88771.156Smgorny for (i = 0; i < signal_threads; i++) { 88781.156Smgorny FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0); 88791.138Smgorny } 88801.138Smgorny 88811.158Smgorny FORKEE_ASSERT(pthread_key_delete(thread_concurrent_key) == 0); 88821.138Smgorny FORKEE_ASSERT(pthread_barrier_destroy( 88831.156Smgorny &thread_concurrent_barrier) == 0); 88841.138Smgorny 88851.138Smgorny DPRINTF("Before exiting of the child process\n"); 88861.138Smgorny _exit(exitval); 88871.138Smgorny } 88881.138Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 88891.138Smgorny 88901.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 88911.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 88921.138Smgorny 88931.138Smgorny validate_status_stopped(status, sigval); 88941.138Smgorny 88951.159Smgorny DPRINTF("Set LWP event mask for the child process\n"); 88961.159Smgorny memset(&event, 0, sizeof(event)); 88971.159Smgorny event.pe_set_event |= PTRACE_LWP_CREATE; 88981.159Smgorny SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event)) 88991.159Smgorny != -1); 89001.159Smgorny 89011.138Smgorny DPRINTF("Before resuming the child process where it left off\n"); 89021.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 89031.138Smgorny 89041.138Smgorny DPRINTF("Before entering signal collection loop\n"); 89051.138Smgorny while (1) { 89061.138Smgorny ptrace_siginfo_t info; 89071.138Smgorny 89081.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 89091.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 89101.138Smgorny child); 89111.138Smgorny if (WIFEXITED(status)) 89121.138Smgorny break; 89131.138Smgorny /* Note: we use validate_status_stopped() to get nice error 89141.138Smgorny * message. Signal is irrelevant since it won't be reached. 89151.138Smgorny */ 89161.138Smgorny else if (!WIFSTOPPED(status)) 89171.138Smgorny validate_status_stopped(status, 0); 89181.138Smgorny 89191.138Smgorny DPRINTF("Before calling PT_GET_SIGINFO\n"); 89201.138Smgorny SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 89211.138Smgorny sizeof(info)) != -1); 89221.138Smgorny 89231.138Smgorny DPRINTF("Received signal %d from LWP %d (wait: %d)\n", 89241.138Smgorny info.psi_siginfo.si_signo, info.psi_lwpid, 89251.138Smgorny WSTOPSIG(status)); 89261.138Smgorny 89271.159Smgorny ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status), 89281.159Smgorny "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid, 89291.159Smgorny WSTOPSIG(status), info.psi_siginfo.si_signo); 89301.159Smgorny 89311.159Smgorny if (WSTOPSIG(status) != SIGTRAP) { 89321.159Smgorny int expected_sig = 89331.159Smgorny thread_concurrent_signals_list[info.psi_lwpid % 89341.159Smgorny __arraycount(thread_concurrent_signals_list)]; 89351.159Smgorny ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig, 89361.159Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 89371.159Smgorny expected_sig, WSTOPSIG(status)); 89381.138Smgorny 89391.159Smgorny *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1; 89401.160Smgorny } else if (info.psi_siginfo.si_code == TRAP_LWP) { 89411.160Smgorny#if defined(__i386__) || defined(__x86_64__) 89421.160Smgorny thread_concurrent_lwp_setup(child, info.psi_lwpid); 89431.160Smgorny#endif 89441.159Smgorny } else { 89451.160Smgorny#if defined(__i386__) || defined(__x86_64__) 89461.160Smgorny switch (thread_concurrent_handle_sigtrap(child, &info)) { 89471.160Smgorny case TCSE_UNKNOWN: 89481.160Smgorny /* already reported inside the function */ 89491.160Smgorny break; 89501.160Smgorny case TCSE_BREAKPOINT: 89511.160Smgorny *FIND_EVENT_COUNT(bp_counts, 89521.160Smgorny info.psi_lwpid) += 1; 89531.160Smgorny break; 89541.161Smgorny case TCSE_WATCHPOINT: 89551.161Smgorny *FIND_EVENT_COUNT(wp_counts, 89561.161Smgorny info.psi_lwpid) += 1; 89571.161Smgorny break; 89581.160Smgorny } 89591.160Smgorny#else 89601.160Smgorny ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n", 89611.160Smgorny info.psi_siginfo.si_code); 89621.160Smgorny#endif 89631.159Smgorny } 89641.138Smgorny 89651.138Smgorny DPRINTF("Before resuming the child process\n"); 89661.157Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 89671.159Smgorny signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP 89681.159Smgorny ? WSTOPSIG(status) : 0) != -1); 89691.138Smgorny } 89701.138Smgorny 89711.156Smgorny for (i = 0; i < signal_threads; i++) 89721.141Skamil ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1, 89731.141Skamil "signal_counts[%d].lec_count=%d; lec_lwp=%d", 89741.141Skamil i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 89751.156Smgorny for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++) 89761.156Smgorny ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0, 89771.156Smgorny "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d", 89781.156Smgorny i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 89791.138Smgorny 89801.160Smgorny for (i = 0; i < breakpoint_threads; i++) 89811.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1, 89821.160Smgorny "bp_counts[%d].lec_count=%d; lec_lwp=%d", 89831.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 89841.160Smgorny for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++) 89851.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0, 89861.160Smgorny "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d", 89871.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 89881.160Smgorny 89891.161Smgorny for (i = 0; i < watchpoint_threads; i++) 89901.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1, 89911.161Smgorny "wp_counts[%d].lec_count=%d; lec_lwp=%d", 89921.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 89931.161Smgorny for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++) 89941.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0, 89951.161Smgorny "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d", 89961.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 89971.161Smgorny 89981.138Smgorny validate_status_exited(status, exitval); 89991.138Smgorny} 90001.138Smgorny 90011.161Smgorny#define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr) \ 90021.156SmgornyATF_TC(test); \ 90031.156SmgornyATF_TC_HEAD(test, tc) \ 90041.156Smgorny{ \ 90051.156Smgorny atf_tc_set_md_var(tc, "descr", descr); \ 90061.156Smgorny} \ 90071.156Smgorny \ 90081.156SmgornyATF_TC_BODY(test, tc) \ 90091.156Smgorny{ \ 90101.161Smgorny thread_concurrent_test(sig_hdl, bps, sigs, wps); \ 90111.156Smgorny} 90121.156Smgorny 90131.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD, 90141.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90151.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 90161.157Smgorny "correctly"); 90171.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN, 90181.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90191.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 90201.157Smgorny "correctly and passed back to SIG_IGN handler"); 90211.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER, 90221.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90231.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 90241.157Smgorny "correctly and passed back to a handler function"); 90251.156Smgorny 90261.163Skamil#if defined(__i386__) || defined(__x86_64__) 90271.160SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD, 90281.161Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0, 90291.161Smgorny "Verify that concurrent breakpoints are reported correctly"); 90301.161SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD, 90311.161Smgorny 0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 90321.160Smgorny "Verify that concurrent breakpoints are reported correctly"); 90331.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD, 90341.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 90351.162Smgorny "Verify that concurrent breakpoints and watchpoints are reported " 90361.162Smgorny "correctly"); 90371.162Smgorny 90381.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD, 90391.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90401.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly"); 90411.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN, 90421.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90431.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 90441.162Smgorny "and passed back to SIG_IGN handler"); 90451.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER, 90461.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 90471.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 90481.162Smgorny "and passed back to a handler function"); 90491.162Smgorny 90501.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD, 90511.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 90521.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly"); 90531.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN, 90541.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 90551.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 90561.162Smgorny "and passed back to SIG_IGN handler"); 90571.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER, 90581.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 90591.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 90601.162Smgorny "and passed back to a handler function"); 90611.162Smgorny 90621.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD, 90631.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 90641.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 90651.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90661.162Smgorny "correctly"); 90671.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN, 90681.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 90691.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 90701.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90711.162Smgorny "correctly and passed back to SIG_IGN handler"); 90721.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER, 90731.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 90741.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 90751.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 90761.162Smgorny "correctly and passed back to a handler function"); 90771.163Skamil#endif 90781.160Smgorny 90791.138Smgorny#endif /*defined(TWAIT_HAVE_STATUS)*/ 90801.138Smgorny 90811.138Smgorny/// ---------------------------------------------------------------------------- 90821.138Smgorny 90831.1Skamil#include "t_ptrace_amd64_wait.h" 90841.1Skamil#include "t_ptrace_i386_wait.h" 90851.1Skamil#include "t_ptrace_x86_wait.h" 90861.1Skamil 90871.165Skamil/// ---------------------------------------------------------------------------- 90881.165Skamil 90891.165Skamil#else 90901.165SkamilATF_TC(dummy); 90911.165SkamilATF_TC_HEAD(dummy, tc) 90921.165Skamil{ 90931.165Skamil atf_tc_set_md_var(tc, "descr", "A dummy test"); 90941.165Skamil} 90951.165Skamil 90961.165SkamilATF_TC_BODY(dummy, tc) 90971.165Skamil{ 90981.165Skamil 90991.165Skamil // Dummy, skipped 91001.165Skamil // The ATF framework requires at least a single defined test. 91011.165Skamil} 91021.165Skamil#endif 91031.165Skamil 91041.1SkamilATF_TP_ADD_TCS(tp) 91051.1Skamil{ 91061.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 91071.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 91081.33Skamil 91091.165Skamil#ifdef ENABLE_TESTS 91101.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 91111.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 91121.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 91131.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 91141.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 91151.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 91161.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 91171.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 91181.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 91191.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 91201.33Skamil 91211.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 91221.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 91231.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 91241.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 91251.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 91261.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 91271.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 91281.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 91291.87Skamil 91301.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 91311.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 91321.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 91331.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 91341.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 91351.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 91361.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 91371.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 91381.86Skamil 91391.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 91401.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 91411.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 91421.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 91431.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 91441.59Skamil 91451.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 91461.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 91471.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 91481.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 91491.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 91501.88Skamil 91511.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 91521.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 91531.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 91541.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 91551.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 91561.88Skamil 91571.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 91581.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 91591.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 91601.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 91611.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 91621.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 91631.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 91641.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 91651.50Skamil 91661.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 91671.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 91681.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 91691.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 91701.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 91711.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 91721.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 91731.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 91741.50Skamil 91751.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 91761.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 91771.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 91781.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 91791.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 91801.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 91811.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 91821.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 91831.50Skamil 91841.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 91851.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 91861.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 91871.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 91881.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 91891.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 91901.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 91911.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 91921.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 91931.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 91941.1Skamil 91951.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 91961.37Skamil 91971.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 91981.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 91991.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 92001.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 92011.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 92021.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 92031.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 92041.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 92051.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 92061.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 92071.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 92081.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 92091.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 92101.40Skamil 92111.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 92121.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 92131.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 92141.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 92151.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 92161.41Skamil 92171.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 92181.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 92191.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 92201.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 92211.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 92221.92Skamil 92231.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 92241.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 92251.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 92261.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 92271.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 92281.92Skamil 92291.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 92301.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 92311.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 92321.43Skamil 92331.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 92341.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 92351.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 92361.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 92371.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 92381.59Skamil 92391.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92401.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 92411.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92421.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 92431.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92441.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 92451.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92461.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 92471.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92481.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 92491.94Skamil 92501.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92511.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 92521.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92531.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 92541.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92551.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 92561.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92571.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 92581.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92591.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 92601.94Skamil 92611.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 92621.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 92631.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 92641.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 92651.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 92661.51Skamil 92671.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 92681.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 92691.51Skamil 92701.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 92711.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 92721.51Skamil 92731.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92741.51Skamil tracee_sees_its_original_parent_getppid); 92751.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92761.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 92771.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 92781.51Skamil tracee_sees_its_original_parent_procfs_status); 92791.1Skamil 92801.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 92811.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 92821.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 92831.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 92841.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 92851.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 92861.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 92871.1Skamil 92881.31Skamil ATF_TP_ADD_TC(tp, fork1); 92891.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 92901.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 92911.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 92921.31Skamil ATF_TP_ADD_TC(tp, fork5); 92931.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 92941.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 92951.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 92961.125Skamil ATF_TP_ADD_TC(tp, fork9); 92971.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 92981.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 92991.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 93001.125Skamil ATF_TP_ADD_TC(tp, fork13); 93011.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 93021.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 93031.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 93041.31Skamil 93051.31Skamil ATF_TP_ADD_TC(tp, vfork1); 93061.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 93071.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 93081.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 93091.31Skamil ATF_TP_ADD_TC(tp, vfork5); 93101.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 93111.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 93121.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 93131.125Skamil ATF_TP_ADD_TC(tp, vfork9); 93141.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 93151.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 93161.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 93171.125Skamil ATF_TP_ADD_TC(tp, vfork13); 93181.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 93191.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 93201.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 93211.1Skamil 93221.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 93231.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 93241.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 93251.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 93261.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 93271.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 93281.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 93291.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 93301.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 93311.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 93321.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 93331.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 93341.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 93351.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 93361.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 93371.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 93381.124Skamil 93391.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork1); 93401.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork2); 93411.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork3); 93421.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork4); 93431.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork5); 93441.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork6); 93451.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork7); 93461.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork8); 93471.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork9); 93481.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork10); 93491.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork11); 93501.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork12); 93511.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork13); 93521.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork14); 93531.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork15); 93541.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork16); 93551.149Skamil 93561.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork1); 93571.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork2); 93581.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork3); 93591.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork4); 93601.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork5); 93611.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork6); 93621.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork7); 93631.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork8); 93641.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork9); 93651.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork10); 93661.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork11); 93671.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork12); 93681.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork13); 93691.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork14); 93701.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork15); 93711.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork16); 93721.149Skamil 93731.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn1); 93741.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn2); 93751.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn3); 93761.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn4); 93771.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn5); 93781.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn6); 93791.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn7); 93801.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn8); 93811.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn9); 93821.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn10); 93831.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn11); 93841.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn12); 93851.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn13); 93861.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn14); 93871.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn15); 93881.149Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn16); 93891.149Skamil 93901.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 93911.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 93921.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 93931.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 93941.126Skamil 93951.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 93961.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 93971.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 93981.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 93991.116Skamil 94001.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn_detach_spawner); 94011.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork_detach_forker); 94021.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_detach_vforker); 94031.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_detach_vforkerdone); 94041.150Skamil 94051.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_posix_spawn_kill_spawner); 94061.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_fork_kill_forker); 94071.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_kill_vforker); 94081.150Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_vfork_kill_vforkerdone); 94091.150Skamil 94101.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 94111.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 94121.108Skamil 94131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 94141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 94151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 94161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 94171.54Skamil 94181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 94191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 94201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 94211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 94221.54Skamil 94231.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 94241.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 94251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 94261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 94271.54Skamil 94281.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 94291.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 94301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 94311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 94321.54Skamil 94331.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 94341.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 94351.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 94361.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 94371.54Skamil 94381.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 94391.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 94401.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 94411.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 94421.54Skamil 94431.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 94441.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 94451.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 94461.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 94471.54Skamil 94481.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 94491.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 94501.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 94511.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 94521.54Skamil 94531.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 94541.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 94551.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 94561.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 94571.54Skamil 94581.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 94591.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 94601.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 94611.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 94621.1Skamil 94631.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 94641.1Skamil 94651.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 94661.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 94671.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 94681.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 94691.101Skamil 94701.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 94711.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 94721.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 94731.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 94741.101Skamil 94751.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 94761.101Skamil 94771.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 94781.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 94791.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 94801.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 94811.115Skamil 94821.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 94831.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 94841.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 94851.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 94861.115Skamil 94871.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 94881.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 94891.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 94901.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 94911.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 94921.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 94931.1Skamil 94941.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x1); 94951.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x3); 94961.148Smartin ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs_set_unaligned_pc_0x7); 94971.147Skamil 94981.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 94991.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 95001.1Skamil 95011.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 95021.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 95031.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 95041.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 95051.1Skamil 95061.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 95071.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 95081.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 95091.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 95101.2Skamil 95111.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 95121.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 95131.95Skamil 95141.1Skamil ATF_TP_ADD_TC(tp, kill1); 95151.1Skamil ATF_TP_ADD_TC(tp, kill2); 95161.75Skamil ATF_TP_ADD_TC(tp, kill3); 95171.1Skamil 95181.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 95191.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 95201.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 95211.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 95221.77Skamil 95231.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus); 95241.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus); 95251.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus); 95261.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus); 95271.143Skamil 95281.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_sigmask); 95291.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_sigmask); 95301.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_sigmask); 95311.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_sigmask); 95321.143Skamil 95331.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_name); 95341.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_name); 95351.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_name); 95361.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_name); 95371.143Skamil 95381.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_private); 95391.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_private); 95401.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_private); 95411.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_private); 95421.143Skamil 95431.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0); 95441.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1); 95451.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2); 95461.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3); 95471.143Skamil 95481.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_sigmask); 95491.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_sigmask); 95501.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_sigmask); 95511.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_sigmask); 95521.143Skamil 95531.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_name); 95541.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_name); 95551.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_name); 95561.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_name); 95571.143Skamil 95581.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_private); 95591.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_private); 95601.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_private); 95611.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_private); 95621.143Skamil 95631.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 95641.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 95651.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 95661.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 95671.1Skamil 95681.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 95691.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 95701.79Skamil 95711.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 95721.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 95731.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 95741.1Skamil 95751.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 95761.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 95771.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 95781.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 95791.1Skamil 95801.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap); 95811.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap); 95821.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap); 95831.153Skamil 95841.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 95851.84Skamil 95861.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 95871.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 95881.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 95891.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 95901.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 95911.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 95921.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 95931.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 95941.99Skamil 95951.151Skamil ATF_TP_ADD_TC(tp, threads_and_exec); 95961.151Skamil 95971.154Skamil ATF_TP_ADD_TC(tp, suspend_no_deadlock); 95981.1Skamil 95991.155Skamil ATF_TP_ADD_TC(tp, resume); 96001.1Skamil 96011.166Skamil ATF_TP_ADD_TC(tp, syscall); 96021.166Skamil ATF_TP_ADD_TC(tp, syscall_killed_on_sce); 96031.167Skamil ATF_TP_ADD_TC(tp, syscall_signal_on_sce); 96041.167Skamil ATF_TP_ADD_TC(tp, syscall_detach_on_sce); 96051.1Skamil 96061.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 96071.1Skamil 96081.106Skamil ATF_TP_ADD_TC(tp, clone1); 96091.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 96101.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 96111.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 96121.106Skamil ATF_TP_ADD_TC(tp, clone5); 96131.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 96141.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 96151.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 96161.106Skamil 96171.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 96181.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 96191.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 96201.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 96211.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 96221.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 96231.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 96241.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 96251.106Skamil 96261.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 96271.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 96281.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 96291.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 96301.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 96311.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 96321.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 96331.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 96341.106Skamil 96351.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 96361.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 96371.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 96381.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 96391.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 96401.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 96411.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 96421.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 96431.106Skamil 96441.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 96451.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 96461.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 96471.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 96481.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 96491.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 96501.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 96511.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 96521.106Skamil 96531.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 96541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 96551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 96561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 96571.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 96581.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 96591.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 96601.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 96611.106Skamil 96621.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 96631.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 96641.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 96651.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 96661.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 96671.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 96681.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 96691.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 96701.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 96711.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 96721.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 96731.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 96741.103Skamil 96751.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 96761.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 96771.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 96781.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 96791.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 96801.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 96811.107Skamil 96821.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 96831.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 96841.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 96851.122Skamil 96861.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 96871.130Smgorny 96881.138Smgorny#if defined(TWAIT_HAVE_STATUS) 96891.138Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals); 96901.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_sig_ign); 96911.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_handler); 96921.160Smgorny#if defined(__i386__) || defined(__x86_64__) 96931.160Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_breakpoints); 96941.161Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_watchpoints); 96951.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp); 96961.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig); 96971.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_sig_ign); 96981.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_handler); 96991.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig); 97001.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_sig_ign); 97011.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_handler); 97021.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig); 97031.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_sig_ign); 97041.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_handler); 97051.160Smgorny#endif 97061.138Smgorny#endif 97071.138Smgorny 97081.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 97091.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 97101.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 97111.1Skamil 97121.165Skamil#else 97131.165Skamil ATF_TP_ADD_TC(tp, dummy); 97141.165Skamil#endif 97151.165Skamil 97161.1Skamil return atf_no_error(); 97171.1Skamil} 9718