t_ptrace_wait.c revision 1.147
11.147Skamil/* $NetBSD: t_ptrace_wait.c,v 1.147 2020/01/21 16:46:07 kamil Exp $ */ 21.1Skamil 31.1Skamil/*- 41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. 51.1Skamil * All rights reserved. 61.1Skamil * 71.1Skamil * Redistribution and use in source and binary forms, with or without 81.1Skamil * modification, are permitted provided that the following conditions 91.1Skamil * are met: 101.1Skamil * 1. Redistributions of source code must retain the above copyright 111.1Skamil * notice, this list of conditions and the following disclaimer. 121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright 131.1Skamil * notice, this list of conditions and the following disclaimer in the 141.1Skamil * documentation and/or other materials provided with the distribution. 151.1Skamil * 161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Skamil * POSSIBILITY OF SUCH DAMAGE. 271.1Skamil */ 281.1Skamil 291.1Skamil#include <sys/cdefs.h> 301.147Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.147 2020/01/21 16:46:07 kamil Exp $"); 311.143Skamil 321.143Skamil#define __LEGACY_PT_LWPINFO 331.1Skamil 341.1Skamil#include <sys/param.h> 351.1Skamil#include <sys/types.h> 361.130Smgorny#include <sys/exec_elf.h> 371.39Skamil#include <sys/mman.h> 381.1Skamil#include <sys/ptrace.h> 391.1Skamil#include <sys/resource.h> 401.1Skamil#include <sys/stat.h> 411.1Skamil#include <sys/syscall.h> 421.1Skamil#include <sys/sysctl.h> 431.129Smgorny#include <sys/uio.h> 441.1Skamil#include <sys/wait.h> 451.1Skamil#include <machine/reg.h> 461.132Skamil#include <assert.h> 471.1Skamil#include <elf.h> 481.1Skamil#include <err.h> 491.1Skamil#include <errno.h> 501.130Smgorny#include <fcntl.h> 511.1Skamil#include <lwp.h> 521.77Skamil#include <pthread.h> 531.1Skamil#include <sched.h> 541.1Skamil#include <signal.h> 551.124Skamil#include <spawn.h> 561.1Skamil#include <stdint.h> 571.1Skamil#include <stdio.h> 581.1Skamil#include <stdlib.h> 591.1Skamil#include <strings.h> 601.26Skamil#include <time.h> 611.1Skamil#include <unistd.h> 621.1Skamil 631.114Skamil#include <fenv.h> 641.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 651.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 661.114Skamil#endif 671.114Skamil 681.121Smgorny#if defined(__i386__) || defined(__x86_64__) 691.121Smgorny#include <cpuid.h> 701.121Smgorny#include <x86/cpu_extended_state.h> 711.129Smgorny#include <x86/specialreg.h> 721.121Smgorny#endif 731.121Smgorny 741.130Smgorny#include <libelf.h> 751.130Smgorny#include <gelf.h> 761.130Smgorny 771.1Skamil#include <atf-c.h> 781.1Skamil 791.132Skamil/* Assumptions in the kernel code that must be kept. */ 801.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_report_event) == 811.132Skamil sizeof(((siginfo_t *)0)->si_pe_report_event), 821.132Skamil "pe_report_event and si_pe_report_event must be of the same size"); 831.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 841.132Skamil sizeof(((siginfo_t *)0)->si_pe_other_pid), 851.132Skamil "pe_other_pid and si_pe_other_pid must be of the same size"); 861.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_lwp) == 871.132Skamil sizeof(((siginfo_t *)0)->si_pe_lwp), 881.132Skamil "pe_lwp and si_pe_lwp must be of the same size"); 891.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 901.132Skamil sizeof(((struct ptrace_state *)0)->pe_lwp), 911.132Skamil "pe_other_pid and pe_lwp must be of the same size"); 921.132Skamil 931.1Skamil#include "h_macros.h" 941.1Skamil 951.1Skamil#include "t_ptrace_wait.h" 961.1Skamil#include "msg.h" 971.1Skamil 981.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 991.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 1001.61Skre sizeof(msg)) == 0) 1011.1Skamil 1021.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 1031.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 1041.61Skre sizeof(msg)) == 0) 1051.1Skamil 1061.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 1071.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 1081.61Skre sizeof(msg)) == 0) 1091.1Skamil 1101.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 1111.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 1121.61Skre sizeof(msg)) == 0) 1131.13Schristos 1141.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 1151.13Schristos strerror(errno)) 1161.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 1171.18Schristos "%d(%s) != %d", res, strerror(res), exp) 1181.13Schristos 1191.13Schristosstatic int debug = 0; 1201.13Schristos 1211.13Schristos#define DPRINTF(a, ...) do \ 1221.123Skamil if (debug) \ 1231.142Skamil printf("%s() %d.%d %s:%d " a, \ 1241.142Skamil __func__, getpid(), _lwp_self(), __FILE__, __LINE__, ##__VA_ARGS__); \ 1251.13Schristos while (/*CONSTCOND*/0) 1261.1Skamil 1271.34Skamil/// ---------------------------------------------------------------------------- 1281.34Skamil 1291.33Skamilstatic void 1301.33Skamiltraceme_raise(int sigval) 1311.1Skamil{ 1321.1Skamil const int exitval = 5; 1331.1Skamil pid_t child, wpid; 1341.1Skamil#if defined(TWAIT_HAVE_STATUS) 1351.1Skamil int status; 1361.1Skamil#endif 1371.1Skamil 1381.133Skamil ptrace_state_t state, zero_state; 1391.133Skamil const int slen = sizeof(state); 1401.45Skamil struct ptrace_siginfo info; 1411.133Skamil memset(&zero_state, 0, sizeof(zero_state)); 1421.45Skamil memset(&info, 0, sizeof(info)); 1431.45Skamil 1441.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1451.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1461.1Skamil if (child == 0) { 1471.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1481.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1491.1Skamil 1501.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1511.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1521.1Skamil 1531.36Skamil switch (sigval) { 1541.36Skamil case SIGKILL: 1551.36Skamil /* NOTREACHED */ 1561.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1571.70Smrg __unreachable(); 1581.36Skamil default: 1591.36Skamil DPRINTF("Before exiting of the child process\n"); 1601.36Skamil _exit(exitval); 1611.36Skamil } 1621.1Skamil } 1631.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1641.1Skamil 1651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1671.1Skamil 1681.36Skamil switch (sigval) { 1691.36Skamil case SIGKILL: 1701.36Skamil validate_status_signaled(status, sigval, 0); 1711.133Skamil SYSCALL_REQUIRE( 1721.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) == -1); 1731.133Skamil 1741.36Skamil break; 1751.36Skamil default: 1761.36Skamil validate_status_stopped(status, sigval); 1771.1Skamil 1781.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1791.61Skre "child\n"); 1801.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1811.61Skre sizeof(info)) != -1); 1821.45Skamil 1831.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1841.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1851.61Skre "si_errno=%#x\n", 1861.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1871.61Skre info.psi_siginfo.si_errno); 1881.45Skamil 1891.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1901.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1911.45Skamil 1921.133Skamil DPRINTF("Assert that PT_GET_PROCESS_STATE returns non-error"); 1931.133Skamil SYSCALL_REQUIRE( 1941.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 1951.133Skamil ATF_REQUIRE(memcmp(&state, &zero_state, slen) == 0); 1961.133Skamil 1971.36Skamil DPRINTF("Before resuming the child process where it left off " 1981.36Skamil "and without signal to be sent\n"); 1991.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2001.1Skamil 2011.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2021.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 2031.61Skre child); 2041.36Skamil break; 2051.36Skamil } 2061.1Skamil 2071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2081.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2091.1Skamil} 2101.1Skamil 2111.61Skre#define TRACEME_RAISE(test, sig) \ 2121.61SkreATF_TC(test); \ 2131.61SkreATF_TC_HEAD(test, tc) \ 2141.61Skre{ \ 2151.61Skre atf_tc_set_md_var(tc, "descr", \ 2161.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 2171.61Skre} \ 2181.61Skre \ 2191.61SkreATF_TC_BODY(test, tc) \ 2201.61Skre{ \ 2211.61Skre \ 2221.61Skre traceme_raise(sig); \ 2231.33Skamil} 2241.33Skamil 2251.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2261.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2271.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2281.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2291.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2301.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2311.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2321.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2331.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2341.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2351.33Skamil 2361.34Skamil/// ---------------------------------------------------------------------------- 2371.1Skamil 2381.1Skamilstatic void 2391.87Skamiltraceme_raisesignal_ignored(int sigignored) 2401.87Skamil{ 2411.87Skamil const int exitval = 5; 2421.87Skamil const int sigval = SIGSTOP; 2431.87Skamil pid_t child, wpid; 2441.87Skamil struct sigaction sa; 2451.87Skamil#if defined(TWAIT_HAVE_STATUS) 2461.87Skamil int status; 2471.87Skamil#endif 2481.87Skamil struct ptrace_siginfo info; 2491.87Skamil 2501.87Skamil memset(&info, 0, sizeof(info)); 2511.87Skamil 2521.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2531.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2541.87Skamil if (child == 0) { 2551.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2561.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2571.87Skamil 2581.87Skamil memset(&sa, 0, sizeof(sa)); 2591.87Skamil sa.sa_handler = SIG_IGN; 2601.87Skamil sigemptyset(&sa.sa_mask); 2611.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2621.87Skamil 2631.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2641.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2651.87Skamil 2661.87Skamil DPRINTF("Before raising %s from child\n", 2671.87Skamil strsignal(sigignored)); 2681.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2691.87Skamil 2701.87Skamil DPRINTF("Before exiting of the child process\n"); 2711.87Skamil _exit(exitval); 2721.87Skamil } 2731.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2741.87Skamil 2751.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2761.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2771.87Skamil 2781.87Skamil validate_status_stopped(status, sigval); 2791.87Skamil 2801.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2811.87Skamil SYSCALL_REQUIRE( 2821.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2831.87Skamil 2841.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2851.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2861.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2871.87Skamil info.psi_siginfo.si_errno); 2881.87Skamil 2891.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2901.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2911.87Skamil 2921.87Skamil DPRINTF("Before resuming the child process where it left off and " 2931.87Skamil "without signal to be sent\n"); 2941.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2951.87Skamil 2961.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2971.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2981.87Skamil 2991.87Skamil validate_status_stopped(status, sigignored); 3001.87Skamil 3011.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3021.87Skamil SYSCALL_REQUIRE( 3031.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3041.87Skamil 3051.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3061.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3071.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3081.87Skamil info.psi_siginfo.si_errno); 3091.87Skamil 3101.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 3111.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3121.87Skamil 3131.87Skamil DPRINTF("Before resuming the child process where it left off and " 3141.87Skamil "without signal to be sent\n"); 3151.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3161.87Skamil 3171.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3181.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3191.87Skamil 3201.87Skamil validate_status_exited(status, exitval); 3211.87Skamil 3221.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3231.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3241.87Skamil} 3251.87Skamil 3261.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3271.87SkamilATF_TC(test); \ 3281.87SkamilATF_TC_HEAD(test, tc) \ 3291.87Skamil{ \ 3301.87Skamil atf_tc_set_md_var(tc, "descr", \ 3311.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3321.87Skamil "does not stop tracer from catching this raised signal"); \ 3331.87Skamil} \ 3341.87Skamil \ 3351.87SkamilATF_TC_BODY(test, tc) \ 3361.87Skamil{ \ 3371.87Skamil \ 3381.87Skamil traceme_raisesignal_ignored(sig); \ 3391.87Skamil} 3401.87Skamil 3411.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3421.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3431.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3441.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3451.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3461.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3471.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3481.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3491.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3501.87Skamil 3511.87Skamil/// ---------------------------------------------------------------------------- 3521.87Skamil 3531.87Skamilstatic void 3541.86Skamiltraceme_raisesignal_masked(int sigmasked) 3551.86Skamil{ 3561.86Skamil const int exitval = 5; 3571.86Skamil const int sigval = SIGSTOP; 3581.86Skamil pid_t child, wpid; 3591.86Skamil#if defined(TWAIT_HAVE_STATUS) 3601.86Skamil int status; 3611.86Skamil#endif 3621.86Skamil sigset_t intmask; 3631.86Skamil struct ptrace_siginfo info; 3641.86Skamil 3651.86Skamil memset(&info, 0, sizeof(info)); 3661.86Skamil 3671.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3681.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3691.86Skamil if (child == 0) { 3701.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3711.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3721.86Skamil 3731.86Skamil sigemptyset(&intmask); 3741.86Skamil sigaddset(&intmask, sigmasked); 3751.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3761.86Skamil 3771.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3781.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3791.86Skamil 3801.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3811.86Skamil strsignal(sigmasked)); 3821.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3831.86Skamil 3841.86Skamil DPRINTF("Before exiting of the child process\n"); 3851.86Skamil _exit(exitval); 3861.86Skamil } 3871.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3881.86Skamil 3891.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3901.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3911.86Skamil 3921.86Skamil validate_status_stopped(status, sigval); 3931.86Skamil 3941.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3951.86Skamil SYSCALL_REQUIRE( 3961.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3971.86Skamil 3981.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3991.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4001.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4011.86Skamil info.psi_siginfo.si_errno); 4021.86Skamil 4031.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 4041.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 4051.86Skamil 4061.86Skamil DPRINTF("Before resuming the child process where it left off and " 4071.86Skamil "without signal to be sent\n"); 4081.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 4091.86Skamil 4101.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4111.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4121.86Skamil 4131.86Skamil validate_status_exited(status, exitval); 4141.86Skamil 4151.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4161.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 4171.86Skamil} 4181.86Skamil 4191.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 4201.86SkamilATF_TC(test); \ 4211.86SkamilATF_TC_HEAD(test, tc) \ 4221.86Skamil{ \ 4231.86Skamil atf_tc_set_md_var(tc, "descr", \ 4241.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4251.86Skamil "stops tracer from catching this raised signal"); \ 4261.86Skamil} \ 4271.86Skamil \ 4281.86SkamilATF_TC_BODY(test, tc) \ 4291.86Skamil{ \ 4301.86Skamil \ 4311.86Skamil traceme_raisesignal_masked(sig); \ 4321.86Skamil} 4331.86Skamil 4341.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4351.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4361.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4371.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4381.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4391.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4401.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4411.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4421.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4431.86Skamil 4441.86Skamil/// ---------------------------------------------------------------------------- 4451.86Skamil 4461.86Skamilstatic void 4471.59Skamiltraceme_crash(int sig) 4481.59Skamil{ 4491.59Skamil pid_t child, wpid; 4501.59Skamil#if defined(TWAIT_HAVE_STATUS) 4511.59Skamil int status; 4521.59Skamil#endif 4531.59Skamil struct ptrace_siginfo info; 4541.61Skre 4551.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4561.71Skamil if (sig == SIGILL) 4571.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4581.71Skamil#endif 4591.71Skamil 4601.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4611.114Skamil atf_tc_skip("FP exceptions are not supported"); 4621.114Skamil 4631.59Skamil memset(&info, 0, sizeof(info)); 4641.59Skamil 4651.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4661.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4671.59Skamil if (child == 0) { 4681.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4691.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4701.59Skamil 4711.59Skamil DPRINTF("Before executing a trap\n"); 4721.59Skamil switch (sig) { 4731.59Skamil case SIGTRAP: 4741.59Skamil trigger_trap(); 4751.59Skamil break; 4761.59Skamil case SIGSEGV: 4771.59Skamil trigger_segv(); 4781.59Skamil break; 4791.59Skamil case SIGILL: 4801.59Skamil trigger_ill(); 4811.59Skamil break; 4821.59Skamil case SIGFPE: 4831.59Skamil trigger_fpe(); 4841.59Skamil break; 4851.59Skamil case SIGBUS: 4861.59Skamil trigger_bus(); 4871.59Skamil break; 4881.59Skamil default: 4891.59Skamil /* NOTREACHED */ 4901.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4911.59Skamil } 4921.59Skamil 4931.59Skamil /* NOTREACHED */ 4941.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4951.59Skamil } 4961.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4971.59Skamil 4981.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4991.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5001.59Skamil 5011.59Skamil validate_status_stopped(status, sig); 5021.59Skamil 5031.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 5041.61Skre SYSCALL_REQUIRE( 5051.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 5061.59Skamil 5071.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 5081.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 5091.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 5101.61Skre info.psi_siginfo.si_errno); 5111.59Skamil 5121.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 5131.59Skamil switch (sig) { 5141.59Skamil case SIGTRAP: 5151.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 5161.59Skamil break; 5171.59Skamil case SIGSEGV: 5181.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 5191.59Skamil break; 5201.71Skamil case SIGILL: 5211.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 5221.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5231.71Skamil break; 5241.59Skamil case SIGFPE: 5251.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5261.59Skamil break; 5271.59Skamil case SIGBUS: 5281.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5291.59Skamil break; 5301.59Skamil } 5311.59Skamil 5321.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5331.59Skamil 5341.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5351.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5361.59Skamil 5371.59Skamil validate_status_signaled(status, SIGKILL, 0); 5381.59Skamil 5391.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5401.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5411.59Skamil} 5421.59Skamil 5431.61Skre#define TRACEME_CRASH(test, sig) \ 5441.61SkreATF_TC(test); \ 5451.61SkreATF_TC_HEAD(test, tc) \ 5461.61Skre{ \ 5471.61Skre atf_tc_set_md_var(tc, "descr", \ 5481.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5491.61Skre} \ 5501.61Skre \ 5511.61SkreATF_TC_BODY(test, tc) \ 5521.61Skre{ \ 5531.61Skre \ 5541.61Skre traceme_crash(sig); \ 5551.59Skamil} 5561.59Skamil 5571.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5581.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5591.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5601.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5611.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5621.59Skamil 5631.59Skamil/// ---------------------------------------------------------------------------- 5641.59Skamil 5651.59Skamilstatic void 5661.88Skamiltraceme_signalmasked_crash(int sig) 5671.88Skamil{ 5681.89Skamil const int sigval = SIGSTOP; 5691.88Skamil pid_t child, wpid; 5701.88Skamil#if defined(TWAIT_HAVE_STATUS) 5711.88Skamil int status; 5721.88Skamil#endif 5731.88Skamil struct ptrace_siginfo info; 5741.88Skamil sigset_t intmask; 5751.89Skamil struct kinfo_proc2 kp; 5761.89Skamil size_t len = sizeof(kp); 5771.89Skamil 5781.89Skamil int name[6]; 5791.89Skamil const size_t namelen = __arraycount(name); 5801.89Skamil ki_sigset_t kp_sigmask; 5811.88Skamil 5821.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5831.88Skamil if (sig == SIGILL) 5841.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5851.88Skamil#endif 5861.88Skamil 5871.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5881.114Skamil atf_tc_skip("FP exceptions are not supported"); 5891.114Skamil 5901.88Skamil memset(&info, 0, sizeof(info)); 5911.88Skamil 5921.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5931.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5941.88Skamil if (child == 0) { 5951.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5961.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5971.88Skamil 5981.88Skamil sigemptyset(&intmask); 5991.88Skamil sigaddset(&intmask, sig); 6001.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 6011.88Skamil 6021.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 6031.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 6041.89Skamil 6051.88Skamil DPRINTF("Before executing a trap\n"); 6061.88Skamil switch (sig) { 6071.88Skamil case SIGTRAP: 6081.88Skamil trigger_trap(); 6091.88Skamil break; 6101.88Skamil case SIGSEGV: 6111.88Skamil trigger_segv(); 6121.88Skamil break; 6131.88Skamil case SIGILL: 6141.88Skamil trigger_ill(); 6151.88Skamil break; 6161.88Skamil case SIGFPE: 6171.88Skamil trigger_fpe(); 6181.88Skamil break; 6191.88Skamil case SIGBUS: 6201.88Skamil trigger_bus(); 6211.88Skamil break; 6221.88Skamil default: 6231.88Skamil /* NOTREACHED */ 6241.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6251.88Skamil } 6261.88Skamil 6271.88Skamil /* NOTREACHED */ 6281.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6291.88Skamil } 6301.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6311.88Skamil 6321.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6331.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6341.88Skamil 6351.89Skamil validate_status_stopped(status, sigval); 6361.89Skamil 6371.89Skamil name[0] = CTL_KERN, 6381.89Skamil name[1] = KERN_PROC2, 6391.89Skamil name[2] = KERN_PROC_PID; 6401.89Skamil name[3] = child; 6411.89Skamil name[4] = sizeof(kp); 6421.89Skamil name[5] = 1; 6431.89Skamil 6441.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6451.89Skamil 6461.89Skamil kp_sigmask = kp.p_sigmask; 6471.89Skamil 6481.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6491.89Skamil SYSCALL_REQUIRE( 6501.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6511.89Skamil 6521.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6531.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6541.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6551.89Skamil info.psi_siginfo.si_errno); 6561.89Skamil 6571.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6581.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6591.89Skamil 6601.89Skamil DPRINTF("Before resuming the child process where it left off and " 6611.89Skamil "without signal to be sent\n"); 6621.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6631.89Skamil 6641.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6651.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6661.89Skamil 6671.88Skamil validate_status_stopped(status, sig); 6681.88Skamil 6691.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6701.88Skamil SYSCALL_REQUIRE( 6711.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6721.88Skamil 6731.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6741.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6751.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6761.88Skamil info.psi_siginfo.si_errno); 6771.88Skamil 6781.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6791.89Skamil 6801.89Skamil DPRINTF("kp_sigmask=" 6811.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6821.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6831.89Skamil kp_sigmask.__bits[3]); 6841.89Skamil 6851.89Skamil DPRINTF("kp.p_sigmask=" 6861.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6871.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6881.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6891.89Skamil 6901.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6911.89Skamil 6921.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6931.88Skamil switch (sig) { 6941.88Skamil case SIGTRAP: 6951.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6961.88Skamil break; 6971.88Skamil case SIGSEGV: 6981.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6991.88Skamil break; 7001.88Skamil case SIGILL: 7011.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 7021.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 7031.88Skamil break; 7041.88Skamil case SIGFPE: 7051.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 7061.88Skamil break; 7071.88Skamil case SIGBUS: 7081.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 7091.88Skamil break; 7101.88Skamil } 7111.88Skamil 7121.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 7131.88Skamil 7141.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7151.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7161.88Skamil 7171.88Skamil validate_status_signaled(status, SIGKILL, 0); 7181.88Skamil 7191.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7201.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 7211.88Skamil} 7221.88Skamil 7231.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7241.88SkamilATF_TC(test); \ 7251.88SkamilATF_TC_HEAD(test, tc) \ 7261.88Skamil{ \ 7271.88Skamil atf_tc_set_md_var(tc, "descr", \ 7281.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7291.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7301.88Skamil} \ 7311.88Skamil \ 7321.88SkamilATF_TC_BODY(test, tc) \ 7331.88Skamil{ \ 7341.88Skamil \ 7351.88Skamil traceme_signalmasked_crash(sig); \ 7361.88Skamil} 7371.88Skamil 7381.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7391.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7401.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7411.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7421.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7431.88Skamil 7441.88Skamil/// ---------------------------------------------------------------------------- 7451.88Skamil 7461.88Skamilstatic void 7471.88Skamiltraceme_signalignored_crash(int sig) 7481.88Skamil{ 7491.90Skamil const int sigval = SIGSTOP; 7501.88Skamil pid_t child, wpid; 7511.88Skamil#if defined(TWAIT_HAVE_STATUS) 7521.88Skamil int status; 7531.88Skamil#endif 7541.88Skamil struct sigaction sa; 7551.88Skamil struct ptrace_siginfo info; 7561.90Skamil struct kinfo_proc2 kp; 7571.90Skamil size_t len = sizeof(kp); 7581.90Skamil 7591.90Skamil int name[6]; 7601.90Skamil const size_t namelen = __arraycount(name); 7611.90Skamil ki_sigset_t kp_sigignore; 7621.88Skamil 7631.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7641.88Skamil if (sig == SIGILL) 7651.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7661.88Skamil#endif 7671.88Skamil 7681.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7691.114Skamil atf_tc_skip("FP exceptions are not supported"); 7701.114Skamil 7711.88Skamil memset(&info, 0, sizeof(info)); 7721.88Skamil 7731.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7741.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7751.88Skamil if (child == 0) { 7761.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7771.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7781.88Skamil 7791.88Skamil memset(&sa, 0, sizeof(sa)); 7801.88Skamil sa.sa_handler = SIG_IGN; 7811.88Skamil sigemptyset(&sa.sa_mask); 7821.88Skamil 7831.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7841.88Skamil 7851.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7861.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7871.90Skamil 7881.88Skamil DPRINTF("Before executing a trap\n"); 7891.88Skamil switch (sig) { 7901.88Skamil case SIGTRAP: 7911.88Skamil trigger_trap(); 7921.88Skamil break; 7931.88Skamil case SIGSEGV: 7941.88Skamil trigger_segv(); 7951.88Skamil break; 7961.88Skamil case SIGILL: 7971.88Skamil trigger_ill(); 7981.88Skamil break; 7991.88Skamil case SIGFPE: 8001.88Skamil trigger_fpe(); 8011.88Skamil break; 8021.88Skamil case SIGBUS: 8031.88Skamil trigger_bus(); 8041.88Skamil break; 8051.88Skamil default: 8061.88Skamil /* NOTREACHED */ 8071.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8081.88Skamil } 8091.88Skamil 8101.88Skamil /* NOTREACHED */ 8111.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8121.88Skamil } 8131.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 8141.88Skamil 8151.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8161.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8171.88Skamil 8181.90Skamil validate_status_stopped(status, sigval); 8191.90Skamil 8201.90Skamil name[0] = CTL_KERN, 8211.90Skamil name[1] = KERN_PROC2, 8221.90Skamil name[2] = KERN_PROC_PID; 8231.90Skamil name[3] = child; 8241.90Skamil name[4] = sizeof(kp); 8251.90Skamil name[5] = 1; 8261.90Skamil 8271.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8281.90Skamil 8291.90Skamil kp_sigignore = kp.p_sigignore; 8301.90Skamil 8311.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8321.90Skamil SYSCALL_REQUIRE( 8331.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8341.90Skamil 8351.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8361.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8371.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8381.90Skamil info.psi_siginfo.si_errno); 8391.90Skamil 8401.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8411.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8421.90Skamil 8431.90Skamil DPRINTF("Before resuming the child process where it left off and " 8441.90Skamil "without signal to be sent\n"); 8451.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8461.90Skamil 8471.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8481.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8491.90Skamil 8501.88Skamil validate_status_stopped(status, sig); 8511.88Skamil 8521.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8531.88Skamil SYSCALL_REQUIRE( 8541.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8551.88Skamil 8561.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8571.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8581.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8591.88Skamil info.psi_siginfo.si_errno); 8601.88Skamil 8611.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8621.90Skamil 8631.90Skamil DPRINTF("kp_sigignore=" 8641.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8651.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8661.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8671.90Skamil 8681.90Skamil DPRINTF("kp.p_sigignore=" 8691.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8701.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8711.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8721.90Skamil 8731.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8741.90Skamil 8751.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8761.88Skamil switch (sig) { 8771.88Skamil case SIGTRAP: 8781.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8791.88Skamil break; 8801.88Skamil case SIGSEGV: 8811.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8821.88Skamil break; 8831.88Skamil case SIGILL: 8841.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8851.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8861.88Skamil break; 8871.88Skamil case SIGFPE: 8881.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8891.88Skamil break; 8901.88Skamil case SIGBUS: 8911.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8921.88Skamil break; 8931.88Skamil } 8941.88Skamil 8951.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8961.88Skamil 8971.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8981.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8991.88Skamil 9001.88Skamil validate_status_signaled(status, SIGKILL, 0); 9011.88Skamil 9021.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9031.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9041.88Skamil} 9051.88Skamil 9061.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 9071.88SkamilATF_TC(test); \ 9081.88SkamilATF_TC_HEAD(test, tc) \ 9091.88Skamil{ \ 9101.88Skamil atf_tc_set_md_var(tc, "descr", \ 9111.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 9121.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 9131.88Skamil} \ 9141.88Skamil \ 9151.88SkamilATF_TC_BODY(test, tc) \ 9161.88Skamil{ \ 9171.88Skamil \ 9181.88Skamil traceme_signalignored_crash(sig); \ 9191.88Skamil} 9201.88Skamil 9211.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 9221.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9231.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9241.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9251.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9261.88Skamil 9271.88Skamil/// ---------------------------------------------------------------------------- 9281.88Skamil 9291.88Skamilstatic void 9301.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9311.1Skamil{ 9321.1Skamil const int exitval = 5; 9331.34Skamil const int sigval = SIGSTOP; 9341.1Skamil pid_t child, wpid; 9351.1Skamil struct sigaction sa; 9361.1Skamil#if defined(TWAIT_HAVE_STATUS) 9371.1Skamil int status; 9381.1Skamil#endif 9391.61Skre struct ptrace_siginfo info; 9401.1Skamil 9411.45Skamil memset(&info, 0, sizeof(info)); 9421.45Skamil 9431.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9441.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9451.1Skamil if (child == 0) { 9461.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9471.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9481.1Skamil 9491.34Skamil sa.sa_handler = sah; 9501.1Skamil sa.sa_flags = SA_SIGINFO; 9511.1Skamil sigemptyset(&sa.sa_mask); 9521.1Skamil 9531.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9541.1Skamil 9551.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9561.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9571.1Skamil 9581.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9591.1Skamil 9601.13Schristos DPRINTF("Before exiting of the child process\n"); 9611.1Skamil _exit(exitval); 9621.1Skamil } 9631.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9641.1Skamil 9651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9671.1Skamil 9681.1Skamil validate_status_stopped(status, sigval); 9691.1Skamil 9701.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9711.61Skre SYSCALL_REQUIRE( 9721.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9731.45Skamil 9741.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9751.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9761.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9771.45Skamil info.psi_siginfo.si_errno); 9781.45Skamil 9791.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9801.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9811.45Skamil 9821.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9831.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9841.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9851.1Skamil 9861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9881.1Skamil 9891.1Skamil validate_status_exited(status, exitval); 9901.1Skamil 9911.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9921.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9931.1Skamil} 9941.1Skamil 9951.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9961.61SkreATF_TC(test); \ 9971.61SkreATF_TC_HEAD(test, tc) \ 9981.61Skre{ \ 9991.61Skre atf_tc_set_md_var(tc, "descr", \ 10001.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10011.61Skre "handled correctly and caught by a signal handler"); \ 10021.61Skre} \ 10031.61Skre \ 10041.61Skrestatic int test##_caught = 0; \ 10051.61Skre \ 10061.61Skrestatic void \ 10071.61Skretest##_sighandler(int arg) \ 10081.61Skre{ \ 10091.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 10101.61Skre \ 10111.61Skre ++ test##_caught; \ 10121.61Skre} \ 10131.61Skre \ 10141.61SkreATF_TC_BODY(test, tc) \ 10151.61Skre{ \ 10161.61Skre \ 10171.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 10181.34Skamil} 10191.34Skamil 10201.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 10211.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 10221.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10231.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10241.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10251.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10261.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10271.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10281.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10291.34Skamil 10301.34Skamil/// ---------------------------------------------------------------------------- 10311.34Skamil 10321.35Skamilstatic void 10331.50Skamiltraceme_sendsignal_masked(int sigsent) 10341.50Skamil{ 10351.50Skamil const int exitval = 5; 10361.50Skamil const int sigval = SIGSTOP; 10371.50Skamil pid_t child, wpid; 10381.50Skamil sigset_t set; 10391.50Skamil#if defined(TWAIT_HAVE_STATUS) 10401.50Skamil int status; 10411.50Skamil#endif 10421.61Skre struct ptrace_siginfo info; 10431.50Skamil 10441.50Skamil memset(&info, 0, sizeof(info)); 10451.50Skamil 10461.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10471.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10481.50Skamil if (child == 0) { 10491.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10501.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10511.50Skamil 10521.50Skamil sigemptyset(&set); 10531.50Skamil sigaddset(&set, sigsent); 10541.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10551.50Skamil 10561.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10571.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10581.50Skamil 10591.50Skamil _exit(exitval); 10601.50Skamil } 10611.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10621.50Skamil 10631.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10641.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10651.50Skamil 10661.50Skamil validate_status_stopped(status, sigval); 10671.50Skamil 10681.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10691.61Skre SYSCALL_REQUIRE( 10701.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10711.50Skamil 10721.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10731.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10741.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10751.50Skamil info.psi_siginfo.si_errno); 10761.50Skamil 10771.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10781.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10791.50Skamil 10801.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10811.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10821.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10831.50Skamil 10841.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10851.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10861.50Skamil 10871.50Skamil validate_status_exited(status, exitval); 10881.50Skamil 10891.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10901.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10911.50Skamil} 10921.50Skamil 10931.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10941.61SkreATF_TC(test); \ 10951.61SkreATF_TC_HEAD(test, tc) \ 10961.61Skre{ \ 10971.61Skre atf_tc_set_md_var(tc, "descr", \ 10981.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10991.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 11001.61Skre} \ 11011.61Skre \ 11021.61SkreATF_TC_BODY(test, tc) \ 11031.61Skre{ \ 11041.61Skre \ 11051.61Skre traceme_sendsignal_masked(sig); \ 11061.50Skamil} 11071.50Skamil 11081.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 11091.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 11101.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 11111.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 11121.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 11131.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 11141.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 11151.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 11161.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 11171.50Skamil 11181.50Skamil/// ---------------------------------------------------------------------------- 11191.50Skamil 11201.50Skamilstatic void 11211.50Skamiltraceme_sendsignal_ignored(int sigsent) 11221.50Skamil{ 11231.50Skamil const int exitval = 5; 11241.50Skamil const int sigval = SIGSTOP; 11251.50Skamil pid_t child, wpid; 11261.50Skamil struct sigaction sa; 11271.50Skamil#if defined(TWAIT_HAVE_STATUS) 11281.50Skamil int status; 11291.50Skamil#endif 11301.61Skre struct ptrace_siginfo info; 11311.50Skamil 11321.50Skamil memset(&info, 0, sizeof(info)); 11331.50Skamil 11341.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11351.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11361.50Skamil if (child == 0) { 11371.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11381.61Skre 11391.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11401.50Skamil 11411.50Skamil memset(&sa, 0, sizeof(sa)); 11421.50Skamil sa.sa_handler = SIG_IGN; 11431.50Skamil sigemptyset(&sa.sa_mask); 11441.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11451.50Skamil 11461.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11471.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11481.50Skamil 11491.50Skamil _exit(exitval); 11501.50Skamil } 11511.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11521.50Skamil 11531.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11541.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11551.50Skamil 11561.50Skamil validate_status_stopped(status, sigval); 11571.50Skamil 11581.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11591.61Skre SYSCALL_REQUIRE( 11601.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11611.50Skamil 11621.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11631.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11641.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11651.50Skamil info.psi_siginfo.si_errno); 11661.50Skamil 11671.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11681.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11691.50Skamil 11701.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11711.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11721.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11731.50Skamil 11741.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11751.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11761.50Skamil 11771.50Skamil validate_status_exited(status, exitval); 11781.50Skamil 11791.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11801.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11811.50Skamil} 11821.50Skamil 11831.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11841.61SkreATF_TC(test); \ 11851.61SkreATF_TC_HEAD(test, tc) \ 11861.61Skre{ \ 11871.61Skre atf_tc_set_md_var(tc, "descr", \ 11881.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11891.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11901.61Skre} \ 11911.61Skre \ 11921.61SkreATF_TC_BODY(test, tc) \ 11931.61Skre{ \ 11941.61Skre \ 11951.61Skre traceme_sendsignal_ignored(sig); \ 11961.50Skamil} 11971.50Skamil 11981.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11991.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 12001.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 12011.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 12021.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 12031.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 12041.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 12051.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 12061.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 12071.50Skamil 12081.50Skamil/// ---------------------------------------------------------------------------- 12091.50Skamil 12101.50Skamilstatic void 12111.50Skamiltraceme_sendsignal_simple(int sigsent) 12121.1Skamil{ 12131.35Skamil const int sigval = SIGSTOP; 12141.35Skamil int exitval = 0; 12151.1Skamil pid_t child, wpid; 12161.1Skamil#if defined(TWAIT_HAVE_STATUS) 12171.1Skamil int status; 12181.85Skamil int expect_core; 12191.85Skamil 12201.85Skamil switch (sigsent) { 12211.85Skamil case SIGABRT: 12221.85Skamil case SIGTRAP: 12231.85Skamil case SIGBUS: 12241.85Skamil case SIGILL: 12251.85Skamil case SIGFPE: 12261.85Skamil case SIGSEGV: 12271.85Skamil expect_core = 1; 12281.85Skamil break; 12291.85Skamil default: 12301.85Skamil expect_core = 0; 12311.85Skamil break; 12321.85Skamil } 12331.1Skamil#endif 12341.61Skre struct ptrace_siginfo info; 12351.1Skamil 12361.45Skamil memset(&info, 0, sizeof(info)); 12371.45Skamil 12381.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12391.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12401.1Skamil if (child == 0) { 12411.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12421.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12431.1Skamil 12441.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12451.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12461.1Skamil 12471.35Skamil switch (sigsent) { 12481.35Skamil case SIGCONT: 12491.48Skamil case SIGSTOP: 12501.35Skamil _exit(exitval); 12511.35Skamil default: 12521.35Skamil /* NOTREACHED */ 12531.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12541.35Skamil } 12551.1Skamil } 12561.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12571.1Skamil 12581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12601.1Skamil 12611.1Skamil validate_status_stopped(status, sigval); 12621.1Skamil 12631.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12641.61Skre SYSCALL_REQUIRE( 12651.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12661.45Skamil 12671.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12681.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12691.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12701.45Skamil info.psi_siginfo.si_errno); 12711.45Skamil 12721.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12731.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12741.45Skamil 12751.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12761.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12771.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12781.1Skamil 12791.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12801.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12811.1Skamil 12821.35Skamil switch (sigsent) { 12831.48Skamil case SIGSTOP: 12841.48Skamil validate_status_stopped(status, sigsent); 12851.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12861.61Skre "child\n"); 12871.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12881.61Skre sizeof(info)) != -1); 12891.48Skamil 12901.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12911.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12921.61Skre "si_errno=%#x\n", 12931.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12941.61Skre info.psi_siginfo.si_errno); 12951.48Skamil 12961.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12971.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12981.48Skamil 12991.48Skamil DPRINTF("Before resuming the child process where it left off " 13001.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 13011.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 13021.48Skamil 13031.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13041.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 13051.61Skre child); 13061.48Skamil /* FALLTHROUGH */ 13071.35Skamil case SIGCONT: 13081.35Skamil validate_status_exited(status, exitval); 13091.35Skamil break; 13101.35Skamil default: 13111.35Skamil validate_status_signaled(status, sigsent, expect_core); 13121.35Skamil break; 13131.35Skamil } 13141.1Skamil 13151.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 13161.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 13171.1Skamil} 13181.1Skamil 13191.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 13201.61SkreATF_TC(test); \ 13211.61SkreATF_TC_HEAD(test, tc) \ 13221.61Skre{ \ 13231.61Skre atf_tc_set_md_var(tc, "descr", \ 13241.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13251.61Skre "handled correctly in a child without a signal handler"); \ 13261.61Skre} \ 13271.61Skre \ 13281.61SkreATF_TC_BODY(test, tc) \ 13291.61Skre{ \ 13301.61Skre \ 13311.61Skre traceme_sendsignal_simple(sig); \ 13321.35Skamil} 13331.35Skamil 13341.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13351.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13361.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13371.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13381.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13391.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13401.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13411.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13421.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13431.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13441.35Skamil 13451.35Skamil/// ---------------------------------------------------------------------------- 13461.35Skamil 13471.37SkamilATF_TC(traceme_pid1_parent); 13481.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13491.37Skamil{ 13501.37Skamil atf_tc_set_md_var(tc, "descr", 13511.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13521.37Skamil} 13531.37Skamil 13541.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13551.37Skamil{ 13561.37Skamil struct msg_fds parent_child; 13571.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13581.37Skamil pid_t child1, child2, wpid; 13591.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13601.37Skamil#if defined(TWAIT_HAVE_STATUS) 13611.37Skamil int status; 13621.37Skamil#endif 13631.37Skamil 13641.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13651.37Skamil 13661.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13671.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13681.37Skamil if (child1 == 0) { 13691.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13701.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13711.37Skamil if (child2 != 0) { 13721.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13731.61Skre getpid(), child2); 13741.37Skamil _exit(exitval_child1); 13751.37Skamil } 13761.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13771.37Skamil 13781.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13791.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13801.37Skamil 13811.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13821.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13831.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13841.37Skamil 13851.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13861.37Skamil 13871.37Skamil _exit(exitval_child2); 13881.37Skamil } 13891.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13901.37Skamil 13911.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13921.61Skre TWAIT_REQUIRE_SUCCESS( 13931.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13941.37Skamil 13951.37Skamil validate_status_exited(status, exitval_child1); 13961.37Skamil 13971.37Skamil DPRINTF("Notify that child1 is dead\n"); 13981.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13991.37Skamil 14001.37Skamil DPRINTF("Wait for exiting of child2\n"); 14011.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 14021.37Skamil} 14031.37Skamil 14041.37Skamil/// ---------------------------------------------------------------------------- 14051.37Skamil 14061.40Skamilstatic void 14071.40Skamiltraceme_vfork_raise(int sigval) 14081.40Skamil{ 14091.46Skamil const int exitval = 5, exitval_watcher = 10; 14101.46Skamil pid_t child, parent, watcher, wpid; 14111.46Skamil int rv; 14121.40Skamil#if defined(TWAIT_HAVE_STATUS) 14131.40Skamil int status; 14141.85Skamil 14151.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 14161.85Skamil volatile int expect_core; 14171.85Skamil 14181.85Skamil switch (sigval) { 14191.85Skamil case SIGABRT: 14201.85Skamil case SIGTRAP: 14211.85Skamil case SIGBUS: 14221.85Skamil case SIGILL: 14231.85Skamil case SIGFPE: 14241.85Skamil case SIGSEGV: 14251.85Skamil expect_core = 1; 14261.85Skamil break; 14271.85Skamil default: 14281.85Skamil expect_core = 0; 14291.85Skamil break; 14301.85Skamil } 14311.40Skamil#endif 14321.40Skamil 14331.46Skamil /* 14341.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14351.46Skamil * the SIGKILL signal to it. 14361.46Skamil * 14371.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14381.46Skamil * simpler to reparent this process to initproc and forget about it. 14391.46Skamil */ 14401.46Skamil if (sigval == SIGSTOP) { 14411.46Skamil parent = getpid(); 14421.46Skamil 14431.46Skamil watcher = fork(); 14441.46Skamil ATF_REQUIRE(watcher != 1); 14451.46Skamil if (watcher == 0) { 14461.46Skamil /* Double fork(2) trick to reparent to initproc */ 14471.46Skamil watcher = fork(); 14481.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14491.46Skamil if (watcher != 0) 14501.46Skamil _exit(exitval_watcher); 14511.46Skamil 14521.46Skamil child = await_stopped_child(parent); 14531.46Skamil 14541.46Skamil errno = 0; 14551.46Skamil rv = kill(child, SIGKILL); 14561.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14571.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14581.46Skamil 14591.46Skamil /* This exit value will be collected by initproc */ 14601.46Skamil _exit(0); 14611.46Skamil } 14621.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14631.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14641.61Skre watcher); 14651.46Skamil 14661.46Skamil validate_status_exited(status, exitval_watcher); 14671.46Skamil 14681.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14691.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14701.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14711.46Skamil } 14721.46Skamil 14731.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14741.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14751.40Skamil if (child == 0) { 14761.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14771.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14781.40Skamil 14791.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14801.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14811.40Skamil 14821.40Skamil switch (sigval) { 14831.46Skamil case SIGSTOP: 14841.40Skamil case SIGKILL: 14851.40Skamil case SIGABRT: 14861.40Skamil case SIGHUP: 14871.85Skamil case SIGTRAP: 14881.85Skamil case SIGBUS: 14891.85Skamil case SIGILL: 14901.85Skamil case SIGFPE: 14911.85Skamil case SIGSEGV: 14921.40Skamil /* NOTREACHED */ 14931.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14941.70Smrg __unreachable(); 14951.40Skamil default: 14961.40Skamil DPRINTF("Before exiting of the child process\n"); 14971.40Skamil _exit(exitval); 14981.40Skamil } 14991.40Skamil } 15001.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15011.40Skamil 15021.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15031.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15041.40Skamil 15051.40Skamil switch (sigval) { 15061.40Skamil case SIGKILL: 15071.40Skamil case SIGABRT: 15081.40Skamil case SIGHUP: 15091.85Skamil case SIGTRAP: 15101.85Skamil case SIGBUS: 15111.85Skamil case SIGILL: 15121.85Skamil case SIGFPE: 15131.85Skamil case SIGSEGV: 15141.40Skamil validate_status_signaled(status, sigval, expect_core); 15151.40Skamil break; 15161.40Skamil case SIGSTOP: 15171.46Skamil validate_status_signaled(status, SIGKILL, 0); 15181.46Skamil break; 15191.40Skamil case SIGCONT: 15201.47Skamil case SIGTSTP: 15211.47Skamil case SIGTTIN: 15221.47Skamil case SIGTTOU: 15231.40Skamil validate_status_exited(status, exitval); 15241.40Skamil break; 15251.40Skamil default: 15261.40Skamil /* NOTREACHED */ 15271.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15281.40Skamil break; 15291.40Skamil } 15301.40Skamil 15311.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15321.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15331.40Skamil} 15341.40Skamil 15351.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15361.61SkreATF_TC(test); \ 15371.61SkreATF_TC_HEAD(test, tc) \ 15381.61Skre{ \ 15391.61Skre atf_tc_set_md_var(tc, "descr", \ 15401.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15411.61Skre "vfork(2)ed child"); \ 15421.61Skre} \ 15431.61Skre \ 15441.61SkreATF_TC_BODY(test, tc) \ 15451.61Skre{ \ 15461.61Skre \ 15471.61Skre traceme_vfork_raise(sig); \ 15481.40Skamil} 15491.40Skamil 15501.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15511.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15521.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15531.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15541.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15551.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15561.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15571.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15581.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15591.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15601.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15611.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15621.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15631.40Skamil 15641.40Skamil/// ---------------------------------------------------------------------------- 15651.40Skamil 15661.52Skamilstatic void 15671.52Skamiltraceme_vfork_crash(int sig) 15681.41Skamil{ 15691.41Skamil pid_t child, wpid; 15701.41Skamil#if defined(TWAIT_HAVE_STATUS) 15711.41Skamil int status; 15721.41Skamil#endif 15731.41Skamil 15741.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15751.71Skamil if (sig == SIGILL) 15761.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15771.71Skamil#endif 15781.71Skamil 15791.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15801.114Skamil atf_tc_skip("FP exceptions are not supported"); 15811.114Skamil 15821.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15831.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15841.41Skamil if (child == 0) { 15851.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15861.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15871.41Skamil 15881.52Skamil DPRINTF("Before executing a trap\n"); 15891.52Skamil switch (sig) { 15901.52Skamil case SIGTRAP: 15911.52Skamil trigger_trap(); 15921.52Skamil break; 15931.52Skamil case SIGSEGV: 15941.52Skamil trigger_segv(); 15951.52Skamil break; 15961.52Skamil case SIGILL: 15971.52Skamil trigger_ill(); 15981.52Skamil break; 15991.52Skamil case SIGFPE: 16001.52Skamil trigger_fpe(); 16011.52Skamil break; 16021.52Skamil case SIGBUS: 16031.52Skamil trigger_bus(); 16041.52Skamil break; 16051.52Skamil default: 16061.52Skamil /* NOTREACHED */ 16071.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16081.52Skamil } 16091.41Skamil 16101.41Skamil /* NOTREACHED */ 16111.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16121.41Skamil } 16131.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16141.41Skamil 16151.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16161.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16171.41Skamil 16181.52Skamil validate_status_signaled(status, sig, 1); 16191.41Skamil 16201.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16211.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16221.41Skamil} 16231.41Skamil 16241.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16251.61SkreATF_TC(test); \ 16261.61SkreATF_TC_HEAD(test, tc) \ 16271.61Skre{ \ 16281.61Skre atf_tc_set_md_var(tc, "descr", \ 16291.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16301.61Skre "vfork(2)ed child"); \ 16311.61Skre} \ 16321.61Skre \ 16331.61SkreATF_TC_BODY(test, tc) \ 16341.61Skre{ \ 16351.61Skre \ 16361.61Skre traceme_vfork_crash(sig); \ 16371.52Skamil} 16381.52Skamil 16391.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16401.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16411.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16421.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16431.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16441.52Skamil 16451.41Skamil/// ---------------------------------------------------------------------------- 16461.41Skamil 16471.92Skamilstatic void 16481.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16491.92Skamil{ 16501.92Skamil pid_t child, wpid; 16511.92Skamil#if defined(TWAIT_HAVE_STATUS) 16521.92Skamil int status; 16531.92Skamil#endif 16541.92Skamil sigset_t intmask; 16551.92Skamil 16561.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16571.92Skamil if (sig == SIGILL) 16581.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16591.92Skamil#endif 16601.92Skamil 16611.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16621.114Skamil atf_tc_skip("FP exceptions are not supported"); 16631.114Skamil 16641.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16651.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16661.92Skamil if (child == 0) { 16671.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16681.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16691.92Skamil 16701.92Skamil sigemptyset(&intmask); 16711.92Skamil sigaddset(&intmask, sig); 16721.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16731.92Skamil 16741.92Skamil DPRINTF("Before executing a trap\n"); 16751.92Skamil switch (sig) { 16761.92Skamil case SIGTRAP: 16771.92Skamil trigger_trap(); 16781.92Skamil break; 16791.92Skamil case SIGSEGV: 16801.92Skamil trigger_segv(); 16811.92Skamil break; 16821.92Skamil case SIGILL: 16831.92Skamil trigger_ill(); 16841.92Skamil break; 16851.92Skamil case SIGFPE: 16861.92Skamil trigger_fpe(); 16871.92Skamil break; 16881.92Skamil case SIGBUS: 16891.92Skamil trigger_bus(); 16901.92Skamil break; 16911.92Skamil default: 16921.92Skamil /* NOTREACHED */ 16931.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16941.92Skamil } 16951.92Skamil 16961.92Skamil /* NOTREACHED */ 16971.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16981.92Skamil } 16991.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17001.92Skamil 17011.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17021.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17031.92Skamil 17041.92Skamil validate_status_signaled(status, sig, 1); 17051.92Skamil 17061.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17071.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17081.92Skamil} 17091.92Skamil 17101.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 17111.92SkamilATF_TC(test); \ 17121.92SkamilATF_TC_HEAD(test, tc) \ 17131.92Skamil{ \ 17141.92Skamil atf_tc_set_md_var(tc, "descr", \ 17151.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17161.92Skamil "vfork(2)ed child with a masked signal"); \ 17171.92Skamil} \ 17181.92Skamil \ 17191.92SkamilATF_TC_BODY(test, tc) \ 17201.92Skamil{ \ 17211.92Skamil \ 17221.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17231.92Skamil} 17241.92Skamil 17251.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17261.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17271.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17281.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17291.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17301.92Skamil 17311.92Skamil/// ---------------------------------------------------------------------------- 17321.92Skamil 17331.92Skamilstatic void 17341.92Skamiltraceme_vfork_signalignored_crash(int sig) 17351.92Skamil{ 17361.92Skamil pid_t child, wpid; 17371.92Skamil#if defined(TWAIT_HAVE_STATUS) 17381.92Skamil int status; 17391.92Skamil#endif 17401.92Skamil struct sigaction sa; 17411.92Skamil 17421.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17431.92Skamil if (sig == SIGILL) 17441.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17451.92Skamil#endif 17461.92Skamil 17471.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17481.114Skamil atf_tc_skip("FP exceptions are not supported"); 17491.114Skamil 17501.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17511.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17521.92Skamil if (child == 0) { 17531.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17541.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17551.92Skamil 17561.92Skamil memset(&sa, 0, sizeof(sa)); 17571.92Skamil sa.sa_handler = SIG_IGN; 17581.92Skamil sigemptyset(&sa.sa_mask); 17591.92Skamil 17601.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17611.92Skamil 17621.92Skamil DPRINTF("Before executing a trap\n"); 17631.92Skamil switch (sig) { 17641.92Skamil case SIGTRAP: 17651.92Skamil trigger_trap(); 17661.92Skamil break; 17671.92Skamil case SIGSEGV: 17681.92Skamil trigger_segv(); 17691.92Skamil break; 17701.92Skamil case SIGILL: 17711.92Skamil trigger_ill(); 17721.92Skamil break; 17731.92Skamil case SIGFPE: 17741.92Skamil trigger_fpe(); 17751.92Skamil break; 17761.92Skamil case SIGBUS: 17771.92Skamil trigger_bus(); 17781.92Skamil break; 17791.92Skamil default: 17801.92Skamil /* NOTREACHED */ 17811.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17821.92Skamil } 17831.92Skamil 17841.92Skamil /* NOTREACHED */ 17851.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17861.92Skamil } 17871.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17881.92Skamil 17891.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17901.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17911.92Skamil 17921.92Skamil validate_status_signaled(status, sig, 1); 17931.92Skamil 17941.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17951.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17961.92Skamil} 17971.92Skamil 17981.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17991.92SkamilATF_TC(test); \ 18001.92SkamilATF_TC_HEAD(test, tc) \ 18011.92Skamil{ \ 18021.92Skamil atf_tc_set_md_var(tc, "descr", \ 18031.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 18041.92Skamil "vfork(2)ed child with ignored signal"); \ 18051.92Skamil} \ 18061.92Skamil \ 18071.92SkamilATF_TC_BODY(test, tc) \ 18081.92Skamil{ \ 18091.92Skamil \ 18101.92Skamil traceme_vfork_signalignored_crash(sig); \ 18111.92Skamil} 18121.92Skamil 18131.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 18141.92Skamil SIGTRAP) 18151.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 18161.92Skamil SIGSEGV) 18171.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 18181.92Skamil SIGILL) 18191.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 18201.92Skamil SIGFPE) 18211.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 18221.92Skamil SIGBUS) 18231.92Skamil 18241.92Skamil/// ---------------------------------------------------------------------------- 18251.92Skamil 18261.96Skamilstatic void 18271.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18281.43Skamil{ 18291.43Skamil const int sigval = SIGTRAP; 18301.43Skamil pid_t child, wpid; 18311.43Skamil#if defined(TWAIT_HAVE_STATUS) 18321.43Skamil int status; 18331.43Skamil#endif 18341.96Skamil struct sigaction sa; 18351.61Skre struct ptrace_siginfo info; 18361.96Skamil sigset_t intmask; 18371.96Skamil struct kinfo_proc2 kp; 18381.96Skamil size_t len = sizeof(kp); 18391.96Skamil 18401.96Skamil int name[6]; 18411.96Skamil const size_t namelen = __arraycount(name); 18421.96Skamil ki_sigset_t kp_sigmask; 18431.96Skamil ki_sigset_t kp_sigignore; 18441.43Skamil 18451.43Skamil memset(&info, 0, sizeof(info)); 18461.43Skamil 18471.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18481.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18491.43Skamil if (child == 0) { 18501.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18511.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18521.43Skamil 18531.96Skamil if (masked) { 18541.96Skamil sigemptyset(&intmask); 18551.96Skamil sigaddset(&intmask, sigval); 18561.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18571.96Skamil } 18581.96Skamil 18591.96Skamil if (ignored) { 18601.96Skamil memset(&sa, 0, sizeof(sa)); 18611.96Skamil sa.sa_handler = SIG_IGN; 18621.96Skamil sigemptyset(&sa.sa_mask); 18631.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18641.96Skamil } 18651.96Skamil 18661.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18671.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18681.43Skamil 18691.43Skamil /* NOTREACHED */ 18701.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18711.43Skamil } 18721.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18731.43Skamil 18741.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18751.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18761.43Skamil 18771.43Skamil validate_status_stopped(status, sigval); 18781.43Skamil 18791.96Skamil name[0] = CTL_KERN, 18801.96Skamil name[1] = KERN_PROC2, 18811.96Skamil name[2] = KERN_PROC_PID; 18821.96Skamil name[3] = getpid(); 18831.96Skamil name[4] = sizeof(kp); 18841.96Skamil name[5] = 1; 18851.96Skamil 18861.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18871.96Skamil 18881.96Skamil if (masked) 18891.96Skamil kp_sigmask = kp.p_sigmask; 18901.96Skamil 18911.96Skamil if (ignored) 18921.96Skamil kp_sigignore = kp.p_sigignore; 18931.96Skamil 18941.96Skamil name[3] = getpid(); 18951.96Skamil 18961.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18971.96Skamil 18981.96Skamil if (masked) { 18991.96Skamil DPRINTF("kp_sigmask=" 19001.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19011.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 19021.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 19031.96Skamil 19041.96Skamil DPRINTF("kp.p_sigmask=" 19051.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19061.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 19071.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 19081.96Skamil 19091.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 19101.96Skamil sizeof(kp_sigmask))); 19111.96Skamil } 19121.96Skamil 19131.96Skamil if (ignored) { 19141.96Skamil DPRINTF("kp_sigignore=" 19151.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19161.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 19171.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 19181.96Skamil 19191.96Skamil DPRINTF("kp.p_sigignore=" 19201.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19211.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 19221.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19231.96Skamil 19241.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19251.96Skamil sizeof(kp_sigignore))); 19261.96Skamil } 19271.96Skamil 19281.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19291.61Skre SYSCALL_REQUIRE( 19301.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19311.43Skamil 19321.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19331.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19341.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19351.43Skamil info.psi_siginfo.si_errno); 19361.43Skamil 19371.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19381.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19391.43Skamil 19401.43Skamil DPRINTF("Before resuming the child process where it left off and " 19411.43Skamil "without signal to be sent\n"); 19421.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19431.43Skamil 19441.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19451.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19461.43Skamil 19471.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19481.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19491.43Skamil} 19501.43Skamil 19511.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19521.96SkamilATF_TC(test); \ 19531.96SkamilATF_TC_HEAD(test, tc) \ 19541.96Skamil{ \ 19551.96Skamil atf_tc_set_md_var(tc, "descr", \ 19561.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19571.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19581.96Skamil masked ? " with ignored signal" : ""); \ 19591.96Skamil} \ 19601.96Skamil \ 19611.96SkamilATF_TC_BODY(test, tc) \ 19621.96Skamil{ \ 19631.96Skamil \ 19641.96Skamil traceme_vfork_exec(masked, ignored); \ 19651.96Skamil} 19661.96Skamil 19671.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19681.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19691.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19701.96Skamil 19711.43Skamil/// ---------------------------------------------------------------------------- 19721.43Skamil 19731.1Skamil#if defined(TWAIT_HAVE_PID) 19741.51Skamilstatic void 19751.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19761.59Skamil{ 19771.94Skamil const int sigval = SIGSTOP; 19781.59Skamil struct msg_fds parent_tracee, parent_tracer; 19791.59Skamil const int exitval = 10; 19801.59Skamil pid_t tracee, tracer, wpid; 19811.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19821.59Skamil#if defined(TWAIT_HAVE_STATUS) 19831.59Skamil int status; 19841.59Skamil#endif 19851.94Skamil struct sigaction sa; 19861.59Skamil struct ptrace_siginfo info; 19871.94Skamil sigset_t intmask; 19881.94Skamil struct kinfo_proc2 kp; 19891.94Skamil size_t len = sizeof(kp); 19901.94Skamil 19911.94Skamil int name[6]; 19921.94Skamil const size_t namelen = __arraycount(name); 19931.94Skamil ki_sigset_t kp_sigmask; 19941.94Skamil ki_sigset_t kp_sigignore; 19951.61Skre 19961.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19971.71Skamil if (sig == SIGILL) 19981.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19991.71Skamil#endif 20001.71Skamil 20011.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 20021.114Skamil atf_tc_skip("FP exceptions are not supported"); 20031.114Skamil 20041.59Skamil memset(&info, 0, sizeof(info)); 20051.59Skamil 20061.59Skamil DPRINTF("Spawn tracee\n"); 20071.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 20081.59Skamil tracee = atf_utils_fork(); 20091.59Skamil if (tracee == 0) { 20101.59Skamil // Wait for parent to let us crash 20111.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 20121.61Skre 20131.94Skamil if (masked) { 20141.94Skamil sigemptyset(&intmask); 20151.94Skamil sigaddset(&intmask, sig); 20161.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 20171.94Skamil } 20181.94Skamil 20191.94Skamil if (ignored) { 20201.94Skamil memset(&sa, 0, sizeof(sa)); 20211.94Skamil sa.sa_handler = SIG_IGN; 20221.94Skamil sigemptyset(&sa.sa_mask); 20231.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20241.94Skamil } 20251.94Skamil 20261.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20271.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20281.94Skamil 20291.59Skamil DPRINTF("Before executing a trap\n"); 20301.59Skamil switch (sig) { 20311.59Skamil case SIGTRAP: 20321.59Skamil trigger_trap(); 20331.59Skamil break; 20341.59Skamil case SIGSEGV: 20351.59Skamil trigger_segv(); 20361.59Skamil break; 20371.59Skamil case SIGILL: 20381.59Skamil trigger_ill(); 20391.59Skamil break; 20401.59Skamil case SIGFPE: 20411.59Skamil trigger_fpe(); 20421.59Skamil break; 20431.59Skamil case SIGBUS: 20441.59Skamil trigger_bus(); 20451.59Skamil break; 20461.59Skamil default: 20471.59Skamil /* NOTREACHED */ 20481.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20491.59Skamil } 20501.59Skamil 20511.59Skamil /* NOTREACHED */ 20521.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20531.59Skamil } 20541.59Skamil 20551.59Skamil DPRINTF("Spawn debugger\n"); 20561.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20571.59Skamil tracer = atf_utils_fork(); 20581.59Skamil if (tracer == 0) { 20591.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20601.59Skamil tracer = atf_utils_fork(); 20611.59Skamil if (tracer != 0) 20621.61Skre _exit(exitval); 20631.59Skamil 20641.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20651.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20661.59Skamil 20671.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20681.59Skamil FORKEE_REQUIRE_SUCCESS( 20691.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20701.59Skamil 20711.59Skamil forkee_status_stopped(status, SIGSTOP); 20721.59Skamil 20731.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20741.94Skamil "traced process\n"); 20751.94Skamil SYSCALL_REQUIRE( 20761.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20771.94Skamil 20781.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20791.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20801.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20811.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20821.94Skamil 20831.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20841.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20851.94Skamil 20861.59Skamil /* Resume tracee with PT_CONTINUE */ 20871.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20881.59Skamil 20891.59Skamil /* Inform parent that tracer has attached to tracee */ 20901.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20911.59Skamil 20921.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20931.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20941.59Skamil 20951.59Skamil /* Wait for tracee and assert that it exited */ 20961.59Skamil FORKEE_REQUIRE_SUCCESS( 20971.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20981.59Skamil 20991.94Skamil forkee_status_stopped(status, sigval); 21001.94Skamil 21011.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21021.94Skamil "traced process\n"); 21031.94Skamil SYSCALL_REQUIRE( 21041.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21051.94Skamil 21061.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21071.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21081.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 21091.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21101.94Skamil 21111.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 21121.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 21131.94Skamil 21141.94Skamil name[0] = CTL_KERN, 21151.94Skamil name[1] = KERN_PROC2, 21161.94Skamil name[2] = KERN_PROC_PID; 21171.94Skamil name[3] = tracee; 21181.94Skamil name[4] = sizeof(kp); 21191.94Skamil name[5] = 1; 21201.94Skamil 21211.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21221.94Skamil 21231.94Skamil if (masked) 21241.94Skamil kp_sigmask = kp.p_sigmask; 21251.94Skamil 21261.94Skamil if (ignored) 21271.94Skamil kp_sigignore = kp.p_sigignore; 21281.94Skamil 21291.94Skamil /* Resume tracee with PT_CONTINUE */ 21301.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21311.94Skamil 21321.94Skamil /* Wait for tracee and assert that it exited */ 21331.94Skamil FORKEE_REQUIRE_SUCCESS( 21341.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21351.94Skamil 21361.93Skamil forkee_status_stopped(status, sig); 21371.59Skamil 21381.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21391.61Skre "traced process\n"); 21401.61Skre SYSCALL_REQUIRE( 21411.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21421.59Skamil 21431.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21441.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21451.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21461.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21471.59Skamil 21481.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21491.94Skamil 21501.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21511.94Skamil 21521.94Skamil if (masked) { 21531.94Skamil DPRINTF("kp_sigmask=" 21541.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21551.94Skamil PRIx32 "\n", 21561.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21571.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21581.94Skamil 21591.94Skamil DPRINTF("kp.p_sigmask=" 21601.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21611.94Skamil PRIx32 "\n", 21621.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21631.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21641.94Skamil 21651.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21661.94Skamil sizeof(kp_sigmask))); 21671.94Skamil } 21681.94Skamil 21691.94Skamil if (ignored) { 21701.94Skamil DPRINTF("kp_sigignore=" 21711.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21721.94Skamil PRIx32 "\n", 21731.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21741.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21751.94Skamil 21761.94Skamil DPRINTF("kp.p_sigignore=" 21771.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21781.94Skamil PRIx32 "\n", 21791.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21801.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21811.94Skamil 21821.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21831.94Skamil sizeof(kp_sigignore))); 21841.94Skamil } 21851.94Skamil 21861.59Skamil switch (sig) { 21871.59Skamil case SIGTRAP: 21881.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21891.59Skamil break; 21901.59Skamil case SIGSEGV: 21911.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21921.59Skamil break; 21931.71Skamil case SIGILL: 21941.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21951.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21961.71Skamil break; 21971.59Skamil case SIGFPE: 21981.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21991.59Skamil break; 22001.59Skamil case SIGBUS: 22011.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 22021.59Skamil break; 22031.59Skamil } 22041.59Skamil 22051.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 22061.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 22071.93Skamil FORKEE_REQUIRE_SUCCESS( 22081.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22091.59Skamil 22101.93Skamil forkee_status_signaled(status, SIGKILL, 0); 22111.59Skamil 22121.71Skamil /* Inform parent that tracer is exiting normally */ 22131.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 22141.71Skamil 22151.59Skamil DPRINTF("Before exiting of the tracer process\n"); 22161.59Skamil _exit(0 /* collect by initproc */); 22171.59Skamil } 22181.59Skamil 22191.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 22201.59Skamil "calling %s()\n", TWAIT_FNAME); 22211.59Skamil TWAIT_REQUIRE_SUCCESS( 22221.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22231.59Skamil 22241.59Skamil validate_status_exited(status, exitval); 22251.59Skamil 22261.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22271.59Skamil TWAIT_FNAME); 22281.59Skamil TWAIT_REQUIRE_SUCCESS( 22291.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22301.59Skamil 22311.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22321.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22331.59Skamil 22341.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22351.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22361.59Skamil 22371.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22381.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22391.59Skamil 22401.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22411.59Skamil TWAIT_FNAME); 22421.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22431.59Skamil 22441.59Skamil validate_status_signaled(status, SIGKILL, 0); 22451.59Skamil 22461.71Skamil DPRINTF("Await normal exit of tracer\n"); 22471.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22481.71Skamil 22491.59Skamil msg_close(&parent_tracer); 22501.59Skamil msg_close(&parent_tracee); 22511.59Skamil} 22521.59Skamil 22531.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22541.61SkreATF_TC(test); \ 22551.61SkreATF_TC_HEAD(test, tc) \ 22561.61Skre{ \ 22571.61Skre atf_tc_set_md_var(tc, "descr", \ 22581.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22591.94Skamil "the debuggee"); \ 22601.61Skre} \ 22611.61Skre \ 22621.61SkreATF_TC_BODY(test, tc) \ 22631.61Skre{ \ 22641.61Skre \ 22651.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22661.59Skamil} 22671.59Skamil 22681.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22691.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22701.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22711.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22721.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22731.94Skamil 22741.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22751.94SkamilATF_TC(test); \ 22761.94SkamilATF_TC_HEAD(test, tc) \ 22771.94Skamil{ \ 22781.94Skamil atf_tc_set_md_var(tc, "descr", \ 22791.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22801.94Skamil "the debuggee with masked signal"); \ 22811.94Skamil} \ 22821.94Skamil \ 22831.94SkamilATF_TC_BODY(test, tc) \ 22841.94Skamil{ \ 22851.94Skamil \ 22861.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22871.94Skamil} 22881.94Skamil 22891.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22901.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22911.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22921.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22931.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22941.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22951.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22961.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22971.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22981.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22991.94Skamil 23001.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 23011.94SkamilATF_TC(test); \ 23021.94SkamilATF_TC_HEAD(test, tc) \ 23031.94Skamil{ \ 23041.94Skamil atf_tc_set_md_var(tc, "descr", \ 23051.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 23061.94Skamil "the debuggee with signal ignored"); \ 23071.94Skamil} \ 23081.94Skamil \ 23091.94SkamilATF_TC_BODY(test, tc) \ 23101.94Skamil{ \ 23111.94Skamil \ 23121.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 23131.94Skamil} 23141.94Skamil 23151.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23161.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 23171.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23181.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 23191.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23201.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 23211.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23221.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23231.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23241.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23251.59Skamil#endif 23261.59Skamil 23271.59Skamil/// ---------------------------------------------------------------------------- 23281.59Skamil 23291.59Skamil#if defined(TWAIT_HAVE_PID) 23301.59Skamilstatic void 23311.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23321.67Skamil bool stopped) 23331.1Skamil{ 23341.51Skamil /* 23351.51Skamil * notimeout - disable timeout in await zombie function 23361.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23371.67Skamil * stopped - attach to a stopped process 23381.51Skamil */ 23391.1Skamil 23401.1Skamil struct msg_fds parent_tracee, parent_tracer; 23411.1Skamil const int exitval_tracee = 5; 23421.1Skamil const int exitval_tracer = 10; 23431.1Skamil pid_t tracee, tracer, wpid; 23441.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23451.1Skamil#if defined(TWAIT_HAVE_STATUS) 23461.1Skamil int status; 23471.1Skamil#endif 23481.1Skamil 23491.67Skamil /* 23501.67Skamil * Only a subset of options are supported. 23511.67Skamil */ 23521.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23531.67Skamil (!notimeout && unrelated && !stopped) || 23541.67Skamil (notimeout && !unrelated && !stopped) || 23551.67Skamil (!notimeout && unrelated && stopped)); 23561.67Skamil 23571.13Schristos DPRINTF("Spawn tracee\n"); 23581.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23591.1Skamil tracee = atf_utils_fork(); 23601.1Skamil if (tracee == 0) { 23611.67Skamil if (stopped) { 23621.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23631.67Skamil raise(SIGSTOP); 23641.67Skamil } 23651.67Skamil 23661.1Skamil // Wait for parent to let us exit 23671.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23681.1Skamil _exit(exitval_tracee); 23691.1Skamil } 23701.1Skamil 23711.13Schristos DPRINTF("Spawn debugger\n"); 23721.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23731.1Skamil tracer = atf_utils_fork(); 23741.1Skamil if (tracer == 0) { 23751.51Skamil if(unrelated) { 23761.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23771.51Skamil tracer = atf_utils_fork(); 23781.51Skamil if (tracer != 0) 23791.51Skamil _exit(exitval_tracer); 23801.51Skamil } 23811.51Skamil 23821.67Skamil if (stopped) { 23831.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23841.67Skamil await_stopped(tracee); 23851.67Skamil } 23861.67Skamil 23871.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23881.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23891.1Skamil 23901.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23911.1Skamil FORKEE_REQUIRE_SUCCESS( 23921.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23931.1Skamil 23941.1Skamil forkee_status_stopped(status, SIGSTOP); 23951.1Skamil 23961.1Skamil /* Resume tracee with PT_CONTINUE */ 23971.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23981.1Skamil 23991.1Skamil /* Inform parent that tracer has attached to tracee */ 24001.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 24011.1Skamil 24021.1Skamil /* Wait for parent to tell use that tracee should have exited */ 24031.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 24041.1Skamil 24051.1Skamil /* Wait for tracee and assert that it exited */ 24061.1Skamil FORKEE_REQUIRE_SUCCESS( 24071.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24081.1Skamil 24091.1Skamil forkee_status_exited(status, exitval_tracee); 24101.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 24111.1Skamil 24121.13Schristos DPRINTF("Before exiting of the tracer process\n"); 24131.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 24141.51Skamil } 24151.51Skamil 24161.51Skamil if (unrelated) { 24171.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 24181.51Skamil "calling %s()\n", TWAIT_FNAME); 24191.51Skamil TWAIT_REQUIRE_SUCCESS( 24201.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 24211.51Skamil 24221.51Skamil validate_status_exited(status, exitval_tracer); 24231.51Skamil 24241.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24251.51Skamil TWAIT_FNAME); 24261.51Skamil TWAIT_REQUIRE_SUCCESS( 24271.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24281.1Skamil } 24291.1Skamil 24301.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24311.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24321.1Skamil 24331.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24341.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24351.1Skamil 24361.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24371.51Skamil if (notimeout) 24381.26Skamil await_zombie_raw(tracee, 0); 24391.26Skamil else 24401.26Skamil await_zombie(tracee); 24411.1Skamil 24421.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24431.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24441.1Skamil TWAIT_FNAME); 24451.1Skamil TWAIT_REQUIRE_SUCCESS( 24461.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24471.1Skamil 24481.51Skamil if (unrelated) { 24491.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24501.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24511.51Skamil } else { 24521.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24531.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24541.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24551.59Skamil "%s()\n", TWAIT_FNAME); 24561.51Skamil 24571.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24581.59Skamil "tracee\n"); 24591.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24601.51Skamil tracer); 24611.1Skamil 24621.51Skamil validate_status_exited(status, exitval_tracer); 24631.51Skamil } 24641.1Skamil 24651.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24661.1Skamil TWAIT_FNAME); 24671.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24681.1Skamil 24691.1Skamil validate_status_exited(status, exitval_tracee); 24701.1Skamil 24711.1Skamil msg_close(&parent_tracer); 24721.1Skamil msg_close(&parent_tracee); 24731.1Skamil} 24741.26Skamil 24751.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24761.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24771.51Skamil{ 24781.51Skamil atf_tc_set_md_var(tc, "descr", 24791.51Skamil "Assert that tracer sees process termination before the parent"); 24801.51Skamil} 24811.51Skamil 24821.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24831.26Skamil{ 24841.26Skamil 24851.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24861.26Skamil} 24871.26Skamil 24881.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24891.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24901.1Skamil{ 24911.1Skamil atf_tc_set_md_var(tc, "descr", 24921.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24931.51Skamil "process and no other error is reported"); 24941.1Skamil} 24951.1Skamil 24961.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24971.1Skamil{ 24981.51Skamil time_t start, end; 24991.51Skamil double diff; 25001.51Skamil unsigned long N = 0; 25011.1Skamil 25021.51Skamil /* 25031.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 25041.51Skamil * This test body isn't specific to this race, however it's just good 25051.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 25061.51Skamil */ 25071.1Skamil 25081.51Skamil start = time(NULL); 25091.51Skamil while (true) { 25101.51Skamil DPRINTF("Step: %lu\n", N); 25111.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 25121.67Skamil false); 25131.51Skamil end = time(NULL); 25141.51Skamil diff = difftime(end, start); 25151.51Skamil if (diff >= 5.0) 25161.51Skamil break; 25171.51Skamil ++N; 25181.1Skamil } 25191.51Skamil DPRINTF("Iterations: %lu\n", N); 25201.51Skamil} 25211.1Skamil 25221.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25231.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25241.51Skamil{ 25251.51Skamil atf_tc_set_md_var(tc, "descr", 25261.51Skamil "Assert that tracer sees process termination before the parent"); 25271.51Skamil} 25281.1Skamil 25291.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25301.51Skamil{ 25311.1Skamil 25321.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25331.67Skamil} 25341.67Skamil 25351.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25361.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25371.67Skamil{ 25381.67Skamil atf_tc_set_md_var(tc, "descr", 25391.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25401.67Skamil} 25411.67Skamil 25421.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25431.67Skamil{ 25441.67Skamil 25451.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25461.1Skamil} 25471.1Skamil#endif 25481.1Skamil 25491.51Skamil/// ---------------------------------------------------------------------------- 25501.51Skamil 25511.66Skamilstatic void 25521.66Skamilparent_attach_to_its_child(bool stopped) 25531.1Skamil{ 25541.1Skamil struct msg_fds parent_tracee; 25551.1Skamil const int exitval_tracee = 5; 25561.1Skamil pid_t tracee, wpid; 25571.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25581.1Skamil#if defined(TWAIT_HAVE_STATUS) 25591.1Skamil int status; 25601.1Skamil#endif 25611.1Skamil 25621.13Schristos DPRINTF("Spawn tracee\n"); 25631.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25641.1Skamil tracee = atf_utils_fork(); 25651.1Skamil if (tracee == 0) { 25661.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25671.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25681.1Skamil 25691.66Skamil if (stopped) { 25701.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25711.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25721.66Skamil } 25731.66Skamil 25741.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25751.1Skamil /* Wait for message from the parent */ 25761.1Skamil _exit(exitval_tracee); 25771.1Skamil } 25781.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25791.57Skamil 25801.66Skamil if (stopped) { 25811.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25821.66Skamil await_stopped(tracee); 25831.66Skamil } 25841.66Skamil 25851.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25861.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25871.1Skamil 25881.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25891.1Skamil TWAIT_FNAME); 25901.1Skamil TWAIT_REQUIRE_SUCCESS( 25911.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25921.1Skamil 25931.1Skamil validate_status_stopped(status, SIGSTOP); 25941.1Skamil 25951.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25971.1Skamil 25981.13Schristos DPRINTF("Let the tracee exit now\n"); 25991.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 26001.1Skamil 26011.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 26021.1Skamil TWAIT_REQUIRE_SUCCESS( 26031.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 26041.1Skamil 26051.1Skamil validate_status_exited(status, exitval_tracee); 26061.1Skamil 26071.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 26081.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26091.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 26101.1Skamil 26111.1Skamil msg_close(&parent_tracee); 26121.1Skamil} 26131.1Skamil 26141.66SkamilATF_TC(parent_attach_to_its_child); 26151.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 26161.66Skamil{ 26171.66Skamil atf_tc_set_md_var(tc, "descr", 26181.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 26191.66Skamil} 26201.66Skamil 26211.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26221.66Skamil{ 26231.66Skamil 26241.66Skamil parent_attach_to_its_child(false); 26251.66Skamil} 26261.66Skamil 26271.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26281.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26291.66Skamil{ 26301.66Skamil atf_tc_set_md_var(tc, "descr", 26311.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26321.66Skamil} 26331.66Skamil 26341.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26351.66Skamil{ 26361.66Skamil 26371.66Skamil parent_attach_to_its_child(true); 26381.66Skamil} 26391.66Skamil 26401.51Skamil/// ---------------------------------------------------------------------------- 26411.51Skamil 26421.65Skamilstatic void 26431.65Skamilchild_attach_to_its_parent(bool stopped) 26441.1Skamil{ 26451.1Skamil struct msg_fds parent_tracee; 26461.1Skamil const int exitval_tracer = 5; 26471.1Skamil pid_t tracer, wpid; 26481.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26491.1Skamil#if defined(TWAIT_HAVE_STATUS) 26501.1Skamil int status; 26511.1Skamil#endif 26521.1Skamil 26531.13Schristos DPRINTF("Spawn tracer\n"); 26541.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26551.1Skamil tracer = atf_utils_fork(); 26561.1Skamil if (tracer == 0) { 26571.1Skamil /* Wait for message from the parent */ 26581.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26591.1Skamil 26601.65Skamil if (stopped) { 26611.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26621.65Skamil getppid()); 26631.65Skamil await_stopped(getppid()); 26641.65Skamil } 26651.65Skamil 26661.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26671.1Skamil getppid()); 26681.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26691.1Skamil 26701.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26711.1Skamil TWAIT_FNAME); 26721.1Skamil FORKEE_REQUIRE_SUCCESS( 26731.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26741.1Skamil 26751.1Skamil forkee_status_stopped(status, SIGSTOP); 26761.1Skamil 26771.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26781.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26791.1Skamil != -1); 26801.1Skamil 26811.1Skamil /* Tell parent we are ready */ 26821.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26831.1Skamil 26841.1Skamil _exit(exitval_tracer); 26851.1Skamil } 26861.1Skamil 26871.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26881.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26891.65Skamil 26901.65Skamil if (stopped) { 26911.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26921.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26931.65Skamil } 26941.65Skamil 26951.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26961.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26971.1Skamil 26981.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26991.1Skamil TWAIT_REQUIRE_SUCCESS( 27001.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 27011.1Skamil 27021.1Skamil validate_status_exited(status, exitval_tracer); 27031.1Skamil 27041.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 27051.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 27061.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 27071.1Skamil 27081.1Skamil msg_close(&parent_tracee); 27091.1Skamil} 27101.1Skamil 27111.65SkamilATF_TC(child_attach_to_its_parent); 27121.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 27131.65Skamil{ 27141.65Skamil atf_tc_set_md_var(tc, "descr", 27151.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 27161.65Skamil} 27171.65Skamil 27181.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 27191.65Skamil{ 27201.65Skamil 27211.65Skamil child_attach_to_its_parent(false); 27221.65Skamil} 27231.65Skamil 27241.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27251.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27261.65Skamil{ 27271.65Skamil atf_tc_set_md_var(tc, "descr", 27281.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27291.65Skamil} 27301.65Skamil 27311.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27321.65Skamil{ 27331.65Skamil /* 27341.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27351.65Skamil * this causes a pipe (established from atf-run) to be broken. 27361.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27371.65Skamil * 27381.65Skamil * As a workaround spawn this test as a subprocess. 27391.65Skamil */ 27401.65Skamil 27411.65Skamil const int exitval = 15; 27421.65Skamil pid_t child, wpid; 27431.65Skamil#if defined(TWAIT_HAVE_STATUS) 27441.65Skamil int status; 27451.65Skamil#endif 27461.65Skamil 27471.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27481.65Skamil if (child == 0) { 27491.65Skamil child_attach_to_its_parent(true); 27501.65Skamil _exit(exitval); 27511.65Skamil } else { 27521.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27531.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27541.65Skamil 27551.65Skamil validate_status_exited(status, exitval); 27561.65Skamil 27571.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27581.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27591.65Skamil } 27601.65Skamil} 27611.65Skamil 27621.51Skamil/// ---------------------------------------------------------------------------- 27631.51Skamil 27641.1Skamil#if defined(TWAIT_HAVE_PID) 27651.1Skamil 27661.51Skamilenum tracee_sees_its_original_parent_type { 27671.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27681.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27691.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27701.51Skamil}; 27711.51Skamil 27721.51Skamilstatic void 27731.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27741.1Skamil{ 27751.1Skamil struct msg_fds parent_tracer, parent_tracee; 27761.1Skamil const int exitval_tracee = 5; 27771.1Skamil const int exitval_tracer = 10; 27781.1Skamil pid_t parent, tracee, tracer, wpid; 27791.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27801.1Skamil#if defined(TWAIT_HAVE_STATUS) 27811.1Skamil int status; 27821.1Skamil#endif 27831.51Skamil /* sysctl(3) - kinfo_proc2 */ 27841.51Skamil int name[CTL_MAXNAME]; 27851.51Skamil struct kinfo_proc2 kp; 27861.51Skamil size_t len = sizeof(kp); 27871.51Skamil unsigned int namelen; 27881.51Skamil 27891.51Skamil /* procfs - status */ 27901.51Skamil FILE *fp; 27911.51Skamil struct stat st; 27921.51Skamil const char *fname = "/proc/curproc/status"; 27931.51Skamil char s_executable[MAXPATHLEN]; 27941.51Skamil int s_pid, s_ppid; 27951.51Skamil int rv; 27961.51Skamil 27971.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27981.61Skre SYSCALL_REQUIRE( 27991.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 28001.61Skre if (rv != 0) 28011.51Skamil atf_tc_skip("/proc/curproc/status not found"); 28021.51Skamil } 28031.1Skamil 28041.13Schristos DPRINTF("Spawn tracee\n"); 28051.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 28061.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 28071.1Skamil tracee = atf_utils_fork(); 28081.1Skamil if (tracee == 0) { 28091.1Skamil parent = getppid(); 28101.1Skamil 28111.1Skamil /* Emit message to the parent */ 28121.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 28131.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 28141.1Skamil 28151.51Skamil switch (type) { 28161.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 28171.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 28181.51Skamil break; 28191.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 28201.51Skamil namelen = 0; 28211.51Skamil name[namelen++] = CTL_KERN; 28221.51Skamil name[namelen++] = KERN_PROC2; 28231.51Skamil name[namelen++] = KERN_PROC_PID; 28241.51Skamil name[namelen++] = getpid(); 28251.51Skamil name[namelen++] = len; 28261.51Skamil name[namelen++] = 1; 28271.51Skamil 28281.61Skre FORKEE_ASSERT_EQ( 28291.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28301.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28311.51Skamil break; 28321.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28331.51Skamil /* 28341.51Skamil * Format: 28351.51Skamil * EXECUTABLE PID PPID ... 28361.51Skamil */ 28371.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28381.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28391.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28401.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28411.51Skamil break; 28421.51Skamil } 28431.1Skamil 28441.1Skamil _exit(exitval_tracee); 28451.1Skamil } 28461.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28471.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28481.1Skamil 28491.13Schristos DPRINTF("Spawn debugger\n"); 28501.1Skamil tracer = atf_utils_fork(); 28511.1Skamil if (tracer == 0) { 28521.1Skamil /* No IPC to communicate with the child */ 28531.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28541.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28551.1Skamil 28561.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28571.1Skamil FORKEE_REQUIRE_SUCCESS( 28581.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28591.1Skamil 28601.1Skamil forkee_status_stopped(status, SIGSTOP); 28611.1Skamil 28621.1Skamil /* Resume tracee with PT_CONTINUE */ 28631.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28641.1Skamil 28651.1Skamil /* Inform parent that tracer has attached to tracee */ 28661.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28671.1Skamil 28681.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28691.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28701.1Skamil 28711.1Skamil /* Wait for tracee and assert that it exited */ 28721.1Skamil FORKEE_REQUIRE_SUCCESS( 28731.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28741.1Skamil 28751.1Skamil forkee_status_exited(status, exitval_tracee); 28761.1Skamil 28771.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28781.1Skamil _exit(exitval_tracer); 28791.1Skamil } 28801.1Skamil 28811.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28821.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28831.1Skamil 28841.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28851.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28861.1Skamil 28871.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28881.1Skamil await_zombie(tracee); 28891.1Skamil 28901.13Schristos DPRINTF("Assert that there is no status about tracee - " 28911.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28921.1Skamil TWAIT_REQUIRE_SUCCESS( 28931.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28941.1Skamil 28951.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28961.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28971.1Skamil 28981.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 29001.1Skamil tracer); 29011.1Skamil 29021.1Skamil validate_status_exited(status, exitval_tracer); 29031.1Skamil 29041.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 29051.1Skamil TWAIT_FNAME); 29061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 29071.1Skamil tracee); 29081.1Skamil 29091.1Skamil validate_status_exited(status, exitval_tracee); 29101.1Skamil 29111.1Skamil msg_close(&parent_tracer); 29121.1Skamil msg_close(&parent_tracee); 29131.1Skamil} 29141.1Skamil 29151.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 29161.61SkreATF_TC(test); \ 29171.61SkreATF_TC_HEAD(test, tc) \ 29181.61Skre{ \ 29191.61Skre atf_tc_set_md_var(tc, "descr", \ 29201.61Skre "Assert that tracee sees its original parent when being traced " \ 29211.61Skre "(check " descr ")"); \ 29221.61Skre} \ 29231.61Skre \ 29241.61SkreATF_TC_BODY(test, tc) \ 29251.61Skre{ \ 29261.61Skre \ 29271.61Skre tracee_sees_its_original_parent(type); \ 29281.1Skamil} 29291.1Skamil 29301.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29311.51Skamil tracee_sees_its_original_parent_getppid, 29321.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29331.51Skamil "getppid(2)"); 29341.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29351.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29361.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29371.51Skamil "sysctl(3) and kinfo_proc2"); 29381.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29391.51Skamil tracee_sees_its_original_parent_procfs_status, 29401.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29411.51Skamil "the status file in procfs"); 29421.1Skamil#endif 29431.1Skamil 29441.51Skamil/// ---------------------------------------------------------------------------- 29451.1Skamil 29461.53Skamilstatic void 29471.53Skamileventmask_preserved(int event) 29481.1Skamil{ 29491.1Skamil const int exitval = 5; 29501.1Skamil const int sigval = SIGSTOP; 29511.1Skamil pid_t child, wpid; 29521.1Skamil#if defined(TWAIT_HAVE_STATUS) 29531.1Skamil int status; 29541.1Skamil#endif 29551.1Skamil ptrace_event_t set_event, get_event; 29561.1Skamil const int len = sizeof(ptrace_event_t); 29571.1Skamil 29581.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29591.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29601.1Skamil if (child == 0) { 29611.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29621.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29631.1Skamil 29641.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29651.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29661.1Skamil 29671.13Schristos DPRINTF("Before exiting of the child process\n"); 29681.1Skamil _exit(exitval); 29691.1Skamil } 29701.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29711.1Skamil 29721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29741.1Skamil 29751.1Skamil validate_status_stopped(status, sigval); 29761.1Skamil 29771.53Skamil set_event.pe_set_event = event; 29781.61Skre SYSCALL_REQUIRE( 29791.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29801.61Skre SYSCALL_REQUIRE( 29811.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29821.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29831.125Skamil get_event.pe_set_event); 29841.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29851.1Skamil 29861.13Schristos DPRINTF("Before resuming the child process where it left off and " 29871.1Skamil "without signal to be sent\n"); 29881.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29891.1Skamil 29901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29921.1Skamil 29931.1Skamil validate_status_exited(status, exitval); 29941.1Skamil 29951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29961.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29971.1Skamil} 29981.1Skamil 29991.61Skre#define EVENTMASK_PRESERVED(test, event) \ 30001.61SkreATF_TC(test); \ 30011.61SkreATF_TC_HEAD(test, tc) \ 30021.61Skre{ \ 30031.61Skre atf_tc_set_md_var(tc, "descr", \ 30041.61Skre "Verify that eventmask " #event " is preserved"); \ 30051.61Skre} \ 30061.61Skre \ 30071.61SkreATF_TC_BODY(test, tc) \ 30081.61Skre{ \ 30091.61Skre \ 30101.61Skre eventmask_preserved(event); \ 30111.1Skamil} 30121.1Skamil 30131.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 30141.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 30151.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 30161.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 30171.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 30181.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 30191.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 30201.1Skamil 30211.53Skamil/// ---------------------------------------------------------------------------- 30221.1Skamil 30231.28Skamilstatic void 30241.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 30251.105Skamil bool trackvforkdone) 30261.1Skamil{ 30271.1Skamil const int exitval = 5; 30281.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30291.1Skamil const int sigval = SIGSTOP; 30301.31Skamil pid_t child, child2 = 0, wpid; 30311.1Skamil#if defined(TWAIT_HAVE_STATUS) 30321.1Skamil int status; 30331.1Skamil#endif 30341.1Skamil ptrace_state_t state; 30351.1Skamil const int slen = sizeof(state); 30361.1Skamil ptrace_event_t event; 30371.1Skamil const int elen = sizeof(event); 30381.1Skamil 30391.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30401.124Skamil 30411.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30421.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30431.1Skamil if (child == 0) { 30441.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30451.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30461.1Skamil 30471.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30481.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30491.1Skamil 30501.125Skamil if (strcmp(fn, "spawn") == 0) { 30511.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30521.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30531.125Skamil } else { 30541.125Skamil if (strcmp(fn, "fork") == 0) { 30551.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30561.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30571.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30581.125Skamil } 30591.1Skamil 30601.124Skamil if (child2 == 0) 30611.124Skamil _exit(exitval2); 30621.124Skamil } 30631.1Skamil FORKEE_REQUIRE_SUCCESS 30641.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30651.1Skamil 30661.1Skamil forkee_status_exited(status, exitval2); 30671.1Skamil 30681.13Schristos DPRINTF("Before exiting of the child process\n"); 30691.1Skamil _exit(exitval); 30701.1Skamil } 30711.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30721.1Skamil 30731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30751.1Skamil 30761.1Skamil validate_status_stopped(status, sigval); 30771.1Skamil 30781.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30791.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30801.61Skre trackfork ? "|PTRACE_FORK" : "", 30811.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30821.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30831.30Skamil event.pe_set_event = 0; 30841.125Skamil if (trackspawn) 30851.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30861.30Skamil if (trackfork) 30871.30Skamil event.pe_set_event |= PTRACE_FORK; 30881.30Skamil if (trackvfork) 30891.30Skamil event.pe_set_event |= PTRACE_VFORK; 30901.30Skamil if (trackvforkdone) 30911.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30921.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30931.1Skamil 30941.13Schristos DPRINTF("Before resuming the child process where it left off and " 30951.1Skamil "without signal to be sent\n"); 30961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30971.1Skamil 30981.29Skamil#if defined(TWAIT_HAVE_PID) 30991.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31001.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31011.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31021.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31031.61Skre child); 31041.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 31051.61Skre child); 31061.1Skamil 31071.29Skamil validate_status_stopped(status, SIGTRAP); 31081.1Skamil 31091.61Skre SYSCALL_REQUIRE( 31101.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31111.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31121.125Skamil ATF_REQUIRE_EQ( 31131.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31141.125Skamil PTRACE_POSIX_SPAWN); 31151.125Skamil } 31161.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31171.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31181.30Skamil PTRACE_FORK); 31191.30Skamil } 31201.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31211.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31221.30Skamil PTRACE_VFORK); 31231.30Skamil } 31241.29Skamil 31251.29Skamil child2 = state.pe_other_pid; 31261.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31271.29Skamil 31281.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31291.61Skre "%d\n", TWAIT_FNAME, child2, child); 31301.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31311.29Skamil child2); 31321.1Skamil 31331.29Skamil validate_status_stopped(status, SIGTRAP); 31341.1Skamil 31351.61Skre SYSCALL_REQUIRE( 31361.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31371.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31381.125Skamil ATF_REQUIRE_EQ( 31391.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31401.125Skamil PTRACE_POSIX_SPAWN); 31411.125Skamil } 31421.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31431.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31441.30Skamil PTRACE_FORK); 31451.30Skamil } 31461.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31471.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31481.30Skamil PTRACE_VFORK); 31491.30Skamil } 31501.30Skamil 31511.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31521.29Skamil 31531.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31541.29Skamil "and without signal to be sent\n"); 31551.61Skre SYSCALL_REQUIRE( 31561.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31571.29Skamil 31581.29Skamil DPRINTF("Before resuming the child process where it left off " 31591.61Skre "and without signal to be sent\n"); 31601.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31611.30Skamil } 31621.30Skamil#endif 31631.30Skamil 31641.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31651.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31661.61Skre child); 31671.61Skre TWAIT_REQUIRE_SUCCESS( 31681.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31691.30Skamil 31701.30Skamil validate_status_stopped(status, SIGTRAP); 31711.30Skamil 31721.61Skre SYSCALL_REQUIRE( 31731.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31741.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31751.30Skamil 31761.30Skamil child2 = state.pe_other_pid; 31771.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31781.61Skre child2); 31791.30Skamil 31801.30Skamil DPRINTF("Before resuming the child process where it left off " 31811.61Skre "and without signal to be sent\n"); 31821.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31831.30Skamil } 31841.29Skamil 31851.30Skamil#if defined(TWAIT_HAVE_PID) 31861.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31871.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31881.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31891.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31901.61Skre "\n", TWAIT_FNAME); 31911.61Skre TWAIT_REQUIRE_SUCCESS( 31921.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31931.29Skamil 31941.29Skamil validate_status_exited(status, exitval2); 31951.29Skamil 31961.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31971.61Skre "process\n", TWAIT_FNAME); 31981.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31991.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 32001.29Skamil } 32011.29Skamil#endif 32021.1Skamil 32031.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 32041.1Skamil "SIGCHLD\n", TWAIT_FNAME); 32051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32061.1Skamil 32071.1Skamil validate_status_stopped(status, SIGCHLD); 32081.1Skamil 32091.13Schristos DPRINTF("Before resuming the child process where it left off and " 32101.1Skamil "without signal to be sent\n"); 32111.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 32121.1Skamil 32131.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 32141.1Skamil TWAIT_FNAME); 32151.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32161.1Skamil 32171.1Skamil validate_status_exited(status, exitval); 32181.1Skamil 32191.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 32201.1Skamil TWAIT_FNAME); 32211.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32221.1Skamil} 32231.28Skamil 32241.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 32251.61SkreATF_TC(name); \ 32261.61SkreATF_TC_HEAD(name, tc) \ 32271.61Skre{ \ 32281.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32291.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32301.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32311.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32321.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32331.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32341.61Skre} \ 32351.61Skre \ 32361.61SkreATF_TC_BODY(name, tc) \ 32371.61Skre{ \ 32381.61Skre \ 32391.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32401.32Skamil} 32411.32Skamil 32421.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32431.31Skamil#if defined(TWAIT_HAVE_PID) 32441.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32451.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32461.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32471.31Skamil#endif 32481.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32491.31Skamil#if defined(TWAIT_HAVE_PID) 32501.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32511.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32521.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32531.125Skamil#endif 32541.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32551.125Skamil#if defined(TWAIT_HAVE_PID) 32561.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32571.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32581.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32591.125Skamil#endif 32601.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32611.125Skamil#if defined(TWAIT_HAVE_PID) 32621.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32631.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32641.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32651.31Skamil#endif 32661.1Skamil 32671.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32681.31Skamil#if defined(TWAIT_HAVE_PID) 32691.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32701.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32711.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32721.31Skamil#endif 32731.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32741.31Skamil#if defined(TWAIT_HAVE_PID) 32751.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32761.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32771.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32781.31Skamil#endif 32791.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32801.125Skamil#if defined(TWAIT_HAVE_PID) 32811.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32821.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32831.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32841.110Skamil#endif 32851.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32861.124Skamil#if defined(TWAIT_HAVE_PID) 32871.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32881.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32891.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32901.124Skamil#endif 32911.125Skamil 32921.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32931.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32941.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32951.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32961.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32971.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32981.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32991.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 33001.124Skamil#if defined(TWAIT_HAVE_PID) 33011.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 33021.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 33031.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 33041.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 33051.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 33061.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 33071.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 33081.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 33091.124Skamil#endif 33101.124Skamil 33111.54Skamil/// ---------------------------------------------------------------------------- 33121.31Skamil 33131.116Skamil#if defined(TWAIT_HAVE_PID) 33141.116Skamilstatic void 33151.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 33161.116Skamil{ 33171.116Skamil const int exitval = 5; 33181.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 33191.116Skamil const int sigval = SIGSTOP; 33201.116Skamil pid_t child, child2 = 0, wpid; 33211.116Skamil#if defined(TWAIT_HAVE_STATUS) 33221.116Skamil int status; 33231.116Skamil#endif 33241.116Skamil ptrace_state_t state; 33251.116Skamil const int slen = sizeof(state); 33261.116Skamil ptrace_event_t event; 33271.116Skamil const int elen = sizeof(event); 33281.116Skamil 33291.116Skamil int op; 33301.116Skamil 33311.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33321.116Skamil 33331.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33341.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 33351.116Skamil if (child == 0) { 33361.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33371.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33381.116Skamil 33391.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33401.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 33411.116Skamil 33421.126Skamil if (strcmp(fn, "spawn") == 0) { 33431.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 33441.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 33451.126Skamil } else { 33461.126Skamil if (strcmp(fn, "fork") == 0) { 33471.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 33481.126Skamil } else { 33491.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 33501.126Skamil } 33511.116Skamil 33521.126Skamil if (child2 == 0) 33531.126Skamil _exit(exitval2); 33541.126Skamil } 33551.116Skamil 33561.116Skamil FORKEE_REQUIRE_SUCCESS 33571.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33581.116Skamil 33591.116Skamil forkee_status_exited(status, exitval2); 33601.116Skamil 33611.116Skamil DPRINTF("Before exiting of the child process\n"); 33621.116Skamil _exit(exitval); 33631.116Skamil } 33641.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33651.116Skamil 33661.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33671.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33681.116Skamil 33691.116Skamil validate_status_stopped(status, sigval); 33701.116Skamil 33711.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 33721.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 33731.126Skamil | PTRACE_VFORK_DONE; 33741.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 33751.116Skamil 33761.116Skamil DPRINTF("Before resuming the child process where it left off and " 33771.116Skamil "without signal to be sent\n"); 33781.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 33791.116Skamil 33801.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 33811.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33821.116Skamil 33831.116Skamil validate_status_stopped(status, SIGTRAP); 33841.116Skamil 33851.116Skamil SYSCALL_REQUIRE( 33861.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33871.126Skamil 33881.126Skamil if (strcmp(fn, "spawn") == 0) 33891.126Skamil op = PTRACE_POSIX_SPAWN; 33901.126Skamil else if (strcmp(fn, "fork") == 0) 33911.126Skamil op = PTRACE_FORK; 33921.126Skamil else 33931.126Skamil op = PTRACE_VFORK; 33941.126Skamil 33951.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33961.116Skamil 33971.116Skamil child2 = state.pe_other_pid; 33981.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 33991.116Skamil 34001.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 34011.126Skamil strcmp(fn, "vfork") == 0) 34021.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34031.116Skamil else 34041.116Skamil op = PT_CONTINUE; 34051.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34061.116Skamil 34071.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 34081.116Skamil TWAIT_FNAME, child2, child); 34091.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34101.116Skamil 34111.116Skamil validate_status_stopped(status, SIGTRAP); 34121.116Skamil 34131.116Skamil SYSCALL_REQUIRE( 34141.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 34151.126Skamil if (strcmp(fn, "spawn") == 0) 34161.126Skamil op = PTRACE_POSIX_SPAWN; 34171.126Skamil else if (strcmp(fn, "fork") == 0) 34181.126Skamil op = PTRACE_FORK; 34191.126Skamil else 34201.126Skamil op = PTRACE_VFORK; 34211.126Skamil 34221.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 34231.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 34241.116Skamil 34251.116Skamil DPRINTF("Before resuming the forkee process where it left off " 34261.116Skamil "and without signal to be sent\n"); 34271.116Skamil SYSCALL_REQUIRE( 34281.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 34291.116Skamil 34301.126Skamil if (strcmp(fn, "vforkdone") == 0) { 34311.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 34321.116Skamil child); 34331.116Skamil TWAIT_REQUIRE_SUCCESS( 34341.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 34351.116Skamil 34361.116Skamil validate_status_stopped(status, SIGTRAP); 34371.116Skamil 34381.116Skamil SYSCALL_REQUIRE( 34391.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 34401.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 34411.116Skamil 34421.116Skamil child2 = state.pe_other_pid; 34431.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 34441.116Skamil child2); 34451.116Skamil 34461.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34471.116Skamil DPRINTF("Before resuming the child process where it left off " 34481.116Skamil "and without signal to be sent\n"); 34491.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34501.116Skamil } 34511.116Skamil 34521.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34531.116Skamil TWAIT_FNAME); 34541.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34551.116Skamil 34561.116Skamil validate_status_exited(status, exitval2); 34571.116Skamil 34581.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 34591.116Skamil TWAIT_FNAME); 34601.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 34611.116Skamil 34621.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34631.116Skamil TWAIT_FNAME); 34641.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34651.116Skamil 34661.116Skamil if (kill_process) { 34671.116Skamil validate_status_signaled(status, SIGKILL, 0); 34681.116Skamil } else { 34691.116Skamil validate_status_exited(status, exitval); 34701.116Skamil } 34711.116Skamil 34721.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34731.116Skamil TWAIT_FNAME); 34741.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34751.116Skamil} 34761.116Skamil 34771.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 34781.116SkamilATF_TC(name); \ 34791.116SkamilATF_TC_HEAD(name, tc) \ 34801.116Skamil{ \ 34811.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 34821.126Skamil kprocess ? "killed" : "detached"); \ 34831.116Skamil} \ 34841.116Skamil \ 34851.116SkamilATF_TC_BODY(name, tc) \ 34861.116Skamil{ \ 34871.116Skamil \ 34881.126Skamil fork_detach_forker_body(event, kprocess); \ 34891.116Skamil} 34901.116Skamil 34911.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 34921.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 34931.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 34941.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 34951.126Skamil 34961.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 34971.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 34981.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 34991.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 35001.116Skamil#endif 35011.116Skamil 35021.116Skamil/// ---------------------------------------------------------------------------- 35031.116Skamil 35041.108Skamilstatic void 35051.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 35061.108Skamil{ 35071.108Skamil const int exitval = 5; 35081.108Skamil const int exitval2 = 15; 35091.108Skamil pid_t child, child2 = 0, wpid; 35101.108Skamil#if defined(TWAIT_HAVE_STATUS) 35111.108Skamil int status; 35121.108Skamil#endif 35131.108Skamil 35141.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 35151.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 35161.108Skamil if (child == 0) { 35171.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 35181.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 35191.108Skamil 35201.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 35211.108Skamil 35221.108Skamil if (child2 == 0) 35231.108Skamil _exit(exitval2); 35241.108Skamil 35251.108Skamil FORKEE_REQUIRE_SUCCESS 35261.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 35271.108Skamil 35281.108Skamil forkee_status_exited(status, exitval2); 35291.108Skamil 35301.108Skamil DPRINTF("Before exiting of the child process\n"); 35311.108Skamil _exit(exitval); 35321.108Skamil } 35331.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35341.108Skamil 35351.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 35361.108Skamil TWAIT_FNAME); 35371.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35381.108Skamil 35391.108Skamil validate_status_exited(status, exitval); 35401.108Skamil 35411.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 35421.108Skamil TWAIT_FNAME); 35431.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35441.108Skamil} 35451.108Skamil 35461.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 35471.108SkamilATF_TC(name); \ 35481.108SkamilATF_TC_HEAD(name, tc) \ 35491.108Skamil{ \ 35501.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 35511.108Skamil "called from vfork(2)ed child"); \ 35521.108Skamil} \ 35531.108Skamil \ 35541.108SkamilATF_TC_BODY(name, tc) \ 35551.108Skamil{ \ 35561.108Skamil \ 35571.108Skamil traceme_vfork_fork_body(fun); \ 35581.108Skamil} 35591.108Skamil 35601.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 35611.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 35621.108Skamil 35631.108Skamil/// ---------------------------------------------------------------------------- 35641.108Skamil 35651.54Skamilenum bytes_transfer_type { 35661.54Skamil BYTES_TRANSFER_DATA, 35671.54Skamil BYTES_TRANSFER_DATAIO, 35681.54Skamil BYTES_TRANSFER_TEXT, 35691.54Skamil BYTES_TRANSFER_TEXTIO, 35701.54Skamil BYTES_TRANSFER_AUXV 35711.54Skamil}; 35721.31Skamil 35731.54Skamilstatic int __used 35741.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 35751.54Skamil{ 35761.54Skamil int e, f, g, h; 35771.1Skamil 35781.54Skamil a *= 4; 35791.54Skamil b += 3; 35801.54Skamil c -= 2; 35811.54Skamil d /= 1; 35821.1Skamil 35831.54Skamil e = strtol("10", NULL, 10); 35841.54Skamil f = strtol("20", NULL, 10); 35851.54Skamil g = strtol("30", NULL, 10); 35861.54Skamil h = strtol("40", NULL, 10); 35871.1Skamil 35881.54Skamil return (a + b * c - d) + (e * f - g / h); 35891.1Skamil} 35901.1Skamil 35911.54Skamilstatic void 35921.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 35931.1Skamil{ 35941.1Skamil const int exitval = 5; 35951.1Skamil const int sigval = SIGSTOP; 35961.1Skamil pid_t child, wpid; 35971.54Skamil bool skip = false; 35981.1Skamil 35991.54Skamil int lookup_me = 0; 36001.54Skamil uint8_t lookup_me8 = 0; 36011.54Skamil uint16_t lookup_me16 = 0; 36021.54Skamil uint32_t lookup_me32 = 0; 36031.54Skamil uint64_t lookup_me64 = 0; 36041.1Skamil 36051.54Skamil int magic = 0x13579246; 36061.54Skamil uint8_t magic8 = 0xab; 36071.54Skamil uint16_t magic16 = 0x1234; 36081.54Skamil uint32_t magic32 = 0x98765432; 36091.54Skamil uint64_t magic64 = 0xabcdef0123456789; 36101.1Skamil 36111.54Skamil struct ptrace_io_desc io; 36121.1Skamil#if defined(TWAIT_HAVE_STATUS) 36131.1Skamil int status; 36141.1Skamil#endif 36151.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 36161.60Skre AuxInfo ai[513], *aip; 36171.55Schristos 36181.55Schristos ATF_REQUIRE(size < sizeof(ai)); 36191.1Skamil 36201.54Skamil /* Prepare variables for .TEXT transfers */ 36211.54Skamil switch (type) { 36221.54Skamil case BYTES_TRANSFER_TEXT: 36231.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 36241.54Skamil break; 36251.54Skamil case BYTES_TRANSFER_TEXTIO: 36261.54Skamil switch (size) { 36271.54Skamil case 8: 36281.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 36291.54Skamil break; 36301.54Skamil case 16: 36311.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 36321.54Skamil break; 36331.54Skamil case 32: 36341.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 36351.54Skamil break; 36361.54Skamil case 64: 36371.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 36381.54Skamil break; 36391.54Skamil } 36401.54Skamil break; 36411.54Skamil default: 36421.54Skamil break; 36431.54Skamil } 36441.1Skamil 36451.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 36461.54Skamil switch (type) { 36471.54Skamil case BYTES_TRANSFER_TEXTIO: 36481.54Skamil case BYTES_TRANSFER_DATAIO: 36491.54Skamil io.piod_op = operation; 36501.54Skamil switch (size) { 36511.54Skamil case 8: 36521.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36531.54Skamil (void *)bytes_transfer_dummy : 36541.54Skamil &lookup_me8; 36551.54Skamil io.piod_addr = &lookup_me8; 36561.54Skamil io.piod_len = sizeof(lookup_me8); 36571.54Skamil break; 36581.54Skamil case 16: 36591.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36601.54Skamil (void *)bytes_transfer_dummy : 36611.54Skamil &lookup_me16; 36621.54Skamil io.piod_addr = &lookup_me16; 36631.54Skamil io.piod_len = sizeof(lookup_me16); 36641.54Skamil break; 36651.54Skamil case 32: 36661.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36671.54Skamil (void *)bytes_transfer_dummy : 36681.54Skamil &lookup_me32; 36691.54Skamil io.piod_addr = &lookup_me32; 36701.54Skamil io.piod_len = sizeof(lookup_me32); 36711.54Skamil break; 36721.54Skamil case 64: 36731.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36741.54Skamil (void *)bytes_transfer_dummy : 36751.54Skamil &lookup_me64; 36761.54Skamil io.piod_addr = &lookup_me64; 36771.54Skamil io.piod_len = sizeof(lookup_me64); 36781.54Skamil break; 36791.54Skamil default: 36801.54Skamil break; 36811.54Skamil } 36821.54Skamil break; 36831.54Skamil case BYTES_TRANSFER_AUXV: 36841.54Skamil io.piod_op = operation; 36851.54Skamil io.piod_offs = 0; 36861.54Skamil io.piod_addr = ai; 36871.54Skamil io.piod_len = size; 36881.54Skamil break; 36891.54Skamil default: 36901.54Skamil break; 36911.1Skamil } 36921.1Skamil 36931.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36941.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36951.1Skamil if (child == 0) { 36961.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36971.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36981.1Skamil 36991.54Skamil switch (type) { 37001.54Skamil case BYTES_TRANSFER_DATA: 37011.54Skamil switch (operation) { 37021.54Skamil case PT_READ_D: 37031.54Skamil case PT_READ_I: 37041.54Skamil lookup_me = magic; 37051.54Skamil break; 37061.54Skamil default: 37071.54Skamil break; 37081.54Skamil } 37091.54Skamil break; 37101.54Skamil case BYTES_TRANSFER_DATAIO: 37111.54Skamil switch (operation) { 37121.54Skamil case PIOD_READ_D: 37131.54Skamil case PIOD_READ_I: 37141.54Skamil switch (size) { 37151.54Skamil case 8: 37161.54Skamil lookup_me8 = magic8; 37171.54Skamil break; 37181.54Skamil case 16: 37191.54Skamil lookup_me16 = magic16; 37201.54Skamil break; 37211.54Skamil case 32: 37221.54Skamil lookup_me32 = magic32; 37231.54Skamil break; 37241.54Skamil case 64: 37251.54Skamil lookup_me64 = magic64; 37261.54Skamil break; 37271.54Skamil default: 37281.54Skamil break; 37291.54Skamil } 37301.54Skamil break; 37311.54Skamil default: 37321.54Skamil break; 37331.54Skamil } 37341.54Skamil default: 37351.54Skamil break; 37361.54Skamil } 37371.54Skamil 37381.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37391.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37401.1Skamil 37411.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 37421.54Skamil switch (type) { 37431.54Skamil case BYTES_TRANSFER_DATA: 37441.54Skamil switch (operation) { 37451.54Skamil case PT_WRITE_D: 37461.54Skamil case PT_WRITE_I: 37471.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 37481.54Skamil break; 37491.54Skamil default: 37501.54Skamil break; 37511.54Skamil } 37521.54Skamil break; 37531.54Skamil case BYTES_TRANSFER_DATAIO: 37541.54Skamil switch (operation) { 37551.54Skamil case PIOD_WRITE_D: 37561.54Skamil case PIOD_WRITE_I: 37571.54Skamil switch (size) { 37581.54Skamil case 8: 37591.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 37601.54Skamil break; 37611.54Skamil case 16: 37621.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 37631.54Skamil break; 37641.54Skamil case 32: 37651.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 37661.54Skamil break; 37671.54Skamil case 64: 37681.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 37691.54Skamil break; 37701.54Skamil default: 37711.54Skamil break; 37721.54Skamil } 37731.54Skamil break; 37741.54Skamil default: 37751.54Skamil break; 37761.54Skamil } 37771.54Skamil break; 37781.54Skamil case BYTES_TRANSFER_TEXT: 37791.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 37801.54Skamil sizeof(magic)) == 0); 37811.54Skamil break; 37821.54Skamil case BYTES_TRANSFER_TEXTIO: 37831.54Skamil switch (size) { 37841.54Skamil case 8: 37851.54Skamil FORKEE_ASSERT(memcmp(&magic8, 37861.54Skamil bytes_transfer_dummy, 37871.54Skamil sizeof(magic8)) == 0); 37881.54Skamil break; 37891.54Skamil case 16: 37901.54Skamil FORKEE_ASSERT(memcmp(&magic16, 37911.54Skamil bytes_transfer_dummy, 37921.54Skamil sizeof(magic16)) == 0); 37931.54Skamil break; 37941.54Skamil case 32: 37951.54Skamil FORKEE_ASSERT(memcmp(&magic32, 37961.54Skamil bytes_transfer_dummy, 37971.54Skamil sizeof(magic32)) == 0); 37981.54Skamil break; 37991.54Skamil case 64: 38001.54Skamil FORKEE_ASSERT(memcmp(&magic64, 38011.54Skamil bytes_transfer_dummy, 38021.54Skamil sizeof(magic64)) == 0); 38031.54Skamil break; 38041.54Skamil } 38051.54Skamil break; 38061.54Skamil default: 38071.54Skamil break; 38081.54Skamil } 38091.54Skamil 38101.13Schristos DPRINTF("Before exiting of the child process\n"); 38111.1Skamil _exit(exitval); 38121.1Skamil } 38131.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 38141.1Skamil 38151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38171.1Skamil 38181.1Skamil validate_status_stopped(status, sigval); 38191.1Skamil 38201.54Skamil /* Check PaX MPROTECT */ 38211.54Skamil if (!can_we_write_to_text(child)) { 38221.54Skamil switch (type) { 38231.54Skamil case BYTES_TRANSFER_TEXTIO: 38241.54Skamil switch (operation) { 38251.54Skamil case PIOD_WRITE_D: 38261.54Skamil case PIOD_WRITE_I: 38271.54Skamil skip = true; 38281.54Skamil break; 38291.54Skamil default: 38301.54Skamil break; 38311.54Skamil } 38321.54Skamil break; 38331.54Skamil case BYTES_TRANSFER_TEXT: 38341.54Skamil switch (operation) { 38351.54Skamil case PT_WRITE_D: 38361.54Skamil case PT_WRITE_I: 38371.54Skamil skip = true; 38381.54Skamil break; 38391.54Skamil default: 38401.54Skamil break; 38411.54Skamil } 38421.54Skamil break; 38431.54Skamil default: 38441.54Skamil break; 38451.54Skamil } 38461.54Skamil } 38471.1Skamil 38481.54Skamil /* Bailout cleanly killing the child process */ 38491.54Skamil if (skip) { 38501.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 38511.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38521.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38531.54Skamil child); 38541.1Skamil 38551.54Skamil validate_status_signaled(status, SIGKILL, 0); 38561.1Skamil 38571.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 38581.54Skamil } 38591.1Skamil 38601.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 38611.54Skamil "parent=%d\n", child, getpid()); 38621.1Skamil 38631.54Skamil switch (type) { 38641.54Skamil case BYTES_TRANSFER_TEXTIO: 38651.54Skamil case BYTES_TRANSFER_DATAIO: 38661.54Skamil case BYTES_TRANSFER_AUXV: 38671.54Skamil switch (operation) { 38681.54Skamil case PIOD_WRITE_D: 38691.54Skamil case PIOD_WRITE_I: 38701.54Skamil switch (size) { 38711.54Skamil case 8: 38721.54Skamil lookup_me8 = magic8; 38731.54Skamil break; 38741.54Skamil case 16: 38751.54Skamil lookup_me16 = magic16; 38761.54Skamil break; 38771.54Skamil case 32: 38781.54Skamil lookup_me32 = magic32; 38791.54Skamil break; 38801.54Skamil case 64: 38811.54Skamil lookup_me64 = magic64; 38821.54Skamil break; 38831.54Skamil default: 38841.54Skamil break; 38851.54Skamil } 38861.54Skamil break; 38871.54Skamil default: 38881.54Skamil break; 38891.54Skamil } 38901.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 38911.54Skamil switch (operation) { 38921.54Skamil case PIOD_READ_D: 38931.54Skamil case PIOD_READ_I: 38941.54Skamil switch (size) { 38951.54Skamil case 8: 38961.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 38971.54Skamil break; 38981.54Skamil case 16: 38991.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 39001.54Skamil break; 39011.54Skamil case 32: 39021.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 39031.54Skamil break; 39041.54Skamil case 64: 39051.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 39061.54Skamil break; 39071.54Skamil default: 39081.54Skamil break; 39091.54Skamil } 39101.54Skamil break; 39111.54Skamil case PIOD_READ_AUXV: 39121.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 39131.54Skamil io.piod_len); 39141.54Skamil ATF_REQUIRE(io.piod_len > 0); 39151.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 39161.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 39171.54Skamil (long long int)aip->a_type, 39181.54Skamil (long long int)aip->a_v); 39191.54Skamil break; 39201.54Skamil default: 39211.54Skamil break; 39221.54Skamil } 39231.54Skamil break; 39241.54Skamil case BYTES_TRANSFER_TEXT: 39251.54Skamil switch (operation) { 39261.54Skamil case PT_READ_D: 39271.54Skamil case PT_READ_I: 39281.54Skamil errno = 0; 39291.54Skamil lookup_me = ptrace(operation, child, 39301.54Skamil bytes_transfer_dummy, 0); 39311.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39321.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39331.54Skamil break; 39341.54Skamil case PT_WRITE_D: 39351.54Skamil case PT_WRITE_I: 39361.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 39371.54Skamil bytes_transfer_dummy, magic) 39381.54Skamil != -1); 39391.54Skamil break; 39401.54Skamil default: 39411.54Skamil break; 39421.54Skamil } 39431.54Skamil break; 39441.54Skamil case BYTES_TRANSFER_DATA: 39451.54Skamil switch (operation) { 39461.54Skamil case PT_READ_D: 39471.54Skamil case PT_READ_I: 39481.54Skamil errno = 0; 39491.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 39501.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39511.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39521.54Skamil break; 39531.54Skamil case PT_WRITE_D: 39541.54Skamil case PT_WRITE_I: 39551.54Skamil lookup_me = magic; 39561.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 39571.54Skamil magic) != -1); 39581.54Skamil break; 39591.54Skamil default: 39601.54Skamil break; 39611.54Skamil } 39621.54Skamil break; 39631.54Skamil default: 39641.54Skamil break; 39651.54Skamil } 39661.1Skamil 39671.13Schristos DPRINTF("Before resuming the child process where it left off and " 39681.1Skamil "without signal to be sent\n"); 39691.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39701.1Skamil 39711.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39721.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39731.1Skamil 39741.1Skamil validate_status_exited(status, exitval); 39751.1Skamil 39761.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39771.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39781.1Skamil} 39791.1Skamil 39801.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 39811.61SkreATF_TC(test); \ 39821.61SkreATF_TC_HEAD(test, tc) \ 39831.61Skre{ \ 39841.61Skre atf_tc_set_md_var(tc, "descr", \ 39851.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 39861.61Skre " of type " #type); \ 39871.61Skre} \ 39881.61Skre \ 39891.61SkreATF_TC_BODY(test, tc) \ 39901.61Skre{ \ 39911.61Skre \ 39921.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 39931.1Skamil} 39941.1Skamil 39951.54Skamil// DATA 39961.1Skamil 39971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 39981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 39991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 40001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 40011.54Skamil 40021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 40031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 40041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 40051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 40061.54Skamil 40071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 40081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 40091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 40101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 40111.54Skamil 40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 40131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 40141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 40151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 40161.54Skamil 40171.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 40181.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 40191.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 40201.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 40211.54Skamil 40221.54Skamil// TEXT 40231.54Skamil 40241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 40251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 40261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 40271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 40281.54Skamil 40291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 40301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 40311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 40321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 40331.54Skamil 40341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 40351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 40361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 40371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 40381.54Skamil 40391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 40401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 40411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 40421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 40431.54Skamil 40441.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 40451.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 40461.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 40471.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 40481.1Skamil 40491.54Skamil// AUXV 40501.1Skamil 40511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 40521.1Skamil 40531.54Skamil/// ---------------------------------------------------------------------------- 40541.1Skamil 40551.101Skamilstatic void 40561.101Skamilbytes_transfer_alignment(const char *operation) 40571.101Skamil{ 40581.101Skamil const int exitval = 5; 40591.101Skamil const int sigval = SIGSTOP; 40601.101Skamil pid_t child, wpid; 40611.101Skamil#if defined(TWAIT_HAVE_STATUS) 40621.101Skamil int status; 40631.101Skamil#endif 40641.101Skamil char *buffer; 40651.101Skamil int vector; 40661.101Skamil size_t len; 40671.101Skamil size_t i; 40681.101Skamil int op; 40691.101Skamil 40701.101Skamil struct ptrace_io_desc io; 40711.101Skamil struct ptrace_siginfo info; 40721.101Skamil 40731.101Skamil memset(&io, 0, sizeof(io)); 40741.101Skamil memset(&info, 0, sizeof(info)); 40751.101Skamil 40761.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 40771.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 40781.101Skamil buffer = malloc(len); 40791.101Skamil ATF_REQUIRE(buffer != NULL); 40801.101Skamil 40811.101Skamil /* Initialize the buffer with random data */ 40821.101Skamil for (i = 0; i < len; i++) 40831.101Skamil buffer[i] = i & 0xff; 40841.101Skamil 40851.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 40861.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 40871.101Skamil if (child == 0) { 40881.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40891.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40901.101Skamil 40911.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40921.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 40931.101Skamil 40941.101Skamil DPRINTF("Before exiting of the child process\n"); 40951.101Skamil _exit(exitval); 40961.101Skamil } 40971.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 40981.101Skamil 40991.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41001.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41011.101Skamil 41021.101Skamil validate_status_stopped(status, sigval); 41031.101Skamil 41041.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 41051.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 41061.101Skamil != -1); 41071.101Skamil 41081.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 41091.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 41101.101Skamil "si_errno=%#x\n", 41111.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 41121.101Skamil info.psi_siginfo.si_errno); 41131.101Skamil 41141.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 41151.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 41161.101Skamil 41171.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 41181.101Skamil strcmp(operation, "PT_READ_D") == 0) { 41191.101Skamil if (strcmp(operation, "PT_READ_I")) 41201.101Skamil op = PT_READ_I; 41211.101Skamil else 41221.101Skamil op = PT_READ_D; 41231.101Skamil 41241.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41251.101Skamil errno = 0; 41261.101Skamil vector = ptrace(op, child, buffer + i, 0); 41271.101Skamil ATF_REQUIRE_EQ(errno, 0); 41281.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41291.101Skamil } 41301.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41311.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41321.101Skamil if (strcmp(operation, "PT_WRITE_I")) 41331.101Skamil op = PT_WRITE_I; 41341.101Skamil else 41351.101Skamil op = PT_WRITE_D; 41361.101Skamil 41371.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41381.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 41391.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 41401.101Skamil != -1); 41411.101Skamil } 41421.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41431.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41441.101Skamil if (strcmp(operation, "PIOD_READ_I")) 41451.101Skamil op = PIOD_READ_I; 41461.101Skamil else 41471.101Skamil op = PIOD_READ_D; 41481.101Skamil 41491.101Skamil io.piod_op = op; 41501.101Skamil io.piod_addr = &vector; 41511.101Skamil io.piod_len = sizeof(int); 41521.101Skamil 41531.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41541.101Skamil io.piod_offs = buffer + i; 41551.101Skamil 41561.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41571.101Skamil != -1); 41581.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41591.101Skamil } 41601.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 41611.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 41621.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 41631.101Skamil op = PIOD_WRITE_I; 41641.101Skamil else 41651.101Skamil op = PIOD_WRITE_D; 41661.101Skamil 41671.101Skamil io.piod_op = op; 41681.101Skamil io.piod_addr = &vector; 41691.101Skamil io.piod_len = sizeof(int); 41701.101Skamil 41711.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41721.101Skamil io.piod_offs = buffer + i; 41731.101Skamil 41741.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41751.101Skamil != -1); 41761.101Skamil } 41771.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 41781.101Skamil io.piod_op = PIOD_READ_AUXV; 41791.101Skamil io.piod_addr = &vector; 41801.101Skamil io.piod_len = sizeof(int); 41811.101Skamil 41821.101Skamil errno = 0; 41831.101Skamil i = 0; 41841.101Skamil /* Read the whole AUXV vector, it has no clear length */ 41851.120Skamil while (io.piod_len > 0) { 41861.101Skamil io.piod_offs = (void *)(intptr_t)i; 41871.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41881.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 41891.101Skamil ++i; 41901.101Skamil } 41911.101Skamil } 41921.101Skamil 41931.101Skamil DPRINTF("Before resuming the child process where it left off " 41941.101Skamil "and without signal to be sent\n"); 41951.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41961.101Skamil 41971.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41981.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 41991.101Skamil child); 42001.101Skamil 42011.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42021.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 42031.101Skamil} 42041.101Skamil 42051.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 42061.101SkamilATF_TC(test); \ 42071.101SkamilATF_TC_HEAD(test, tc) \ 42081.101Skamil{ \ 42091.101Skamil atf_tc_set_md_var(tc, "descr", \ 42101.101Skamil "Verify bytes transfer for potentially misaligned " \ 42111.101Skamil "operation " operation); \ 42121.101Skamil} \ 42131.101Skamil \ 42141.101SkamilATF_TC_BODY(test, tc) \ 42151.101Skamil{ \ 42161.101Skamil \ 42171.101Skamil bytes_transfer_alignment(operation); \ 42181.101Skamil} 42191.101Skamil 42201.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 42211.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 42221.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 42231.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 42241.101Skamil 42251.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 42261.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 42271.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 42281.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 42291.101Skamil 42301.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 42311.101Skamil 42321.101Skamil/// ---------------------------------------------------------------------------- 42331.101Skamil 42341.115Skamilstatic void 42351.115Skamilbytes_transfer_eof(const char *operation) 42361.115Skamil{ 42371.115Skamil const int exitval = 5; 42381.115Skamil const int sigval = SIGSTOP; 42391.115Skamil pid_t child, wpid; 42401.115Skamil#if defined(TWAIT_HAVE_STATUS) 42411.115Skamil int status; 42421.115Skamil#endif 42431.115Skamil FILE *fp; 42441.115Skamil char *p; 42451.115Skamil int vector; 42461.115Skamil int op; 42471.115Skamil 42481.115Skamil struct ptrace_io_desc io; 42491.115Skamil struct ptrace_siginfo info; 42501.115Skamil 42511.115Skamil memset(&io, 0, sizeof(io)); 42521.115Skamil memset(&info, 0, sizeof(info)); 42531.115Skamil 42541.115Skamil vector = 0; 42551.115Skamil 42561.115Skamil fp = tmpfile(); 42571.115Skamil ATF_REQUIRE(fp != NULL); 42581.115Skamil 42591.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 42601.115Skamil ATF_REQUIRE(p != MAP_FAILED); 42611.115Skamil 42621.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42631.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42641.115Skamil if (child == 0) { 42651.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42661.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42671.115Skamil 42681.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42691.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 42701.115Skamil 42711.115Skamil DPRINTF("Before exiting of the child process\n"); 42721.115Skamil _exit(exitval); 42731.115Skamil } 42741.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42751.115Skamil 42761.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42771.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42781.115Skamil 42791.115Skamil validate_status_stopped(status, sigval); 42801.115Skamil 42811.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42821.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 42831.115Skamil != -1); 42841.115Skamil 42851.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42861.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42871.115Skamil "si_errno=%#x\n", 42881.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42891.115Skamil info.psi_siginfo.si_errno); 42901.115Skamil 42911.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42921.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42931.115Skamil 42941.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 42951.115Skamil strcmp(operation, "PT_READ_D") == 0) { 42961.115Skamil if (strcmp(operation, "PT_READ_I")) 42971.115Skamil op = PT_READ_I; 42981.115Skamil else 42991.115Skamil op = PT_READ_D; 43001.115Skamil 43011.115Skamil errno = 0; 43021.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 43031.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43041.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 43051.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 43061.115Skamil if (strcmp(operation, "PT_WRITE_I")) 43071.115Skamil op = PT_WRITE_I; 43081.115Skamil else 43091.115Skamil op = PT_WRITE_D; 43101.115Skamil 43111.115Skamil errno = 0; 43121.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 43131.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43141.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 43151.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 43161.115Skamil if (strcmp(operation, "PIOD_READ_I")) 43171.115Skamil op = PIOD_READ_I; 43181.115Skamil else 43191.115Skamil op = PIOD_READ_D; 43201.115Skamil 43211.115Skamil io.piod_op = op; 43221.115Skamil io.piod_addr = &vector; 43231.115Skamil io.piod_len = sizeof(int); 43241.115Skamil io.piod_offs = p; 43251.115Skamil 43261.115Skamil errno = 0; 43271.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43281.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43291.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 43301.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 43311.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 43321.115Skamil op = PIOD_WRITE_I; 43331.115Skamil else 43341.115Skamil op = PIOD_WRITE_D; 43351.115Skamil 43361.115Skamil io.piod_op = op; 43371.115Skamil io.piod_addr = &vector; 43381.115Skamil io.piod_len = sizeof(int); 43391.115Skamil io.piod_offs = p; 43401.115Skamil 43411.115Skamil errno = 0; 43421.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43431.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43441.115Skamil } 43451.115Skamil 43461.115Skamil DPRINTF("Before resuming the child process where it left off " 43471.115Skamil "and without signal to be sent\n"); 43481.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43491.115Skamil 43501.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43511.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43521.115Skamil child); 43531.115Skamil 43541.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43551.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43561.115Skamil} 43571.115Skamil 43581.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 43591.115SkamilATF_TC(test); \ 43601.115SkamilATF_TC_HEAD(test, tc) \ 43611.115Skamil{ \ 43621.115Skamil atf_tc_set_md_var(tc, "descr", \ 43631.115Skamil "Verify bytes EOF byte transfer for the " operation \ 43641.115Skamil " operation"); \ 43651.115Skamil} \ 43661.115Skamil \ 43671.115SkamilATF_TC_BODY(test, tc) \ 43681.115Skamil{ \ 43691.115Skamil \ 43701.115Skamil bytes_transfer_eof(operation); \ 43711.115Skamil} 43721.115Skamil 43731.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 43741.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 43751.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 43761.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 43771.115Skamil 43781.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 43791.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 43801.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 43811.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 43821.115Skamil 43831.115Skamil/// ---------------------------------------------------------------------------- 43841.115Skamil 43851.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 43861.72Skamilstatic void 43871.72Skamilaccess_regs(const char *regset, const char *aux) 43881.1Skamil{ 43891.1Skamil const int exitval = 5; 43901.1Skamil const int sigval = SIGSTOP; 43911.1Skamil pid_t child, wpid; 43921.1Skamil#if defined(TWAIT_HAVE_STATUS) 43931.1Skamil int status; 43941.1Skamil#endif 43951.72Skamil#if defined(HAVE_GPREGS) 43961.72Skamil struct reg gpr; 43971.76Sscole register_t rgstr; 43981.1Skamil#endif 43991.72Skamil#if defined(HAVE_FPREGS) 44001.72Skamil struct fpreg fpr; 44011.1Skamil#endif 44021.76Sscole 44031.72Skamil#if !defined(HAVE_GPREGS) 44041.72Skamil if (strcmp(regset, "regs") == 0) 44051.72Skamil atf_tc_fail("Impossible test scenario!"); 44061.1Skamil#endif 44071.1Skamil 44081.72Skamil#if !defined(HAVE_FPREGS) 44091.72Skamil if (strcmp(regset, "fpregs") == 0) 44101.72Skamil atf_tc_fail("Impossible test scenario!"); 44111.1Skamil#endif 44121.1Skamil 44131.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44141.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44151.1Skamil if (child == 0) { 44161.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44171.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44181.1Skamil 44191.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44201.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44211.1Skamil 44221.13Schristos DPRINTF("Before exiting of the child process\n"); 44231.1Skamil _exit(exitval); 44241.1Skamil } 44251.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44261.1Skamil 44271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44291.1Skamil 44301.1Skamil validate_status_stopped(status, sigval); 44311.1Skamil 44321.1Skamil#if defined(HAVE_GPREGS) 44331.72Skamil if (strcmp(regset, "regs") == 0) { 44341.72Skamil DPRINTF("Call GETREGS for the child process\n"); 44351.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44361.72Skamil 44371.72Skamil if (strcmp(aux, "none") == 0) { 44381.72Skamil DPRINTF("Retrieved registers\n"); 44391.72Skamil } else if (strcmp(aux, "pc") == 0) { 44401.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44411.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44421.147Skamil } else if (strstr(aux, "set_pc") != NULL) { 44431.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44441.147Skamil DPRINTF("Retrieved PC %" PRIxREGISTER "\n", rgstr); 44451.147Skamil if (strstr(aux, "0x1") != NULL) { 44461.147Skamil rgstr |= 0x1; 44471.147Skamil } else if (strstr(aux, "0x3") != NULL) { 44481.147Skamil rgstr |= 0x3; 44491.147Skamil } else if (strstr(aux, "0x7") != NULL) { 44501.147Skamil rgstr |= 0x7; 44511.147Skamil } 44521.147Skamil DPRINTF("Set PC %" PRIxREGISTER "\n", rgstr); 44531.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 44541.147Skamil if (strcmp(aux, "set_pc") != 0) { 44551.147Skamil /* This call can fail with EINVAL or similar. */ 44561.147Skamil ptrace(PT_SETREGS, child, &gpr, 0); 44571.147Skamil } 44581.72Skamil } else if (strcmp(aux, "sp") == 0) { 44591.72Skamil rgstr = PTRACE_REG_SP(&gpr); 44601.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44611.72Skamil } else if (strcmp(aux, "intrv") == 0) { 44621.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 44631.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44641.72Skamil } else if (strcmp(aux, "setregs") == 0) { 44651.72Skamil DPRINTF("Call SETREGS for the child process\n"); 44661.72Skamil SYSCALL_REQUIRE( 44671.147Skamil ptrace(PT_SETREGS, child, &gpr, 0) != -1); 44681.72Skamil } 44691.72Skamil } 44701.1Skamil#endif 44711.1Skamil 44721.72Skamil#if defined(HAVE_FPREGS) 44731.72Skamil if (strcmp(regset, "fpregs") == 0) { 44741.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 44751.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 44761.72Skamil 44771.72Skamil if (strcmp(aux, "getfpregs") == 0) { 44781.72Skamil DPRINTF("Retrieved FP registers\n"); 44791.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 44801.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 44811.72Skamil SYSCALL_REQUIRE( 44821.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 44831.72Skamil } 44841.1Skamil } 44851.1Skamil#endif 44861.1Skamil 44871.13Schristos DPRINTF("Before resuming the child process where it left off and " 44881.1Skamil "without signal to be sent\n"); 44891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44901.1Skamil 44911.147Skamil if (strstr(aux, "unaligned") != NULL) { 44921.147Skamil DPRINTF("Before resuming the child process where it left off " 44931.147Skamil "and without signal to be sent\n"); 44941.147Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 44951.147Skamil 44961.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44971.147Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 44981.147Skamil child); 44991.147Skamil 45001.147Skamil validate_status_signaled(status, SIGKILL, 0); 45011.147Skamil 45021.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45031.147Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 45041.147Skamil wpid = TWAIT_GENERIC(child, &status, 0)); 45051.147Skamil } else { 45061.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45071.147Skamil TWAIT_REQUIRE_SUCCESS( 45081.147Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 45091.1Skamil 45101.147Skamil validate_status_exited(status, exitval); 45111.1Skamil 45121.147Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45131.147Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 45141.147Skamil wpid = TWAIT_GENERIC(child, &status, 0)); 45151.147Skamil } 45161.1Skamil} 45171.1Skamil 45181.72Skamil#define ACCESS_REGS(test, regset, aux) \ 45191.72SkamilATF_TC(test); \ 45201.72SkamilATF_TC_HEAD(test, tc) \ 45211.72Skamil{ \ 45221.72Skamil atf_tc_set_md_var(tc, "descr", \ 45231.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 45241.72Skamil} \ 45251.72Skamil \ 45261.72SkamilATF_TC_BODY(test, tc) \ 45271.72Skamil{ \ 45281.72Skamil \ 45291.72Skamil access_regs(regset, aux); \ 45301.1Skamil} 45311.1Skamil#endif 45321.1Skamil 45331.72Skamil#if defined(HAVE_GPREGS) 45341.72SkamilACCESS_REGS(access_regs1, "regs", "none") 45351.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 45361.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 45371.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 45381.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 45391.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 45401.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x1, "regs", "set_pc+unaligned+0x1") 45411.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x3, "regs", "set_pc+unaligned+0x3") 45421.147SkamilACCESS_REGS(access_regs_set_unaligned_pc_0x7, "regs", "set_pc+unaligned+0x7") 45431.1Skamil#endif 45441.1Skamil#if defined(HAVE_FPREGS) 45451.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 45461.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 45471.1Skamil#endif 45481.1Skamil 45491.72Skamil/// ---------------------------------------------------------------------------- 45501.1Skamil 45511.1Skamil#if defined(PT_STEP) 45521.1Skamilstatic void 45531.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 45541.1Skamil{ 45551.1Skamil const int exitval = 5; 45561.1Skamil const int sigval = SIGSTOP; 45571.1Skamil pid_t child, wpid; 45581.1Skamil#if defined(TWAIT_HAVE_STATUS) 45591.1Skamil int status; 45601.1Skamil#endif 45611.1Skamil int happy; 45621.95Skamil struct sigaction sa; 45631.81Skamil struct ptrace_siginfo info; 45641.95Skamil sigset_t intmask; 45651.95Skamil struct kinfo_proc2 kp; 45661.95Skamil size_t len = sizeof(kp); 45671.95Skamil 45681.95Skamil int name[6]; 45691.95Skamil const size_t namelen = __arraycount(name); 45701.95Skamil ki_sigset_t kp_sigmask; 45711.95Skamil ki_sigset_t kp_sigignore; 45721.1Skamil 45731.1Skamil#if defined(__arm__) 45741.1Skamil /* PT_STEP not supported on arm 32-bit */ 45751.1Skamil atf_tc_expect_fail("PR kern/52119"); 45761.1Skamil#endif 45771.1Skamil 45781.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45791.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45801.1Skamil if (child == 0) { 45811.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45821.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45831.1Skamil 45841.95Skamil if (masked) { 45851.95Skamil sigemptyset(&intmask); 45861.95Skamil sigaddset(&intmask, SIGTRAP); 45871.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 45881.95Skamil } 45891.95Skamil 45901.95Skamil if (ignored) { 45911.95Skamil memset(&sa, 0, sizeof(sa)); 45921.95Skamil sa.sa_handler = SIG_IGN; 45931.95Skamil sigemptyset(&sa.sa_mask); 45941.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 45951.95Skamil } 45961.95Skamil 45971.1Skamil happy = check_happy(999); 45981.1Skamil 45991.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 46001.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 46011.1Skamil 46021.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 46031.1Skamil 46041.13Schristos DPRINTF("Before exiting of the child process\n"); 46051.1Skamil _exit(exitval); 46061.1Skamil } 46071.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 46081.1Skamil 46091.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46111.1Skamil 46121.1Skamil validate_status_stopped(status, sigval); 46131.1Skamil 46141.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46151.81Skamil SYSCALL_REQUIRE( 46161.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46171.81Skamil 46181.81Skamil DPRINTF("Before checking siginfo_t\n"); 46191.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 46201.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 46211.81Skamil 46221.95Skamil name[0] = CTL_KERN, 46231.95Skamil name[1] = KERN_PROC2, 46241.95Skamil name[2] = KERN_PROC_PID; 46251.95Skamil name[3] = child; 46261.95Skamil name[4] = sizeof(kp); 46271.95Skamil name[5] = 1; 46281.95Skamil 46291.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46301.95Skamil 46311.95Skamil if (masked) 46321.95Skamil kp_sigmask = kp.p_sigmask; 46331.95Skamil 46341.95Skamil if (ignored) 46351.95Skamil kp_sigignore = kp.p_sigignore; 46361.95Skamil 46371.1Skamil while (N --> 0) { 46381.2Skamil if (setstep) { 46391.13Schristos DPRINTF("Before resuming the child process where it " 46401.2Skamil "left off and without signal to be sent (use " 46411.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 46421.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 46431.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 46441.2Skamil != -1); 46451.2Skamil } else { 46461.13Schristos DPRINTF("Before resuming the child process where it " 46471.2Skamil "left off and without signal to be sent (use " 46481.2Skamil "PT_STEP)\n"); 46491.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 46501.2Skamil != -1); 46511.2Skamil } 46521.1Skamil 46531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 46551.1Skamil child); 46561.1Skamil 46571.1Skamil validate_status_stopped(status, SIGTRAP); 46581.2Skamil 46591.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46601.81Skamil SYSCALL_REQUIRE( 46611.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46621.81Skamil 46631.81Skamil DPRINTF("Before checking siginfo_t\n"); 46641.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46651.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 46661.81Skamil 46671.2Skamil if (setstep) { 46681.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 46691.2Skamil } 46701.95Skamil 46711.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46721.95Skamil 46731.95Skamil if (masked) { 46741.95Skamil DPRINTF("kp_sigmask=" 46751.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46761.95Skamil PRIx32 "\n", 46771.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 46781.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 46791.95Skamil 46801.95Skamil DPRINTF("kp.p_sigmask=" 46811.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46821.95Skamil PRIx32 "\n", 46831.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 46841.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 46851.95Skamil 46861.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 46871.95Skamil sizeof(kp_sigmask))); 46881.95Skamil } 46891.95Skamil 46901.95Skamil if (ignored) { 46911.95Skamil DPRINTF("kp_sigignore=" 46921.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46931.95Skamil PRIx32 "\n", 46941.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 46951.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 46961.95Skamil 46971.95Skamil DPRINTF("kp.p_sigignore=" 46981.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46991.95Skamil PRIx32 "\n", 47001.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 47011.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 47021.95Skamil 47031.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 47041.95Skamil sizeof(kp_sigignore))); 47051.95Skamil } 47061.1Skamil } 47071.1Skamil 47081.13Schristos DPRINTF("Before resuming the child process where it left off and " 47091.1Skamil "without signal to be sent\n"); 47101.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 47111.1Skamil 47121.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47131.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47141.1Skamil 47151.1Skamil validate_status_exited(status, exitval); 47161.1Skamil 47171.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47181.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47191.1Skamil} 47201.1Skamil 47211.73Skamil#define PTRACE_STEP(test, N, setstep) \ 47221.73SkamilATF_TC(test); \ 47231.73SkamilATF_TC_HEAD(test, tc) \ 47241.73Skamil{ \ 47251.73Skamil atf_tc_set_md_var(tc, "descr", \ 47261.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 47271.73Skamil} \ 47281.73Skamil \ 47291.73SkamilATF_TC_BODY(test, tc) \ 47301.73Skamil{ \ 47311.73Skamil \ 47321.95Skamil ptrace_step(N, setstep, false, false); \ 47331.1Skamil} 47341.1Skamil 47351.73SkamilPTRACE_STEP(step1, 1, 0) 47361.73SkamilPTRACE_STEP(step2, 2, 0) 47371.73SkamilPTRACE_STEP(step3, 3, 0) 47381.73SkamilPTRACE_STEP(step4, 4, 0) 47391.73SkamilPTRACE_STEP(setstep1, 1, 1) 47401.73SkamilPTRACE_STEP(setstep2, 2, 1) 47411.73SkamilPTRACE_STEP(setstep3, 3, 1) 47421.73SkamilPTRACE_STEP(setstep4, 4, 1) 47431.95Skamil 47441.95SkamilATF_TC(step_signalmasked); 47451.95SkamilATF_TC_HEAD(step_signalmasked, tc) 47461.95Skamil{ 47471.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 47481.95Skamil} 47491.95Skamil 47501.95SkamilATF_TC_BODY(step_signalmasked, tc) 47511.95Skamil{ 47521.95Skamil 47531.95Skamil ptrace_step(1, 0, true, false); 47541.95Skamil} 47551.95Skamil 47561.95SkamilATF_TC(step_signalignored); 47571.95SkamilATF_TC_HEAD(step_signalignored, tc) 47581.95Skamil{ 47591.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 47601.95Skamil} 47611.95Skamil 47621.95SkamilATF_TC_BODY(step_signalignored, tc) 47631.95Skamil{ 47641.95Skamil 47651.95Skamil ptrace_step(1, 0, false, true); 47661.95Skamil} 47671.1Skamil#endif 47681.1Skamil 47691.73Skamil/// ---------------------------------------------------------------------------- 47701.1Skamil 47711.75Skamilstatic void 47721.75Skamilptrace_kill(const char *type) 47731.1Skamil{ 47741.75Skamil const int sigval = SIGSTOP; 47751.1Skamil pid_t child, wpid; 47761.1Skamil#if defined(TWAIT_HAVE_STATUS) 47771.1Skamil int status; 47781.1Skamil#endif 47791.1Skamil 47801.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47811.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47821.1Skamil if (child == 0) { 47831.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47841.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47851.1Skamil 47861.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47871.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47881.1Skamil 47891.1Skamil /* NOTREACHED */ 47901.1Skamil FORKEE_ASSERTX(0 && 47911.1Skamil "Child should be terminated by a signal from its parent"); 47921.1Skamil } 47931.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47941.1Skamil 47951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47971.1Skamil 47981.1Skamil validate_status_stopped(status, sigval); 47991.1Skamil 48001.75Skamil DPRINTF("Before killing the child process with %s\n", type); 48011.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 48021.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 48031.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 48041.75Skamil kill(child, SIGKILL); 48051.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 48061.75Skamil setpgid(child, 0); 48071.75Skamil killpg(getpgid(child), SIGKILL); 48081.75Skamil } 48091.1Skamil 48101.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48121.1Skamil 48131.75Skamil validate_status_signaled(status, SIGKILL, 0); 48141.1Skamil 48151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48161.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48171.1Skamil} 48181.1Skamil 48191.75Skamil#define PTRACE_KILL(test, type) \ 48201.75SkamilATF_TC(test); \ 48211.75SkamilATF_TC_HEAD(test, tc) \ 48221.75Skamil{ \ 48231.75Skamil atf_tc_set_md_var(tc, "descr", \ 48241.75Skamil "Verify killing the child with " type); \ 48251.75Skamil} \ 48261.75Skamil \ 48271.75SkamilATF_TC_BODY(test, tc) \ 48281.75Skamil{ \ 48291.75Skamil \ 48301.75Skamil ptrace_kill(type); \ 48311.1Skamil} 48321.1Skamil 48331.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 48341.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 48351.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 48361.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 48371.1Skamil 48381.75Skamil/// ---------------------------------------------------------------------------- 48391.1Skamil 48401.143Skamilstatic int lwpinfo_thread_sigmask[] = {SIGXCPU, SIGPIPE, SIGALRM, SIGURG}; 48411.143Skamil 48421.143Skamilstatic pthread_mutex_t lwpinfo_thread_mtx = PTHREAD_MUTEX_INITIALIZER; 48431.143Skamilstatic pthread_cond_t lwpinfo_thread_cnd = PTHREAD_COND_INITIALIZER; 48441.143Skamilstatic volatile size_t lwpinfo_thread_done; 48451.143Skamil 48461.143Skamilstatic void * 48471.143Skamillwpinfo_thread(void *arg) 48481.143Skamil{ 48491.143Skamil sigset_t s; 48501.143Skamil volatile void **tcb; 48511.143Skamil 48521.143Skamil tcb = (volatile void **)arg; 48531.143Skamil 48541.145Skamil *tcb = _lwp_getprivate(); 48551.143Skamil DPRINTF("Storing tcb[] = %p from thread %d\n", *tcb, _lwp_self()); 48561.143Skamil 48571.143Skamil pthread_setname_np(pthread_self(), "thread %d", 48581.143Skamil (void *)(intptr_t)_lwp_self()); 48591.143Skamil 48601.143Skamil sigemptyset(&s); 48611.143Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 48621.143Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 48631.143Skamil lwpinfo_thread_done++; 48641.143Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 48651.143Skamil pthread_cond_signal(&lwpinfo_thread_cnd); 48661.143Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 48671.143Skamil 48681.143Skamil return infinite_thread(NULL); 48691.143Skamil} 48701.143Skamil 48711.77Skamilstatic void 48721.143Skamiltraceme_lwpinfo(const size_t threads, const char *iter) 48731.1Skamil{ 48741.1Skamil const int sigval = SIGSTOP; 48751.77Skamil const int sigval2 = SIGINT; 48761.1Skamil pid_t child, wpid; 48771.1Skamil#if defined(TWAIT_HAVE_STATUS) 48781.1Skamil int status; 48791.1Skamil#endif 48801.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 48811.143Skamil struct ptrace_lwpstatus lwpstatus = {0}; 48821.77Skamil struct ptrace_siginfo info; 48831.143Skamil void *private; 48841.143Skamil char *name; 48851.143Skamil char namebuf[PL_LNAMELEN]; 48861.143Skamil volatile void *tcb[4]; 48871.143Skamil bool found; 48881.143Skamil sigset_t s; 48891.77Skamil 48901.77Skamil /* Maximum number of supported threads in this test */ 48911.143Skamil pthread_t t[__arraycount(tcb) - 1]; 48921.143Skamil size_t n, m; 48931.143Skamil int rv; 48941.143Skamil size_t bytes_read; 48951.143Skamil 48961.143Skamil struct ptrace_io_desc io; 48971.143Skamil sigset_t sigmask; 48981.77Skamil 48991.143Skamil ATF_REQUIRE(__arraycount(t) >= threads); 49001.143Skamil memset(tcb, 0, sizeof(tcb)); 49011.1Skamil 49021.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 49031.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 49041.1Skamil if (child == 0) { 49051.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 49061.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 49071.1Skamil 49081.145Skamil tcb[0] = _lwp_getprivate(); 49091.143Skamil DPRINTF("Storing tcb[0] = %p\n", tcb[0]); 49101.143Skamil 49111.143Skamil pthread_setname_np(pthread_self(), "thread %d", 49121.143Skamil (void *)(intptr_t)_lwp_self()); 49131.143Skamil 49141.143Skamil sigemptyset(&s); 49151.143Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 49161.143Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 49171.143Skamil 49181.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49191.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 49201.1Skamil 49211.77Skamil for (n = 0; n < threads; n++) { 49221.143Skamil rv = pthread_create(&t[n], NULL, lwpinfo_thread, 49231.143Skamil &tcb[n + 1]); 49241.77Skamil FORKEE_ASSERT(rv == 0); 49251.77Skamil } 49261.77Skamil 49271.143Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 49281.143Skamil while (lwpinfo_thread_done < threads) { 49291.143Skamil pthread_cond_wait(&lwpinfo_thread_cnd, 49301.143Skamil &lwpinfo_thread_mtx); 49311.143Skamil } 49321.143Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 49331.143Skamil 49341.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 49351.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 49361.77Skamil 49371.77Skamil /* NOTREACHED */ 49381.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 49391.1Skamil } 49401.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 49411.1Skamil 49421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49441.1Skamil 49451.1Skamil validate_status_stopped(status, sigval); 49461.1Skamil 49471.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 49481.77Skamil SYSCALL_REQUIRE( 49491.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 49501.77Skamil 49511.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49521.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 49531.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49541.77Skamil info.psi_siginfo.si_errno); 49551.77Skamil 49561.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 49571.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 49581.77Skamil 49591.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 49601.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49611.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 49621.143Skamil != -1); 49631.1Skamil 49641.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 49651.143Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 49661.1Skamil 49671.143Skamil DPRINTF("Assert that lwp thread %d received event " 49681.143Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 49691.143Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 49701.143Skamil 49711.143Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 49721.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPSTATUS " 49731.143Skamil "for child\n"); 49741.143Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 49751.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, &lwpstatus, 49761.143Skamil sizeof(lwpstatus)) != -1); 49771.143Skamil } 49781.1Skamil 49791.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49801.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 49811.143Skamil != -1); 49821.1Skamil 49831.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 49841.143Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 49851.143Skamil } else { 49861.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 49871.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 49881.143Skamil sizeof(lwpstatus)) != -1); 49891.143Skamil 49901.143Skamil DPRINTF("Assert that there exists a single thread only %d\n", lwpstatus.pl_lwpid); 49911.143Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 49921.143Skamil 49931.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 49941.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 49951.143Skamil sizeof(lwpstatus)) != -1); 49961.143Skamil 49971.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 49981.143Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 49991.143Skamil } 50001.1Skamil 50011.13Schristos DPRINTF("Before resuming the child process where it left off and " 50021.1Skamil "without signal to be sent\n"); 50031.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 50041.1Skamil 50051.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50071.1Skamil 50081.77Skamil validate_status_stopped(status, sigval2); 50091.77Skamil 50101.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 50111.77Skamil SYSCALL_REQUIRE( 50121.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 50131.77Skamil 50141.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50151.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 50161.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50171.77Skamil info.psi_siginfo.si_errno); 50181.77Skamil 50191.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 50201.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 50211.77Skamil 50221.77Skamil memset(&lwp, 0, sizeof(lwp)); 50231.143Skamil memset(&lwpstatus, 0, sizeof(lwpstatus)); 50241.143Skamil 50251.143Skamil memset(&io, 0, sizeof(io)); 50261.143Skamil 50271.143Skamil bytes_read = 0; 50281.143Skamil io.piod_op = PIOD_READ_D; 50291.143Skamil io.piod_len = sizeof(tcb); 50301.143Skamil 50311.143Skamil do { 50321.143Skamil io.piod_addr = (char *)&tcb + bytes_read; 50331.143Skamil io.piod_offs = io.piod_addr; 50341.143Skamil 50351.143Skamil rv = ptrace(PT_IO, child, &io, sizeof(io)); 50361.143Skamil ATF_REQUIRE(rv != -1 && io.piod_len != 0); 50371.143Skamil 50381.143Skamil bytes_read += io.piod_len; 50391.143Skamil io.piod_len = sizeof(tcb) - bytes_read; 50401.143Skamil } while (bytes_read < sizeof(tcb)); 50411.77Skamil 50421.77Skamil for (n = 0; n <= threads; n++) { 50431.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 50441.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50451.143Skamil "child\n"); 50461.143Skamil SYSCALL_REQUIRE( 50471.143Skamil ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 50481.143Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50491.143Skamil 50501.143Skamil DPRINTF("Assert that the thread exists\n"); 50511.143Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 50521.143Skamil 50531.143Skamil DPRINTF("Assert that lwp thread %d received expected " 50541.143Skamil "event\n", lwp.pl_lwpid); 50551.143Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 50561.143Skamil info.psi_lwpid == lwp.pl_lwpid ? 50571.143Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 50581.143Skamil 50591.143Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 50601.143Skamil DPRINTF("Before calling ptrace(2) with " 50611.143Skamil "PT_LWPSTATUS for child\n"); 50621.143Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 50631.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, 50641.143Skamil &lwpstatus, sizeof(lwpstatus)) != -1); 50651.143Skamil 50661.143Skamil goto check_lwpstatus; 50671.143Skamil } 50681.143Skamil } else { 50691.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for " 50701.143Skamil "child\n"); 50711.143Skamil SYSCALL_REQUIRE( 50721.143Skamil ptrace(PT_LWPNEXT, child, &lwpstatus, 50731.143Skamil sizeof(lwpstatus)) != -1); 50741.143Skamil DPRINTF("LWP=%d\n", lwpstatus.pl_lwpid); 50751.143Skamil 50761.143Skamil DPRINTF("Assert that the thread exists\n"); 50771.143Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 50781.143Skamil 50791.143Skamil check_lwpstatus: 50801.143Skamil 50811.143Skamil if (strstr(iter, "pl_sigmask") != NULL) { 50821.143Skamil sigmask = lwpstatus.pl_sigmask; 50831.143Skamil 50841.143Skamil DPRINTF("Retrieved sigmask: " 50851.143Skamil "%02x%02x%02x%02x\n", 50861.143Skamil sigmask.__bits[0], sigmask.__bits[1], 50871.143Skamil sigmask.__bits[2], sigmask.__bits[3]); 50881.143Skamil 50891.143Skamil found = false; 50901.143Skamil for (m = 0; 50911.143Skamil m < __arraycount(lwpinfo_thread_sigmask); 50921.143Skamil m++) { 50931.143Skamil if (sigismember(&sigmask, 50941.143Skamil lwpinfo_thread_sigmask[m])) { 50951.143Skamil found = true; 50961.143Skamil lwpinfo_thread_sigmask[m] = 0; 50971.143Skamil break; 50981.143Skamil } 50991.143Skamil } 51001.143Skamil ATF_REQUIRE(found == true); 51011.143Skamil } else if (strstr(iter, "pl_name") != NULL) { 51021.143Skamil name = lwpstatus.pl_name; 51031.143Skamil 51041.143Skamil DPRINTF("Retrieved thread name: " 51051.143Skamil "%s\n", name); 51061.143Skamil 51071.143Skamil snprintf(namebuf, sizeof namebuf, "thread %d", 51081.143Skamil lwpstatus.pl_lwpid); 51091.143Skamil 51101.143Skamil ATF_REQUIRE(strcmp(name, namebuf) == 0); 51111.143Skamil } else if (strstr(iter, "pl_private") != NULL) { 51121.143Skamil private = lwpstatus.pl_private; 51131.143Skamil 51141.143Skamil DPRINTF("Retrieved thread private pointer: " 51151.143Skamil "%p\n", private); 51161.143Skamil 51171.143Skamil found = false; 51181.143Skamil for (m = 0; m < __arraycount(tcb); m++) { 51191.143Skamil DPRINTF("Comparing %p and %p\n", 51201.143Skamil private, tcb[m]); 51211.143Skamil if (private == tcb[m]) { 51221.143Skamil found = true; 51231.143Skamil break; 51241.143Skamil } 51251.143Skamil } 51261.143Skamil ATF_REQUIRE(found == true); 51271.143Skamil } 51281.143Skamil } 51291.143Skamil } 51301.143Skamil 51311.143Skamil if (strstr(iter, "LWPINFO") != NULL) { 51321.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 51331.143Skamil "child\n"); 51341.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 51351.143Skamil != -1); 51361.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 51371.77Skamil 51381.143Skamil DPRINTF("Assert that there are no more threads\n"); 51391.143Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 51401.143Skamil } else { 51411.143Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 51421.143Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 51431.143Skamil sizeof(lwpstatus)) != -1); 51441.77Skamil 51451.143Skamil DPRINTF("Assert that there exists a single thread only\n"); 51461.143Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 51471.143Skamil } 51481.77Skamil 51491.77Skamil DPRINTF("Before resuming the child process where it left off and " 51501.77Skamil "without signal to be sent\n"); 51511.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 51521.77Skamil 51531.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51541.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51551.77Skamil 51561.77Skamil validate_status_signaled(status, SIGKILL, 0); 51571.1Skamil 51581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51591.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 51601.1Skamil} 51611.1Skamil 51621.143Skamil#define TRACEME_LWPINFO(test, threads, iter) \ 51631.77SkamilATF_TC(test); \ 51641.77SkamilATF_TC_HEAD(test, tc) \ 51651.77Skamil{ \ 51661.77Skamil atf_tc_set_md_var(tc, "descr", \ 51671.143Skamil "Verify " iter " with the child with " #threads \ 51681.77Skamil " spawned extra threads"); \ 51691.77Skamil} \ 51701.77Skamil \ 51711.77SkamilATF_TC_BODY(test, tc) \ 51721.77Skamil{ \ 51731.77Skamil \ 51741.143Skamil traceme_lwpinfo(threads, iter); \ 51751.1Skamil} 51761.1Skamil 51771.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0, "LWPINFO") 51781.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1, "LWPINFO") 51791.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2, "LWPINFO") 51801.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3, "LWPINFO") 51811.143Skamil 51821.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus, 0, "LWPINFO+LWPSTATUS") 51831.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus, 1, "LWPINFO+LWPSTATUS") 51841.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus, 2, "LWPINFO+LWPSTATUS") 51851.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus, 3, "LWPINFO+LWPSTATUS") 51861.143Skamil 51871.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_sigmask, 0, 51881.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 51891.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_sigmask, 1, 51901.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 51911.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_sigmask, 2, 51921.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 51931.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_sigmask, 3, 51941.143Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 51951.143Skamil 51961.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_name, 0, 51971.143Skamil "LWPINFO+LWPSTATUS+pl_name") 51981.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_name, 1, 51991.143Skamil "LWPINFO+LWPSTATUS+pl_name") 52001.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_name, 2, 52011.143Skamil "LWPINFO+LWPSTATUS+pl_name") 52021.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_name, 3, 52031.143Skamil "LWPINFO+LWPSTATUS+pl_name") 52041.143Skamil 52051.143SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_private, 0, 52061.143Skamil "LWPINFO+LWPSTATUS+pl_private") 52071.143SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_private, 1, 52081.143Skamil "LWPINFO+LWPSTATUS+pl_private") 52091.143SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_private, 2, 52101.143Skamil "LWPINFO+LWPSTATUS+pl_private") 52111.143SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_private, 3, 52121.143Skamil "LWPINFO+LWPSTATUS+pl_private") 52131.143Skamil 52141.143SkamilTRACEME_LWPINFO(traceme_lwpnext0, 0, "LWPNEXT") 52151.143SkamilTRACEME_LWPINFO(traceme_lwpnext1, 1, "LWPNEXT") 52161.143SkamilTRACEME_LWPINFO(traceme_lwpnext2, 2, "LWPNEXT") 52171.143SkamilTRACEME_LWPINFO(traceme_lwpnext3, 3, "LWPNEXT") 52181.143Skamil 52191.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_sigmask, 0, "LWPNEXT+pl_sigmask") 52201.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_sigmask, 1, "LWPNEXT+pl_sigmask") 52211.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_sigmask, 2, "LWPNEXT+pl_sigmask") 52221.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_sigmask, 3, "LWPNEXT+pl_sigmask") 52231.143Skamil 52241.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_name, 0, "LWPNEXT+pl_name") 52251.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_name, 1, "LWPNEXT+pl_name") 52261.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_name, 2, "LWPNEXT+pl_name") 52271.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_name, 3, "LWPNEXT+pl_name") 52281.143Skamil 52291.143SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_private, 0, "LWPNEXT+pl_private") 52301.143SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_private, 1, "LWPNEXT+pl_private") 52311.143SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_private, 2, "LWPNEXT+pl_private") 52321.143SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_private, 3, "LWPNEXT+pl_private") 52331.77Skamil 52341.77Skamil/// ---------------------------------------------------------------------------- 52351.77Skamil 52361.77Skamil#if defined(TWAIT_HAVE_PID) 52371.77Skamilstatic void 52381.77Skamilattach_lwpinfo(const int threads) 52391.1Skamil{ 52401.77Skamil const int sigval = SIGINT; 52411.1Skamil struct msg_fds parent_tracee, parent_tracer; 52421.1Skamil const int exitval_tracer = 10; 52431.1Skamil pid_t tracee, tracer, wpid; 52441.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 52451.1Skamil#if defined(TWAIT_HAVE_STATUS) 52461.1Skamil int status; 52471.1Skamil#endif 52481.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 52491.77Skamil struct ptrace_siginfo info; 52501.77Skamil 52511.77Skamil /* Maximum number of supported threads in this test */ 52521.77Skamil pthread_t t[3]; 52531.77Skamil int n, rv; 52541.1Skamil 52551.13Schristos DPRINTF("Spawn tracee\n"); 52561.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 52571.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 52581.1Skamil tracee = atf_utils_fork(); 52591.1Skamil if (tracee == 0) { 52601.1Skamil /* Wait for message from the parent */ 52611.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 52621.1Skamil 52631.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 52641.77Skamil 52651.77Skamil for (n = 0; n < threads; n++) { 52661.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 52671.77Skamil FORKEE_ASSERT(rv == 0); 52681.77Skamil } 52691.77Skamil 52701.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 52711.77Skamil 52721.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 52731.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 52741.77Skamil 52751.77Skamil /* NOTREACHED */ 52761.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 52771.1Skamil } 52781.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 52791.1Skamil 52801.13Schristos DPRINTF("Spawn debugger\n"); 52811.1Skamil tracer = atf_utils_fork(); 52821.1Skamil if (tracer == 0) { 52831.1Skamil /* No IPC to communicate with the child */ 52841.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 52851.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 52861.1Skamil 52871.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 52881.1Skamil FORKEE_REQUIRE_SUCCESS( 52891.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 52901.1Skamil 52911.1Skamil forkee_status_stopped(status, SIGSTOP); 52921.1Skamil 52931.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52941.77Skamil "tracee"); 52951.77Skamil FORKEE_ASSERT( 52961.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 52971.77Skamil 52981.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52991.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 53001.77Skamil "si_errno=%#x\n", 53011.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 53021.77Skamil info.psi_siginfo.si_errno); 53031.77Skamil 53041.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 53051.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 53061.77Skamil 53071.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 53081.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 53091.1Skamil != -1); 53101.1Skamil 53111.13Schristos DPRINTF("Assert that there exists a thread\n"); 53121.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 53131.1Skamil 53141.13Schristos DPRINTF("Assert that lwp thread %d received event " 53151.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 53161.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 53171.1Skamil 53181.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 53191.77Skamil "tracee\n"); 53201.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 53211.1Skamil != -1); 53221.1Skamil 53231.77Skamil DPRINTF("Assert that there are no more lwp threads in " 53241.77Skamil "tracee\n"); 53251.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 53261.1Skamil 53271.1Skamil /* Resume tracee with PT_CONTINUE */ 53281.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 53291.1Skamil 53301.1Skamil /* Inform parent that tracer has attached to tracee */ 53311.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 53321.77Skamil 53331.1Skamil /* Wait for parent */ 53341.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 53351.1Skamil 53361.77Skamil /* Wait for tracee and assert that it raised a signal */ 53371.77Skamil FORKEE_REQUIRE_SUCCESS( 53381.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 53391.77Skamil 53401.77Skamil forkee_status_stopped(status, SIGINT); 53411.77Skamil 53421.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 53431.77Skamil "child"); 53441.77Skamil FORKEE_ASSERT( 53451.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 53461.77Skamil 53471.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 53481.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 53491.77Skamil "si_errno=%#x\n", 53501.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 53511.77Skamil info.psi_siginfo.si_errno); 53521.77Skamil 53531.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 53541.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 53551.77Skamil 53561.77Skamil memset(&lwp, 0, sizeof(lwp)); 53571.77Skamil 53581.77Skamil for (n = 0; n <= threads; n++) { 53591.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 53601.77Skamil "child\n"); 53611.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 53621.77Skamil sizeof(lwp)) != -1); 53631.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 53641.77Skamil 53651.77Skamil DPRINTF("Assert that the thread exists\n"); 53661.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 53671.77Skamil 53681.77Skamil DPRINTF("Assert that lwp thread %d received expected " 53691.77Skamil "event\n", lwp.pl_lwpid); 53701.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 53711.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 53721.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 53731.77Skamil } 53741.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 53751.77Skamil "tracee\n"); 53761.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 53771.77Skamil != -1); 53781.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 53791.77Skamil 53801.77Skamil DPRINTF("Assert that there are no more threads\n"); 53811.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 53821.77Skamil 53831.77Skamil DPRINTF("Before resuming the child process where it left off " 53841.77Skamil "and without signal to be sent\n"); 53851.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 53861.77Skamil != -1); 53871.77Skamil 53881.1Skamil /* Wait for tracee and assert that it exited */ 53891.1Skamil FORKEE_REQUIRE_SUCCESS( 53901.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 53911.1Skamil 53921.77Skamil forkee_status_signaled(status, SIGKILL, 0); 53931.1Skamil 53941.13Schristos DPRINTF("Before exiting of the tracer process\n"); 53951.1Skamil _exit(exitval_tracer); 53961.1Skamil } 53971.1Skamil 53981.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 53991.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 54001.1Skamil 54011.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 54021.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 54031.77Skamil 54041.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 54051.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 54061.1Skamil 54071.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 54081.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 54091.1Skamil 54101.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 54111.1Skamil TWAIT_FNAME); 54121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 54131.1Skamil tracer); 54141.1Skamil 54151.1Skamil validate_status_exited(status, exitval_tracer); 54161.1Skamil 54171.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 54181.1Skamil TWAIT_FNAME); 54191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 54201.1Skamil tracee); 54211.1Skamil 54221.77Skamil validate_status_signaled(status, SIGKILL, 0); 54231.1Skamil 54241.1Skamil msg_close(&parent_tracer); 54251.1Skamil msg_close(&parent_tracee); 54261.1Skamil} 54271.77Skamil 54281.77Skamil#define ATTACH_LWPINFO(test, threads) \ 54291.77SkamilATF_TC(test); \ 54301.77SkamilATF_TC_HEAD(test, tc) \ 54311.77Skamil{ \ 54321.77Skamil atf_tc_set_md_var(tc, "descr", \ 54331.77Skamil "Verify LWPINFO with the child with " #threads \ 54341.77Skamil " spawned extra threads (tracer is not the original " \ 54351.77Skamil "parent)"); \ 54361.77Skamil} \ 54371.77Skamil \ 54381.77SkamilATF_TC_BODY(test, tc) \ 54391.77Skamil{ \ 54401.77Skamil \ 54411.77Skamil attach_lwpinfo(threads); \ 54421.77Skamil} 54431.77Skamil 54441.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 54451.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 54461.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 54471.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 54481.1Skamil#endif 54491.1Skamil 54501.77Skamil/// ---------------------------------------------------------------------------- 54511.77Skamil 54521.1Skamilstatic void 54531.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 54541.1Skamil{ 54551.1Skamil const int exitval = 5; 54561.1Skamil const int sigval = SIGINT; 54571.1Skamil const int sigfaked = SIGTRAP; 54581.1Skamil const int sicodefaked = TRAP_BRKPT; 54591.1Skamil pid_t child, wpid; 54601.1Skamil struct sigaction sa; 54611.1Skamil#if defined(TWAIT_HAVE_STATUS) 54621.1Skamil int status; 54631.1Skamil#endif 54641.1Skamil struct ptrace_siginfo info; 54651.1Skamil memset(&info, 0, sizeof(info)); 54661.1Skamil 54671.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54681.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54691.1Skamil if (child == 0) { 54701.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54711.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54721.1Skamil 54731.79Skamil sa.sa_sigaction = sah; 54741.1Skamil sa.sa_flags = SA_SIGINFO; 54751.1Skamil sigemptyset(&sa.sa_mask); 54761.1Skamil 54771.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 54781.79Skamil != -1); 54791.1Skamil 54801.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54811.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54821.1Skamil 54831.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 54841.1Skamil 54851.13Schristos DPRINTF("Before exiting of the child process\n"); 54861.1Skamil _exit(exitval); 54871.1Skamil } 54881.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54891.1Skamil 54901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54921.1Skamil 54931.1Skamil validate_status_stopped(status, sigval); 54941.1Skamil 54951.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 54961.61Skre SYSCALL_REQUIRE( 54971.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54981.1Skamil 54991.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55001.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55011.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55021.1Skamil info.psi_siginfo.si_errno); 55031.1Skamil 55041.79Skamil if (faked) { 55051.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 55061.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 55071.79Skamil info.psi_siginfo.si_signo = sigfaked; 55081.79Skamil info.psi_siginfo.si_code = sicodefaked; 55091.79Skamil } 55101.1Skamil 55111.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 55121.61Skre SYSCALL_REQUIRE( 55131.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 55141.1Skamil 55151.79Skamil if (faked) { 55161.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55171.79Skamil "child\n"); 55181.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 55191.79Skamil sizeof(info)) != -1); 55201.1Skamil 55211.79Skamil DPRINTF("Before checking siginfo_t\n"); 55221.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 55231.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 55241.79Skamil } 55251.1Skamil 55261.13Schristos DPRINTF("Before resuming the child process where it left off and " 55271.1Skamil "without signal to be sent\n"); 55281.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 55291.79Skamil faked ? sigfaked : sigval) != -1); 55301.1Skamil 55311.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55321.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55331.1Skamil 55341.1Skamil validate_status_exited(status, exitval); 55351.1Skamil 55361.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55371.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 55381.1Skamil} 55391.1Skamil 55401.79Skamil#define PTRACE_SIGINFO(test, faked) \ 55411.79SkamilATF_TC(test); \ 55421.79SkamilATF_TC_HEAD(test, tc) \ 55431.79Skamil{ \ 55441.79Skamil atf_tc_set_md_var(tc, "descr", \ 55451.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 55461.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 55471.79Skamil} \ 55481.79Skamil \ 55491.79Skamilstatic int test##_caught = 0; \ 55501.79Skamil \ 55511.79Skamilstatic void \ 55521.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 55531.79Skamil{ \ 55541.79Skamil if (faked) { \ 55551.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 55561.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 55571.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 55581.79Skamil } else { \ 55591.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 55601.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 55611.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 55621.79Skamil } \ 55631.79Skamil \ 55641.79Skamil ++ test##_caught; \ 55651.79Skamil} \ 55661.79Skamil \ 55671.79SkamilATF_TC_BODY(test, tc) \ 55681.79Skamil{ \ 55691.79Skamil \ 55701.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 55711.79Skamil} 55721.79Skamil 55731.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 55741.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 55751.79Skamil 55761.79Skamil/// ---------------------------------------------------------------------------- 55771.79Skamil 55781.97Skamilstatic void 55791.97Skamiltraceme_exec(bool masked, bool ignored) 55801.1Skamil{ 55811.1Skamil const int sigval = SIGTRAP; 55821.1Skamil pid_t child, wpid; 55831.1Skamil#if defined(TWAIT_HAVE_STATUS) 55841.1Skamil int status; 55851.1Skamil#endif 55861.97Skamil struct sigaction sa; 55871.97Skamil struct ptrace_siginfo info; 55881.97Skamil sigset_t intmask; 55891.97Skamil struct kinfo_proc2 kp; 55901.97Skamil size_t len = sizeof(kp); 55911.97Skamil 55921.97Skamil int name[6]; 55931.97Skamil const size_t namelen = __arraycount(name); 55941.97Skamil ki_sigset_t kp_sigmask; 55951.97Skamil ki_sigset_t kp_sigignore; 55961.1Skamil 55971.1Skamil memset(&info, 0, sizeof(info)); 55981.1Skamil 55991.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56001.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56011.1Skamil if (child == 0) { 56021.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56031.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56041.1Skamil 56051.97Skamil if (masked) { 56061.97Skamil sigemptyset(&intmask); 56071.97Skamil sigaddset(&intmask, sigval); 56081.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56091.97Skamil } 56101.97Skamil 56111.97Skamil if (ignored) { 56121.97Skamil memset(&sa, 0, sizeof(sa)); 56131.97Skamil sa.sa_handler = SIG_IGN; 56141.97Skamil sigemptyset(&sa.sa_mask); 56151.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 56161.97Skamil } 56171.97Skamil 56181.13Schristos DPRINTF("Before calling execve(2) from child\n"); 56191.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 56201.1Skamil 56211.1Skamil FORKEE_ASSERT(0 && "Not reached"); 56221.1Skamil } 56231.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56241.1Skamil 56251.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56271.1Skamil 56281.1Skamil validate_status_stopped(status, sigval); 56291.1Skamil 56301.97Skamil name[0] = CTL_KERN, 56311.97Skamil name[1] = KERN_PROC2, 56321.97Skamil name[2] = KERN_PROC_PID; 56331.97Skamil name[3] = getpid(); 56341.97Skamil name[4] = sizeof(kp); 56351.97Skamil name[5] = 1; 56361.97Skamil 56371.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 56381.97Skamil 56391.97Skamil if (masked) 56401.97Skamil kp_sigmask = kp.p_sigmask; 56411.97Skamil 56421.97Skamil if (ignored) 56431.97Skamil kp_sigignore = kp.p_sigignore; 56441.97Skamil 56451.97Skamil name[3] = getpid(); 56461.97Skamil 56471.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 56481.97Skamil 56491.97Skamil if (masked) { 56501.97Skamil DPRINTF("kp_sigmask=" 56511.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 56521.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 56531.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 56541.97Skamil 56551.97Skamil DPRINTF("kp.p_sigmask=" 56561.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 56571.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 56581.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 56591.97Skamil 56601.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 56611.97Skamil sizeof(kp_sigmask))); 56621.97Skamil } 56631.97Skamil 56641.97Skamil if (ignored) { 56651.97Skamil DPRINTF("kp_sigignore=" 56661.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 56671.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 56681.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 56691.97Skamil 56701.97Skamil DPRINTF("kp.p_sigignore=" 56711.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 56721.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 56731.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 56741.97Skamil 56751.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 56761.97Skamil sizeof(kp_sigignore))); 56771.97Skamil } 56781.97Skamil 56791.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 56801.61Skre SYSCALL_REQUIRE( 56811.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56821.1Skamil 56831.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 56841.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 56851.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 56861.1Skamil info.psi_siginfo.si_errno); 56871.1Skamil 56881.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 56891.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 56901.1Skamil 56911.13Schristos DPRINTF("Before resuming the child process where it left off and " 56921.1Skamil "without signal to be sent\n"); 56931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56941.1Skamil 56951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56971.1Skamil 56981.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56991.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57001.1Skamil} 57011.1Skamil 57021.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 57031.97SkamilATF_TC(test); \ 57041.97SkamilATF_TC_HEAD(test, tc) \ 57051.97Skamil{ \ 57061.97Skamil atf_tc_set_md_var(tc, "descr", \ 57071.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 57081.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 57091.97Skamil masked ? " with ignored signal" : ""); \ 57101.97Skamil} \ 57111.97Skamil \ 57121.97SkamilATF_TC_BODY(test, tc) \ 57131.97Skamil{ \ 57141.97Skamil \ 57151.97Skamil traceme_exec(masked, ignored); \ 57161.97Skamil} 57171.97Skamil 57181.97SkamilTRACEME_EXEC(traceme_exec, false, false) 57191.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 57201.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 57211.97Skamil 57221.82Skamil/// ---------------------------------------------------------------------------- 57231.82Skamil 57241.135Skamil#define TRACE_THREADS_NUM 100 57251.135Skamil 57261.83Skamilstatic volatile int done; 57271.137Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER; 57281.1Skamil 57291.83Skamilstatic void * 57301.83Skamiltrace_threads_cb(void *arg __unused) 57311.1Skamil{ 57321.1Skamil 57331.137Skamil pthread_mutex_lock(&trace_threads_mtx); 57341.83Skamil done++; 57351.137Skamil pthread_mutex_unlock(&trace_threads_mtx); 57361.83Skamil 57371.135Skamil while (done < TRACE_THREADS_NUM) 57381.135Skamil sched_yield(); 57391.83Skamil 57401.83Skamil return NULL; 57411.1Skamil} 57421.1Skamil 57431.83Skamilstatic void 57441.83Skamiltrace_threads(bool trace_create, bool trace_exit) 57451.1Skamil{ 57461.1Skamil const int sigval = SIGSTOP; 57471.1Skamil pid_t child, wpid; 57481.1Skamil#if defined(TWAIT_HAVE_STATUS) 57491.1Skamil int status; 57501.1Skamil#endif 57511.1Skamil ptrace_state_t state; 57521.1Skamil const int slen = sizeof(state); 57531.1Skamil ptrace_event_t event; 57541.1Skamil const int elen = sizeof(event); 57551.83Skamil struct ptrace_siginfo info; 57561.83Skamil 57571.135Skamil pthread_t t[TRACE_THREADS_NUM]; 57581.83Skamil int rv; 57591.83Skamil size_t n; 57601.1Skamil lwpid_t lid; 57611.83Skamil 57621.83Skamil /* Track created and exited threads */ 57631.141Skamil struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}}; 57641.83Skamil 57651.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57661.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57671.1Skamil if (child == 0) { 57681.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57691.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57701.1Skamil 57711.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57721.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57731.1Skamil 57741.83Skamil for (n = 0; n < __arraycount(t); n++) { 57751.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 57761.83Skamil NULL); 57771.83Skamil FORKEE_ASSERT(rv == 0); 57781.83Skamil } 57791.1Skamil 57801.83Skamil for (n = 0; n < __arraycount(t); n++) { 57811.83Skamil rv = pthread_join(t[n], NULL); 57821.83Skamil FORKEE_ASSERT(rv == 0); 57831.83Skamil } 57841.1Skamil 57851.83Skamil /* 57861.83Skamil * There is race between _exit() and pthread_join() detaching 57871.83Skamil * a thread. For simplicity kill the process after detecting 57881.83Skamil * LWP events. 57891.83Skamil */ 57901.83Skamil while (true) 57911.83Skamil continue; 57921.1Skamil 57931.83Skamil FORKEE_ASSERT(0 && "Not reached"); 57941.1Skamil } 57951.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57961.1Skamil 57971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57991.1Skamil 58001.1Skamil validate_status_stopped(status, sigval); 58011.1Skamil 58021.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 58031.83Skamil SYSCALL_REQUIRE( 58041.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 58051.1Skamil 58061.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 58071.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 58081.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 58091.83Skamil info.psi_siginfo.si_errno); 58101.1Skamil 58111.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 58121.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 58131.1Skamil 58141.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 58151.83Skamil memset(&event, 0, sizeof(event)); 58161.83Skamil if (trace_create) 58171.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 58181.83Skamil if (trace_exit) 58191.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 58201.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58211.1Skamil 58221.13Schristos DPRINTF("Before resuming the child process where it left off and " 58231.1Skamil "without signal to be sent\n"); 58241.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58251.1Skamil 58261.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 58271.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 58281.83Skamil "SIGTRAP\n", TWAIT_FNAME); 58291.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58301.83Skamil child); 58311.1Skamil 58321.83Skamil validate_status_stopped(status, SIGTRAP); 58331.1Skamil 58341.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 58351.83Skamil "child\n"); 58361.83Skamil SYSCALL_REQUIRE( 58371.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 58381.1Skamil 58391.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 58401.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 58411.83Skamil "si_errno=%#x\n", 58421.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 58431.83Skamil info.psi_siginfo.si_errno); 58441.1Skamil 58451.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 58461.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 58471.1Skamil 58481.83Skamil SYSCALL_REQUIRE( 58491.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58501.1Skamil 58511.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 58521.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 58531.1Skamil 58541.83Skamil lid = state.pe_lwp; 58551.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 58561.1Skamil 58571.141Skamil *FIND_EVENT_COUNT(traced_lwps, lid) += 1; 58581.1Skamil 58591.83Skamil DPRINTF("Before resuming the child process where it left off " 58601.83Skamil "and without signal to be sent\n"); 58611.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58621.83Skamil } 58631.1Skamil 58641.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 58651.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 58661.83Skamil "SIGTRAP\n", TWAIT_FNAME); 58671.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58681.83Skamil child); 58691.1Skamil 58701.83Skamil validate_status_stopped(status, SIGTRAP); 58711.1Skamil 58721.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 58731.83Skamil "child\n"); 58741.83Skamil SYSCALL_REQUIRE( 58751.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 58761.1Skamil 58771.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 58781.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 58791.83Skamil "si_errno=%#x\n", 58801.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 58811.83Skamil info.psi_siginfo.si_errno); 58821.1Skamil 58831.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 58841.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 58851.1Skamil 58861.83Skamil SYSCALL_REQUIRE( 58871.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58881.1Skamil 58891.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 58901.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 58911.1Skamil 58921.83Skamil lid = state.pe_lwp; 58931.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 58941.1Skamil 58951.83Skamil if (trace_create) { 58961.141Skamil int *count = FIND_EVENT_COUNT(traced_lwps, lid); 58971.141Skamil ATF_REQUIRE_EQ(*count, 1); 58981.141Skamil *count = 0; 58991.83Skamil } 59001.1Skamil 59011.83Skamil DPRINTF("Before resuming the child process where it left off " 59021.83Skamil "and without signal to be sent\n"); 59031.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59041.83Skamil } 59051.1Skamil 59061.83Skamil kill(child, SIGKILL); 59071.1Skamil 59081.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 59091.1Skamil TWAIT_FNAME); 59101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59111.1Skamil 59121.83Skamil validate_status_signaled(status, SIGKILL, 0); 59131.1Skamil 59141.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 59151.1Skamil TWAIT_FNAME); 59161.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 59171.1Skamil} 59181.1Skamil 59191.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 59201.83SkamilATF_TC(test); \ 59211.83SkamilATF_TC_HEAD(test, tc) \ 59221.83Skamil{ \ 59231.83Skamil atf_tc_set_md_var(tc, "descr", \ 59241.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 59251.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 59261.83Skamil trace_exit ? "" : "out"); \ 59271.83Skamil} \ 59281.83Skamil \ 59291.83SkamilATF_TC_BODY(test, tc) \ 59301.83Skamil{ \ 59311.83Skamil \ 59321.83Skamil trace_threads(trace_create, trace_exit); \ 59331.83Skamil} 59341.83Skamil 59351.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 59361.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 59371.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 59381.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 59391.83Skamil 59401.83Skamil/// ---------------------------------------------------------------------------- 59411.83Skamil 59421.84SkamilATF_TC(signal_mask_unrelated); 59431.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 59441.1Skamil{ 59451.1Skamil atf_tc_set_md_var(tc, "descr", 59461.1Skamil "Verify that masking single unrelated signal does not stop tracer " 59471.1Skamil "from catching other signals"); 59481.1Skamil} 59491.1Skamil 59501.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 59511.1Skamil{ 59521.1Skamil const int exitval = 5; 59531.1Skamil const int sigval = SIGSTOP; 59541.1Skamil const int sigmasked = SIGTRAP; 59551.1Skamil const int signotmasked = SIGINT; 59561.1Skamil pid_t child, wpid; 59571.1Skamil#if defined(TWAIT_HAVE_STATUS) 59581.1Skamil int status; 59591.1Skamil#endif 59601.1Skamil sigset_t intmask; 59611.1Skamil 59621.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 59631.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 59641.1Skamil if (child == 0) { 59651.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 59661.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 59671.1Skamil 59681.1Skamil sigemptyset(&intmask); 59691.1Skamil sigaddset(&intmask, sigmasked); 59701.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 59711.1Skamil 59721.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 59731.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 59741.1Skamil 59751.13Schristos DPRINTF("Before raising %s from child\n", 59761.1Skamil strsignal(signotmasked)); 59771.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 59781.1Skamil 59791.13Schristos DPRINTF("Before exiting of the child process\n"); 59801.1Skamil _exit(exitval); 59811.1Skamil } 59821.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 59831.1Skamil 59841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 59851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59861.1Skamil 59871.1Skamil validate_status_stopped(status, sigval); 59881.1Skamil 59891.13Schristos DPRINTF("Before resuming the child process where it left off and " 59901.1Skamil "without signal to be sent\n"); 59911.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59921.1Skamil 59931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 59941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59951.1Skamil 59961.1Skamil validate_status_stopped(status, signotmasked); 59971.1Skamil 59981.13Schristos DPRINTF("Before resuming the child process where it left off and " 59991.1Skamil "without signal to be sent\n"); 60001.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60011.1Skamil 60021.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60041.1Skamil 60051.1Skamil validate_status_exited(status, exitval); 60061.1Skamil 60071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60081.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60091.1Skamil} 60101.1Skamil 60111.84Skamil/// ---------------------------------------------------------------------------- 60121.84Skamil 60131.1Skamil#if defined(TWAIT_HAVE_PID) 60141.99Skamilstatic void 60151.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 60161.1Skamil{ 60171.1Skamil const int exitval = 5; 60181.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 60191.1Skamil const int sigval = SIGSTOP; 60201.99Skamil pid_t child, child2 = 0, wpid; 60211.1Skamil#if defined(TWAIT_HAVE_STATUS) 60221.1Skamil int status; 60231.1Skamil#endif 60241.1Skamil ptrace_state_t state; 60251.1Skamil const int slen = sizeof(state); 60261.1Skamil ptrace_event_t event; 60271.1Skamil const int elen = sizeof(event); 60281.99Skamil struct sigaction sa; 60291.99Skamil struct ptrace_siginfo info; 60301.99Skamil sigset_t intmask; 60311.99Skamil struct kinfo_proc2 kp; 60321.99Skamil size_t len = sizeof(kp); 60331.99Skamil 60341.99Skamil int name[6]; 60351.99Skamil const size_t namelen = __arraycount(name); 60361.99Skamil ki_sigset_t kp_sigmask; 60371.99Skamil ki_sigset_t kp_sigignore; 60381.1Skamil 60391.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 60401.14Schristos 60411.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 60421.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 60431.1Skamil if (child == 0) { 60441.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 60451.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 60461.1Skamil 60471.99Skamil if (masked) { 60481.99Skamil sigemptyset(&intmask); 60491.99Skamil sigaddset(&intmask, SIGTRAP); 60501.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 60511.99Skamil } 60521.99Skamil 60531.99Skamil if (ignored) { 60541.99Skamil memset(&sa, 0, sizeof(sa)); 60551.99Skamil sa.sa_handler = SIG_IGN; 60561.99Skamil sigemptyset(&sa.sa_mask); 60571.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 60581.99Skamil } 60591.1Skamil 60601.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 60611.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 60621.1Skamil 60631.126Skamil if (strcmp(fn, "spawn") == 0) { 60641.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 60651.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 60661.126Skamil } else { 60671.126Skamil if (strcmp(fn, "fork") == 0) { 60681.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 60691.126Skamil } else { 60701.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 60711.126Skamil } 60721.126Skamil if (child2 == 0) 60731.126Skamil _exit(exitval2); 60741.126Skamil } 60751.1Skamil 60761.1Skamil FORKEE_REQUIRE_SUCCESS 60771.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 60781.1Skamil 60791.1Skamil forkee_status_exited(status, exitval2); 60801.1Skamil 60811.13Schristos DPRINTF("Before exiting of the child process\n"); 60821.1Skamil _exit(exitval); 60831.1Skamil } 60841.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 60851.1Skamil 60861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60881.1Skamil 60891.1Skamil validate_status_stopped(status, sigval); 60901.1Skamil 60911.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 60921.99Skamil SYSCALL_REQUIRE( 60931.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 60941.99Skamil 60951.99Skamil DPRINTF("Before checking siginfo_t\n"); 60961.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 60971.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 60981.1Skamil 60991.99Skamil name[0] = CTL_KERN, 61001.99Skamil name[1] = KERN_PROC2, 61011.99Skamil name[2] = KERN_PROC_PID; 61021.99Skamil name[3] = child; 61031.99Skamil name[4] = sizeof(kp); 61041.99Skamil name[5] = 1; 61051.1Skamil 61061.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 61071.1Skamil 61081.99Skamil if (masked) 61091.99Skamil kp_sigmask = kp.p_sigmask; 61101.1Skamil 61111.99Skamil if (ignored) 61121.99Skamil kp_sigignore = kp.p_sigignore; 61131.1Skamil 61141.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 61151.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 61161.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 61171.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 61181.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 61191.99Skamil event.pe_set_event = 0; 61201.126Skamil if (strcmp(fn, "spawn") == 0) 61211.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 61221.126Skamil if (strcmp(fn, "fork") == 0) 61231.99Skamil event.pe_set_event |= PTRACE_FORK; 61241.126Skamil if (strcmp(fn, "vfork") == 0) 61251.99Skamil event.pe_set_event |= PTRACE_VFORK; 61261.126Skamil if (strcmp(fn, "vforkdone") == 0) 61271.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 61281.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61291.1Skamil 61301.99Skamil DPRINTF("Before resuming the child process where it left off and " 61311.99Skamil "without signal to be sent\n"); 61321.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61331.1Skamil 61341.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 61351.126Skamil strcmp(fn, "vfork") == 0) { 61361.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 61371.99Skamil child); 61381.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 61391.99Skamil child); 61401.1Skamil 61411.99Skamil validate_status_stopped(status, SIGTRAP); 61421.1Skamil 61431.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 61441.1Skamil 61451.99Skamil if (masked) { 61461.99Skamil DPRINTF("kp_sigmask=" 61471.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 61481.99Skamil PRIx32 "\n", 61491.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 61501.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 61511.1Skamil 61521.99Skamil DPRINTF("kp.p_sigmask=" 61531.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 61541.99Skamil PRIx32 "\n", 61551.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 61561.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 61571.1Skamil 61581.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 61591.99Skamil sizeof(kp_sigmask))); 61601.99Skamil } 61611.1Skamil 61621.99Skamil if (ignored) { 61631.99Skamil DPRINTF("kp_sigignore=" 61641.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 61651.99Skamil PRIx32 "\n", 61661.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 61671.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 61681.1Skamil 61691.99Skamil DPRINTF("kp.p_sigignore=" 61701.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 61711.99Skamil PRIx32 "\n", 61721.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 61731.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 61741.1Skamil 61751.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 61761.99Skamil sizeof(kp_sigignore))); 61771.99Skamil } 61781.1Skamil 61791.99Skamil SYSCALL_REQUIRE( 61801.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 61811.126Skamil if (strcmp(fn, "spawn") == 0) { 61821.126Skamil ATF_REQUIRE_EQ( 61831.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 61841.126Skamil PTRACE_POSIX_SPAWN); 61851.126Skamil } 61861.126Skamil if (strcmp(fn, "fork") == 0) { 61871.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 61881.99Skamil PTRACE_FORK); 61891.99Skamil } 61901.126Skamil if (strcmp(fn, "vfork") == 0) { 61911.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 61921.99Skamil PTRACE_VFORK); 61931.99Skamil } 61941.1Skamil 61951.99Skamil child2 = state.pe_other_pid; 61961.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 61971.1Skamil 61981.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 61991.99Skamil "%d\n", TWAIT_FNAME, child2, child); 62001.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 62011.99Skamil child2); 62021.1Skamil 62031.99Skamil validate_status_stopped(status, SIGTRAP); 62041.1Skamil 62051.99Skamil name[3] = child2; 62061.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 62071.1Skamil 62081.99Skamil if (masked) { 62091.99Skamil DPRINTF("kp_sigmask=" 62101.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 62111.99Skamil PRIx32 "\n", 62121.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 62131.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 62141.1Skamil 62151.99Skamil DPRINTF("kp.p_sigmask=" 62161.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 62171.99Skamil PRIx32 "\n", 62181.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 62191.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 62201.14Schristos 62211.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 62221.99Skamil sizeof(kp_sigmask))); 62231.99Skamil } 62241.1Skamil 62251.99Skamil if (ignored) { 62261.99Skamil DPRINTF("kp_sigignore=" 62271.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 62281.99Skamil PRIx32 "\n", 62291.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 62301.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 62311.1Skamil 62321.99Skamil DPRINTF("kp.p_sigignore=" 62331.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 62341.99Skamil PRIx32 "\n", 62351.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 62361.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 62371.1Skamil 62381.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 62391.99Skamil sizeof(kp_sigignore))); 62401.99Skamil } 62411.1Skamil 62421.99Skamil SYSCALL_REQUIRE( 62431.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 62441.126Skamil if (strcmp(fn, "spawn") == 0) { 62451.126Skamil ATF_REQUIRE_EQ( 62461.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 62471.126Skamil PTRACE_POSIX_SPAWN); 62481.126Skamil } 62491.126Skamil if (strcmp(fn, "fork") == 0) { 62501.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 62511.99Skamil PTRACE_FORK); 62521.99Skamil } 62531.126Skamil if (strcmp(fn, "vfork") == 0) { 62541.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 62551.99Skamil PTRACE_VFORK); 62561.99Skamil } 62571.1Skamil 62581.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 62591.1Skamil 62601.99Skamil DPRINTF("Before resuming the forkee process where it left off " 62611.99Skamil "and without signal to be sent\n"); 62621.99Skamil SYSCALL_REQUIRE( 62631.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 62641.1Skamil 62651.99Skamil DPRINTF("Before resuming the child process where it left off " 62661.99Skamil "and without signal to be sent\n"); 62671.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62681.1Skamil } 62691.1Skamil 62701.126Skamil if (strcmp(fn, "vforkdone") == 0) { 62711.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 62721.99Skamil child); 62731.99Skamil TWAIT_REQUIRE_SUCCESS( 62741.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 62751.1Skamil 62761.99Skamil validate_status_stopped(status, SIGTRAP); 62771.1Skamil 62781.99Skamil name[3] = child; 62791.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 62801.1Skamil 62811.102Skamil /* 62821.102Skamil * SIGCHLD is now pending in the signal queue and 62831.102Skamil * the kernel presents it to userland as a masked signal. 62841.102Skamil */ 62851.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 62861.102Skamil 62871.99Skamil if (masked) { 62881.99Skamil DPRINTF("kp_sigmask=" 62891.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 62901.99Skamil PRIx32 "\n", 62911.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 62921.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 62931.1Skamil 62941.99Skamil DPRINTF("kp.p_sigmask=" 62951.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 62961.99Skamil PRIx32 "\n", 62971.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 62981.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 62991.1Skamil 63001.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 63011.99Skamil sizeof(kp_sigmask))); 63021.99Skamil } 63031.1Skamil 63041.99Skamil if (ignored) { 63051.99Skamil DPRINTF("kp_sigignore=" 63061.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 63071.99Skamil PRIx32 "\n", 63081.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 63091.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 63101.1Skamil 63111.99Skamil DPRINTF("kp.p_sigignore=" 63121.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 63131.99Skamil PRIx32 "\n", 63141.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 63151.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 63161.1Skamil 63171.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 63181.99Skamil sizeof(kp_sigignore))); 63191.99Skamil } 63201.1Skamil 63211.99Skamil SYSCALL_REQUIRE( 63221.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 63231.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 63241.1Skamil 63251.99Skamil child2 = state.pe_other_pid; 63261.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 63271.99Skamil child2); 63281.1Skamil 63291.99Skamil DPRINTF("Before resuming the child process where it left off " 63301.99Skamil "and without signal to be sent\n"); 63311.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63321.99Skamil } 63331.1Skamil 63341.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 63351.126Skamil strcmp(fn, "vfork") == 0) { 63361.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 63371.99Skamil "\n", TWAIT_FNAME); 63381.99Skamil TWAIT_REQUIRE_SUCCESS( 63391.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 63401.1Skamil 63411.99Skamil validate_status_exited(status, exitval2); 63421.1Skamil 63431.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 63441.99Skamil "process\n", TWAIT_FNAME); 63451.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 63461.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 63471.99Skamil } 63481.1Skamil 63491.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63501.1Skamil "SIGCHLD\n", TWAIT_FNAME); 63511.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63521.1Skamil 63531.1Skamil validate_status_stopped(status, SIGCHLD); 63541.1Skamil 63551.57Skamil DPRINTF("Before resuming the child process where it left off and " 63561.1Skamil "without signal to be sent\n"); 63571.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63581.1Skamil 63591.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63601.1Skamil TWAIT_FNAME); 63611.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63621.1Skamil 63631.1Skamil validate_status_exited(status, exitval); 63641.1Skamil 63651.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63661.57Skamil TWAIT_FNAME); 63671.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63681.1Skamil} 63691.1Skamil 63701.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 63711.99SkamilATF_TC(name); \ 63721.99SkamilATF_TC_HEAD(name, tc) \ 63731.99Skamil{ \ 63741.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 63751.99Skamil "regardless of signal %s%s", \ 63761.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 63771.99Skamil} \ 63781.99Skamil \ 63791.99SkamilATF_TC_BODY(name, tc) \ 63801.99Skamil{ \ 63811.99Skamil \ 63821.126Skamil fork2_body(fn, masked, ignored); \ 63831.1Skamil} 63841.1Skamil 63851.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 63861.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 63871.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 63881.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 63891.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 63901.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 63911.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 63921.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 63931.1Skamil#endif 63941.1Skamil 63951.99Skamil/// ---------------------------------------------------------------------------- 63961.1Skamil 63971.83Skamilvolatile lwpid_t the_lwp_id = 0; 63981.83Skamil 63991.83Skamilstatic void 64001.83Skamillwp_main_func(void *arg) 64011.83Skamil{ 64021.83Skamil the_lwp_id = _lwp_self(); 64031.83Skamil _lwp_exit(); 64041.83Skamil} 64051.83Skamil 64061.1SkamilATF_TC(signal9); 64071.1SkamilATF_TC_HEAD(signal9, tc) 64081.1Skamil{ 64091.1Skamil atf_tc_set_md_var(tc, "descr", 64101.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 64111.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 64121.1Skamil} 64131.1Skamil 64141.1SkamilATF_TC_BODY(signal9, tc) 64151.1Skamil{ 64161.1Skamil const int exitval = 5; 64171.1Skamil const int sigval = SIGSTOP; 64181.1Skamil const int sigmasked = SIGTRAP; 64191.1Skamil pid_t child, wpid; 64201.1Skamil#if defined(TWAIT_HAVE_STATUS) 64211.1Skamil int status; 64221.1Skamil#endif 64231.1Skamil sigset_t intmask; 64241.1Skamil ptrace_state_t state; 64251.1Skamil const int slen = sizeof(state); 64261.1Skamil ptrace_event_t event; 64271.1Skamil const int elen = sizeof(event); 64281.1Skamil ucontext_t uc; 64291.1Skamil lwpid_t lid; 64301.1Skamil static const size_t ssize = 16*1024; 64311.1Skamil void *stack; 64321.1Skamil 64331.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64341.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64351.1Skamil if (child == 0) { 64361.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64371.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64381.1Skamil 64391.1Skamil sigemptyset(&intmask); 64401.1Skamil sigaddset(&intmask, sigmasked); 64411.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 64421.1Skamil 64431.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64441.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64451.1Skamil 64461.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 64471.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 64481.1Skamil 64491.13Schristos DPRINTF("Before making context for new lwp in child\n"); 64501.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 64511.1Skamil 64521.13Schristos DPRINTF("Before creating new in child\n"); 64531.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 64541.1Skamil 64551.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 64561.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 64571.1Skamil 64581.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 64591.1Skamil "are the same\n", lid, the_lwp_id); 64601.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 64611.1Skamil 64621.13Schristos DPRINTF("Before exiting of the child process\n"); 64631.1Skamil _exit(exitval); 64641.1Skamil } 64651.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64661.1Skamil 64671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64691.1Skamil 64701.1Skamil validate_status_stopped(status, sigval); 64711.1Skamil 64721.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 64731.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 64741.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 64751.1Skamil 64761.13Schristos DPRINTF("Before resuming the child process where it left off and " 64771.1Skamil "without signal to be sent\n"); 64781.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64791.1Skamil 64801.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64811.1Skamil "SIGTRAP\n", TWAIT_FNAME); 64821.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64831.1Skamil 64841.1Skamil validate_status_stopped(status, sigmasked); 64851.1Skamil 64861.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 64871.1Skamil 64881.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 64891.1Skamil 64901.1Skamil lid = state.pe_lwp; 64911.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 64921.1Skamil 64931.13Schristos DPRINTF("Before resuming the child process where it left off and " 64941.1Skamil "without signal to be sent\n"); 64951.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64961.1Skamil 64971.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 64981.1Skamil TWAIT_FNAME); 64991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65001.1Skamil 65011.1Skamil validate_status_exited(status, exitval); 65021.1Skamil 65031.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65041.1Skamil TWAIT_FNAME); 65051.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65061.1Skamil} 65071.1Skamil 65081.1SkamilATF_TC(signal10); 65091.1SkamilATF_TC_HEAD(signal10, tc) 65101.1Skamil{ 65111.1Skamil atf_tc_set_md_var(tc, "descr", 65121.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 65131.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 65141.1Skamil} 65151.1Skamil 65161.1SkamilATF_TC_BODY(signal10, tc) 65171.1Skamil{ 65181.1Skamil const int exitval = 5; 65191.1Skamil const int sigval = SIGSTOP; 65201.1Skamil const int sigmasked = SIGTRAP; 65211.1Skamil pid_t child, wpid; 65221.1Skamil#if defined(TWAIT_HAVE_STATUS) 65231.1Skamil int status; 65241.1Skamil#endif 65251.1Skamil sigset_t intmask; 65261.1Skamil ptrace_state_t state; 65271.1Skamil const int slen = sizeof(state); 65281.1Skamil ptrace_event_t event; 65291.1Skamil const int elen = sizeof(event); 65301.1Skamil ucontext_t uc; 65311.1Skamil lwpid_t lid; 65321.1Skamil static const size_t ssize = 16*1024; 65331.1Skamil void *stack; 65341.1Skamil 65351.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65361.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65371.1Skamil if (child == 0) { 65381.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65391.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65401.1Skamil 65411.1Skamil sigemptyset(&intmask); 65421.1Skamil sigaddset(&intmask, sigmasked); 65431.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 65441.1Skamil 65451.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65461.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65471.1Skamil 65481.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 65491.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 65501.1Skamil 65511.13Schristos DPRINTF("Before making context for new lwp in child\n"); 65521.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 65531.1Skamil 65541.13Schristos DPRINTF("Before creating new in child\n"); 65551.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 65561.1Skamil 65571.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 65581.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 65591.1Skamil 65601.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 65611.1Skamil "are the same\n", lid, the_lwp_id); 65621.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 65631.1Skamil 65641.13Schristos DPRINTF("Before exiting of the child process\n"); 65651.1Skamil _exit(exitval); 65661.1Skamil } 65671.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65681.1Skamil 65691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65711.1Skamil 65721.1Skamil validate_status_stopped(status, sigval); 65731.1Skamil 65741.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 65751.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 65761.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 65771.1Skamil 65781.13Schristos DPRINTF("Before resuming the child process where it left off and " 65791.1Skamil "without signal to be sent\n"); 65801.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65811.1Skamil 65821.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 65831.1Skamil "SIGTRAP\n", TWAIT_FNAME); 65841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65851.1Skamil 65861.1Skamil validate_status_stopped(status, sigmasked); 65871.1Skamil 65881.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 65891.1Skamil 65901.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 65911.1Skamil 65921.1Skamil lid = state.pe_lwp; 65931.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 65941.1Skamil 65951.13Schristos DPRINTF("Before resuming the child process where it left off and " 65961.1Skamil "without signal to be sent\n"); 65971.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65981.1Skamil 65991.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 66001.1Skamil TWAIT_FNAME); 66011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66021.1Skamil 66031.1Skamil validate_status_exited(status, exitval); 66041.1Skamil 66051.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 66061.1Skamil TWAIT_FNAME); 66071.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66081.1Skamil} 66091.1Skamil 66101.1Skamilstatic void 66111.1Skamillwp_main_stop(void *arg) 66121.1Skamil{ 66131.1Skamil the_lwp_id = _lwp_self(); 66141.1Skamil 66151.1Skamil raise(SIGTRAP); 66161.1Skamil 66171.1Skamil _lwp_exit(); 66181.1Skamil} 66191.1Skamil 66201.1SkamilATF_TC(suspend2); 66211.1SkamilATF_TC_HEAD(suspend2, tc) 66221.1Skamil{ 66231.1Skamil atf_tc_set_md_var(tc, "descr", 66241.1Skamil "Verify that the while the only thread within a process is " 66251.1Skamil "suspended, the whole process cannot be unstopped"); 66261.1Skamil} 66271.1Skamil 66281.1SkamilATF_TC_BODY(suspend2, tc) 66291.1Skamil{ 66301.1Skamil const int exitval = 5; 66311.1Skamil const int sigval = SIGSTOP; 66321.1Skamil pid_t child, wpid; 66331.1Skamil#if defined(TWAIT_HAVE_STATUS) 66341.1Skamil int status; 66351.1Skamil#endif 66361.1Skamil struct ptrace_siginfo psi; 66371.1Skamil 66381.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66391.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66401.1Skamil if (child == 0) { 66411.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66421.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66431.1Skamil 66441.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66451.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66461.1Skamil 66471.13Schristos DPRINTF("Before exiting of the child process\n"); 66481.1Skamil _exit(exitval); 66491.1Skamil } 66501.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66511.1Skamil 66521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66541.1Skamil 66551.1Skamil validate_status_stopped(status, sigval); 66561.1Skamil 66571.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 66581.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 66591.1Skamil 66601.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 66611.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 66621.1Skamil 66631.13Schristos DPRINTF("Before resuming the child process where it left off and " 66641.1Skamil "without signal to be sent\n"); 66651.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 66661.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 66671.1Skamil 66681.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 66691.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 66701.1Skamil 66711.13Schristos DPRINTF("Before resuming the child process where it left off and " 66721.1Skamil "without signal to be sent\n"); 66731.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66741.1Skamil 66751.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 66761.1Skamil TWAIT_FNAME); 66771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66781.1Skamil 66791.1Skamil validate_status_exited(status, exitval); 66801.1Skamil 66811.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 66821.1Skamil TWAIT_FNAME); 66831.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66841.1Skamil} 66851.1Skamil 66861.1SkamilATF_TC(resume1); 66871.1SkamilATF_TC_HEAD(resume1, tc) 66881.1Skamil{ 66891.1Skamil atf_tc_set_md_var(tc, "descr", 66901.1Skamil "Verify that a thread can be suspended by a debugger and later " 66911.1Skamil "resumed by the debugger"); 66921.1Skamil} 66931.1Skamil 66941.1SkamilATF_TC_BODY(resume1, tc) 66951.1Skamil{ 66961.1Skamil struct msg_fds fds; 66971.1Skamil const int exitval = 5; 66981.1Skamil const int sigval = SIGSTOP; 66991.1Skamil pid_t child, wpid; 67001.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 67011.1Skamil#if defined(TWAIT_HAVE_STATUS) 67021.1Skamil int status; 67031.1Skamil#endif 67041.1Skamil ucontext_t uc; 67051.1Skamil lwpid_t lid; 67061.1Skamil static const size_t ssize = 16*1024; 67071.1Skamil void *stack; 67081.1Skamil struct ptrace_lwpinfo pl; 67091.1Skamil struct ptrace_siginfo psi; 67101.1Skamil 67111.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 67121.1Skamil 67131.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 67141.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 67151.1Skamil if (child == 0) { 67161.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67171.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67181.1Skamil 67191.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67201.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67211.1Skamil 67221.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 67231.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 67241.1Skamil 67251.13Schristos DPRINTF("Before making context for new lwp in child\n"); 67261.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 67271.1Skamil 67281.13Schristos DPRINTF("Before creating new in child\n"); 67291.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 67301.1Skamil 67311.1Skamil CHILD_TO_PARENT("Message", fds, msg); 67321.1Skamil 67331.1Skamil raise(SIGINT); 67341.1Skamil 67351.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 67361.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 67371.1Skamil 67381.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 67391.1Skamil "are the same\n", lid, the_lwp_id); 67401.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 67411.1Skamil 67421.13Schristos DPRINTF("Before exiting of the child process\n"); 67431.1Skamil _exit(exitval); 67441.1Skamil } 67451.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67461.1Skamil 67471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67491.1Skamil 67501.1Skamil validate_status_stopped(status, sigval); 67511.1Skamil 67521.13Schristos DPRINTF("Before resuming the child process where it left off and " 67531.1Skamil "without signal to be sent\n"); 67541.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67551.1Skamil 67561.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 67571.1Skamil "SIGTRAP\n", TWAIT_FNAME); 67581.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67591.1Skamil 67601.1Skamil validate_status_stopped(status, SIGTRAP); 67611.1Skamil 67621.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 67631.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 67641.1Skamil 67651.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 67661.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 67671.1Skamil 67681.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 67691.1Skamil 67701.13Schristos DPRINTF("Before resuming the child process where it left off and " 67711.1Skamil "without signal to be sent\n"); 67721.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67731.1Skamil 67741.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 67751.1Skamil "SIGINT\n", TWAIT_FNAME); 67761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67771.1Skamil 67781.1Skamil validate_status_stopped(status, SIGINT); 67791.1Skamil 67801.1Skamil pl.pl_lwpid = 0; 67811.1Skamil 67821.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 67831.1Skamil while (pl.pl_lwpid != 0) { 67841.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 67851.1Skamil switch (pl.pl_lwpid) { 67861.1Skamil case 1: 67871.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 67881.1Skamil break; 67891.1Skamil case 2: 67901.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 67911.1Skamil break; 67921.1Skamil } 67931.1Skamil } 67941.1Skamil 67951.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 67961.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 67971.1Skamil 67981.13Schristos DPRINTF("Before resuming the child process where it left off and " 67991.1Skamil "without signal to be sent\n"); 68001.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68011.1Skamil 68021.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 68031.1Skamil TWAIT_FNAME); 68041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68051.1Skamil 68061.1Skamil validate_status_exited(status, exitval); 68071.1Skamil 68081.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 68091.1Skamil TWAIT_FNAME); 68101.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68111.1Skamil 68121.1Skamil msg_close(&fds); 68131.1Skamil} 68141.1Skamil 68151.1SkamilATF_TC(syscall1); 68161.1SkamilATF_TC_HEAD(syscall1, tc) 68171.1Skamil{ 68181.1Skamil atf_tc_set_md_var(tc, "descr", 68191.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 68201.1Skamil} 68211.1Skamil 68221.1SkamilATF_TC_BODY(syscall1, tc) 68231.1Skamil{ 68241.1Skamil const int exitval = 5; 68251.1Skamil const int sigval = SIGSTOP; 68261.1Skamil pid_t child, wpid; 68271.1Skamil#if defined(TWAIT_HAVE_STATUS) 68281.1Skamil int status; 68291.1Skamil#endif 68301.1Skamil struct ptrace_siginfo info; 68311.1Skamil memset(&info, 0, sizeof(info)); 68321.1Skamil 68331.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 68341.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 68351.1Skamil if (child == 0) { 68361.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 68371.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 68381.1Skamil 68391.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 68401.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 68411.1Skamil 68421.1Skamil syscall(SYS_getpid); 68431.1Skamil 68441.13Schristos DPRINTF("Before exiting of the child process\n"); 68451.1Skamil _exit(exitval); 68461.1Skamil } 68471.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 68481.1Skamil 68491.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68501.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68511.1Skamil 68521.1Skamil validate_status_stopped(status, sigval); 68531.1Skamil 68541.13Schristos DPRINTF("Before resuming the child process where it left off and " 68551.1Skamil "without signal to be sent\n"); 68561.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 68571.1Skamil 68581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68601.1Skamil 68611.1Skamil validate_status_stopped(status, SIGTRAP); 68621.1Skamil 68631.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 68641.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 68651.1Skamil 68661.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 68671.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 68681.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 68691.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 68701.1Skamil 68711.13Schristos DPRINTF("Before resuming the child process where it left off and " 68721.1Skamil "without signal to be sent\n"); 68731.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 68741.1Skamil 68751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68771.1Skamil 68781.1Skamil validate_status_stopped(status, SIGTRAP); 68791.1Skamil 68801.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 68811.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 68821.1Skamil 68831.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 68841.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 68851.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 68861.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 68871.1Skamil 68881.13Schristos DPRINTF("Before resuming the child process where it left off and " 68891.1Skamil "without signal to be sent\n"); 68901.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68911.1Skamil 68921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68941.1Skamil 68951.1Skamil validate_status_exited(status, exitval); 68961.1Skamil 68971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68981.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68991.1Skamil} 69001.1Skamil 69011.1SkamilATF_TC(syscallemu1); 69021.1SkamilATF_TC_HEAD(syscallemu1, tc) 69031.1Skamil{ 69041.1Skamil atf_tc_set_md_var(tc, "descr", 69051.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 69061.1Skamil} 69071.1Skamil 69081.1SkamilATF_TC_BODY(syscallemu1, tc) 69091.1Skamil{ 69101.1Skamil const int exitval = 5; 69111.1Skamil const int sigval = SIGSTOP; 69121.1Skamil pid_t child, wpid; 69131.1Skamil#if defined(TWAIT_HAVE_STATUS) 69141.1Skamil int status; 69151.1Skamil#endif 69161.1Skamil 69171.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 69181.6Skamil /* syscallemu does not work on sparc (32-bit) */ 69191.6Skamil atf_tc_expect_fail("PR kern/52166"); 69201.6Skamil#endif 69211.6Skamil 69221.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 69231.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 69241.1Skamil if (child == 0) { 69251.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 69261.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 69271.1Skamil 69281.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 69291.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 69301.1Skamil 69311.1Skamil syscall(SYS_exit, 100); 69321.1Skamil 69331.13Schristos DPRINTF("Before exiting of the child process\n"); 69341.1Skamil _exit(exitval); 69351.1Skamil } 69361.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 69371.1Skamil 69381.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 69391.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69401.1Skamil 69411.1Skamil validate_status_stopped(status, sigval); 69421.1Skamil 69431.13Schristos DPRINTF("Before resuming the child process where it left off and " 69441.1Skamil "without signal to be sent\n"); 69451.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 69461.1Skamil 69471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 69481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69491.1Skamil 69501.1Skamil validate_status_stopped(status, SIGTRAP); 69511.1Skamil 69521.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 69531.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 69541.1Skamil 69551.13Schristos DPRINTF("Before resuming the child process where it left off and " 69561.1Skamil "without signal to be sent\n"); 69571.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 69581.1Skamil 69591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 69601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69611.1Skamil 69621.1Skamil validate_status_stopped(status, SIGTRAP); 69631.1Skamil 69641.13Schristos DPRINTF("Before resuming the child process where it left off and " 69651.1Skamil "without signal to be sent\n"); 69661.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69671.1Skamil 69681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 69691.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69701.1Skamil 69711.1Skamil validate_status_exited(status, exitval); 69721.1Skamil 69731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 69741.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 69751.1Skamil} 69761.1Skamil 69771.103Skamil/// ---------------------------------------------------------------------------- 69781.103Skamil 69791.106Skamilstatic void 69801.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 69811.106Skamil bool trackvforkdone) 69821.106Skamil{ 69831.106Skamil const int exitval = 5; 69841.106Skamil const int exitval2 = 15; 69851.106Skamil const int sigval = SIGSTOP; 69861.106Skamil pid_t child, child2 = 0, wpid; 69871.106Skamil#if defined(TWAIT_HAVE_STATUS) 69881.106Skamil int status; 69891.106Skamil#endif 69901.106Skamil ptrace_state_t state; 69911.106Skamil const int slen = sizeof(state); 69921.106Skamil ptrace_event_t event; 69931.106Skamil const int elen = sizeof(event); 69941.106Skamil 69951.106Skamil const size_t stack_size = 1024 * 1024; 69961.106Skamil void *stack, *stack_base; 69971.106Skamil 69981.106Skamil stack = malloc(stack_size); 69991.106Skamil ATF_REQUIRE(stack != NULL); 70001.106Skamil 70011.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 70021.106Skamil stack_base = stack; 70031.106Skamil#else 70041.106Skamil stack_base = (char *)stack + stack_size; 70051.106Skamil#endif 70061.106Skamil 70071.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 70081.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70091.106Skamil if (child == 0) { 70101.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70111.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70121.106Skamil 70131.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70141.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 70151.106Skamil 70161.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 70171.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 70181.106Skamil 70191.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 70201.106Skamil child2); 70211.106Skamil 70221.106Skamil // XXX WALLSIG? 70231.106Skamil FORKEE_REQUIRE_SUCCESS 70241.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 70251.106Skamil 70261.106Skamil forkee_status_exited(status, exitval2); 70271.106Skamil 70281.106Skamil DPRINTF("Before exiting of the child process\n"); 70291.106Skamil _exit(exitval); 70301.106Skamil } 70311.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 70321.106Skamil 70331.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 70341.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70351.106Skamil 70361.106Skamil validate_status_stopped(status, sigval); 70371.106Skamil 70381.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 70391.106Skamil trackfork ? "|PTRACE_FORK" : "", 70401.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 70411.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 70421.106Skamil event.pe_set_event = 0; 70431.106Skamil if (trackfork) 70441.106Skamil event.pe_set_event |= PTRACE_FORK; 70451.106Skamil if (trackvfork) 70461.106Skamil event.pe_set_event |= PTRACE_VFORK; 70471.106Skamil if (trackvforkdone) 70481.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 70491.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 70501.106Skamil 70511.106Skamil DPRINTF("Before resuming the child process where it left off and " 70521.106Skamil "without signal to be sent\n"); 70531.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70541.106Skamil 70551.106Skamil#if defined(TWAIT_HAVE_PID) 70561.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 70571.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 70581.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 70591.106Skamil child); 70601.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 70611.106Skamil child); 70621.106Skamil 70631.106Skamil validate_status_stopped(status, SIGTRAP); 70641.106Skamil 70651.106Skamil SYSCALL_REQUIRE( 70661.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 70671.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 70681.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 70691.106Skamil PTRACE_FORK); 70701.106Skamil } 70711.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 70721.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 70731.106Skamil PTRACE_VFORK); 70741.106Skamil } 70751.106Skamil 70761.106Skamil child2 = state.pe_other_pid; 70771.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 70781.106Skamil 70791.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 70801.106Skamil "%d\n", TWAIT_FNAME, child2, child); 70811.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 70821.106Skamil child2); 70831.106Skamil 70841.106Skamil validate_status_stopped(status, SIGTRAP); 70851.106Skamil 70861.106Skamil SYSCALL_REQUIRE( 70871.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 70881.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 70891.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 70901.106Skamil PTRACE_FORK); 70911.106Skamil } 70921.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 70931.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 70941.106Skamil PTRACE_VFORK); 70951.106Skamil } 70961.106Skamil 70971.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 70981.106Skamil 70991.106Skamil DPRINTF("Before resuming the forkee process where it left off " 71001.106Skamil "and without signal to be sent\n"); 71011.106Skamil SYSCALL_REQUIRE( 71021.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 71031.106Skamil 71041.106Skamil DPRINTF("Before resuming the child process where it left off " 71051.106Skamil "and without signal to be sent\n"); 71061.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71071.106Skamil } 71081.106Skamil#endif 71091.106Skamil 71101.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 71111.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 71121.106Skamil child); 71131.106Skamil TWAIT_REQUIRE_SUCCESS( 71141.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 71151.106Skamil 71161.106Skamil validate_status_stopped(status, SIGTRAP); 71171.106Skamil 71181.106Skamil SYSCALL_REQUIRE( 71191.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71201.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 71211.106Skamil 71221.106Skamil child2 = state.pe_other_pid; 71231.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 71241.106Skamil child2); 71251.106Skamil 71261.106Skamil DPRINTF("Before resuming the child process where it left off " 71271.106Skamil "and without signal to be sent\n"); 71281.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71291.106Skamil } 71301.106Skamil 71311.103Skamil#if defined(TWAIT_HAVE_PID) 71321.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 71331.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 71341.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 71351.106Skamil "\n", TWAIT_FNAME); 71361.106Skamil TWAIT_REQUIRE_SUCCESS( 71371.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 71381.106Skamil 71391.106Skamil validate_status_exited(status, exitval2); 71401.106Skamil 71411.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 71421.106Skamil "process\n", TWAIT_FNAME); 71431.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 71441.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 71451.106Skamil } 71461.106Skamil#endif 71471.106Skamil 71481.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71491.106Skamil "SIGCHLD\n", TWAIT_FNAME); 71501.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71511.106Skamil 71521.106Skamil validate_status_stopped(status, SIGCHLD); 71531.106Skamil 71541.106Skamil DPRINTF("Before resuming the child process where it left off and " 71551.106Skamil "without signal to be sent\n"); 71561.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71571.106Skamil 71581.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 71591.106Skamil TWAIT_FNAME); 71601.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71611.106Skamil 71621.106Skamil validate_status_exited(status, exitval); 71631.103Skamil 71641.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 71651.106Skamil TWAIT_FNAME); 71661.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 71671.106Skamil} 71681.103Skamil 71691.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 71701.106SkamilATF_TC(name); \ 71711.106SkamilATF_TC_HEAD(name, tc) \ 71721.106Skamil{ \ 71731.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 71741.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 71751.106Skamil #flags, \ 71761.106Skamil tfork ? "|PTRACE_FORK" : "", \ 71771.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 71781.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 71791.106Skamil} \ 71801.106Skamil \ 71811.106SkamilATF_TC_BODY(name, tc) \ 71821.106Skamil{ \ 71831.106Skamil \ 71841.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 71851.103Skamil} 71861.103Skamil 71871.106SkamilCLONE_TEST(clone1, 0, false, false, false) 71881.106Skamil#if defined(TWAIT_HAVE_PID) 71891.106SkamilCLONE_TEST(clone2, 0, true, false, false) 71901.106SkamilCLONE_TEST(clone3, 0, false, true, false) 71911.106SkamilCLONE_TEST(clone4, 0, true, true, false) 71921.106Skamil#endif 71931.106SkamilCLONE_TEST(clone5, 0, false, false, true) 71941.106Skamil#if defined(TWAIT_HAVE_PID) 71951.106SkamilCLONE_TEST(clone6, 0, true, false, true) 71961.106SkamilCLONE_TEST(clone7, 0, false, true, true) 71971.106SkamilCLONE_TEST(clone8, 0, true, true, true) 71981.106Skamil#endif 71991.106Skamil 72001.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 72011.106Skamil#if defined(TWAIT_HAVE_PID) 72021.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 72031.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 72041.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 72051.106Skamil#endif 72061.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 72071.106Skamil#if defined(TWAIT_HAVE_PID) 72081.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 72091.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 72101.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 72111.106Skamil#endif 72121.106Skamil 72131.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 72141.106Skamil#if defined(TWAIT_HAVE_PID) 72151.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 72161.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 72171.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 72181.106Skamil#endif 72191.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 72201.106Skamil#if defined(TWAIT_HAVE_PID) 72211.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 72221.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 72231.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 72241.106Skamil#endif 72251.106Skamil 72261.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 72271.106Skamil#if defined(TWAIT_HAVE_PID) 72281.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 72291.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 72301.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 72311.106Skamil#endif 72321.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 72331.106Skamil#if defined(TWAIT_HAVE_PID) 72341.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 72351.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 72361.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 72371.106Skamil#endif 72381.106Skamil 72391.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 72401.106Skamil#if defined(TWAIT_HAVE_PID) 72411.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 72421.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 72431.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 72441.106Skamil#endif 72451.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 72461.106Skamil#if defined(TWAIT_HAVE_PID) 72471.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 72481.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 72491.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 72501.106Skamil#endif 72511.106Skamil 72521.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 72531.106Skamil#if defined(TWAIT_HAVE_PID) 72541.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 72551.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 72561.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 72571.106Skamil#endif 72581.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 72591.106Skamil#if defined(TWAIT_HAVE_PID) 72601.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 72611.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 72621.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 72631.106Skamil#endif 72641.106Skamil 72651.106Skamil/// ---------------------------------------------------------------------------- 72661.106Skamil 72671.106Skamil#if defined(TWAIT_HAVE_PID) 72681.103Skamilstatic void 72691.106Skamilclone_body2(int flags, bool masked, bool ignored) 72701.103Skamil{ 72711.103Skamil const int exitval = 5; 72721.103Skamil const int exitval2 = 15; 72731.103Skamil const int sigval = SIGSTOP; 72741.103Skamil pid_t child, child2 = 0, wpid; 72751.103Skamil#if defined(TWAIT_HAVE_STATUS) 72761.103Skamil int status; 72771.103Skamil#endif 72781.103Skamil ptrace_state_t state; 72791.103Skamil const int slen = sizeof(state); 72801.103Skamil ptrace_event_t event; 72811.103Skamil const int elen = sizeof(event); 72821.103Skamil struct sigaction sa; 72831.103Skamil struct ptrace_siginfo info; 72841.103Skamil sigset_t intmask; 72851.103Skamil struct kinfo_proc2 kp; 72861.103Skamil size_t len = sizeof(kp); 72871.103Skamil 72881.103Skamil int name[6]; 72891.103Skamil const size_t namelen = __arraycount(name); 72901.103Skamil ki_sigset_t kp_sigmask; 72911.103Skamil ki_sigset_t kp_sigignore; 72921.103Skamil 72931.103Skamil const size_t stack_size = 1024 * 1024; 72941.103Skamil void *stack, *stack_base; 72951.103Skamil 72961.103Skamil stack = malloc(stack_size); 72971.103Skamil ATF_REQUIRE(stack != NULL); 72981.103Skamil 72991.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 73001.103Skamil stack_base = stack; 73011.103Skamil#else 73021.103Skamil stack_base = (char *)stack + stack_size; 73031.103Skamil#endif 73041.103Skamil 73051.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 73061.103Skamil if (child == 0) { 73071.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 73081.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 73091.103Skamil 73101.103Skamil if (masked) { 73111.103Skamil sigemptyset(&intmask); 73121.103Skamil sigaddset(&intmask, SIGTRAP); 73131.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 73141.103Skamil } 73151.103Skamil 73161.103Skamil if (ignored) { 73171.103Skamil memset(&sa, 0, sizeof(sa)); 73181.103Skamil sa.sa_handler = SIG_IGN; 73191.103Skamil sigemptyset(&sa.sa_mask); 73201.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 73211.103Skamil } 73221.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 73231.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 73241.103Skamil 73251.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 73261.103Skamil flags); 73271.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 73281.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 73291.103Skamil 73301.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 73311.103Skamil child2); 73321.103Skamil 73331.103Skamil // XXX WALLSIG? 73341.103Skamil FORKEE_REQUIRE_SUCCESS 73351.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 73361.103Skamil 73371.103Skamil forkee_status_exited(status, exitval2); 73381.103Skamil 73391.103Skamil DPRINTF("Before exiting of the child process\n"); 73401.103Skamil _exit(exitval); 73411.103Skamil } 73421.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 73431.103Skamil 73441.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 73451.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73461.103Skamil 73471.103Skamil validate_status_stopped(status, sigval); 73481.103Skamil 73491.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 73501.103Skamil SYSCALL_REQUIRE( 73511.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 73521.103Skamil 73531.103Skamil DPRINTF("Before checking siginfo_t\n"); 73541.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 73551.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 73561.103Skamil 73571.103Skamil name[0] = CTL_KERN, 73581.103Skamil name[1] = KERN_PROC2, 73591.103Skamil name[2] = KERN_PROC_PID; 73601.103Skamil name[3] = child; 73611.103Skamil name[4] = sizeof(kp); 73621.103Skamil name[5] = 1; 73631.103Skamil 73641.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 73651.103Skamil 73661.103Skamil if (masked) 73671.103Skamil kp_sigmask = kp.p_sigmask; 73681.103Skamil 73691.103Skamil if (ignored) 73701.103Skamil kp_sigignore = kp.p_sigignore; 73711.103Skamil 73721.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 73731.103Skamil "EVENT_MASK for the child %d\n", child); 73741.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 73751.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 73761.103Skamil 73771.103Skamil DPRINTF("Before resuming the child process where it left off and " 73781.103Skamil "without signal to be sent\n"); 73791.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73801.103Skamil 73811.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 73821.103Skamil child); 73831.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 73841.103Skamil child); 73851.103Skamil 73861.103Skamil validate_status_stopped(status, SIGTRAP); 73871.103Skamil 73881.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 73891.103Skamil 73901.103Skamil if (masked) { 73911.103Skamil DPRINTF("kp_sigmask=" 73921.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73931.103Skamil PRIx32 "\n", 73941.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 73951.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 73961.103Skamil 73971.103Skamil DPRINTF("kp.p_sigmask=" 73981.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73991.103Skamil PRIx32 "\n", 74001.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 74011.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 74021.103Skamil 74031.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 74041.103Skamil sizeof(kp_sigmask))); 74051.103Skamil } 74061.103Skamil 74071.103Skamil if (ignored) { 74081.103Skamil DPRINTF("kp_sigignore=" 74091.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 74101.103Skamil PRIx32 "\n", 74111.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 74121.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 74131.103Skamil 74141.103Skamil DPRINTF("kp.p_sigignore=" 74151.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 74161.103Skamil PRIx32 "\n", 74171.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 74181.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 74191.103Skamil 74201.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 74211.103Skamil sizeof(kp_sigignore))); 74221.103Skamil } 74231.103Skamil 74241.103Skamil SYSCALL_REQUIRE( 74251.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 74261.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 74271.103Skamil child2); 74281.103Skamil if (!(flags & CLONE_VFORK)) { 74291.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 74301.103Skamil PTRACE_FORK); 74311.103Skamil } else { 74321.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 74331.103Skamil PTRACE_VFORK); 74341.103Skamil } 74351.103Skamil 74361.103Skamil child2 = state.pe_other_pid; 74371.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 74381.103Skamil 74391.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 74401.103Skamil "%d\n", TWAIT_FNAME, child2, child); 74411.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 74421.103Skamil child2); 74431.103Skamil 74441.103Skamil validate_status_stopped(status, SIGTRAP); 74451.103Skamil 74461.103Skamil name[3] = child2; 74471.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 74481.103Skamil 74491.103Skamil if (masked) { 74501.103Skamil DPRINTF("kp_sigmask=" 74511.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 74521.103Skamil PRIx32 "\n", 74531.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 74541.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 74551.103Skamil 74561.103Skamil DPRINTF("kp.p_sigmask=" 74571.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 74581.103Skamil PRIx32 "\n", 74591.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 74601.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 74611.103Skamil 74621.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 74631.103Skamil sizeof(kp_sigmask))); 74641.103Skamil } 74651.103Skamil 74661.103Skamil if (ignored) { 74671.103Skamil DPRINTF("kp_sigignore=" 74681.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 74691.103Skamil PRIx32 "\n", 74701.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 74711.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 74721.103Skamil 74731.103Skamil DPRINTF("kp.p_sigignore=" 74741.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 74751.103Skamil PRIx32 "\n", 74761.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 74771.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 74781.103Skamil 74791.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 74801.103Skamil sizeof(kp_sigignore))); 74811.103Skamil } 74821.103Skamil 74831.103Skamil SYSCALL_REQUIRE( 74841.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 74851.103Skamil if (!(flags & CLONE_VFORK)) { 74861.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 74871.103Skamil PTRACE_FORK); 74881.103Skamil } else { 74891.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 74901.103Skamil PTRACE_VFORK); 74911.103Skamil } 74921.103Skamil 74931.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 74941.103Skamil 74951.103Skamil DPRINTF("Before resuming the forkee process where it left off " 74961.103Skamil "and without signal to be sent\n"); 74971.103Skamil SYSCALL_REQUIRE( 74981.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 74991.103Skamil 75001.103Skamil DPRINTF("Before resuming the child process where it left off " 75011.103Skamil "and without signal to be sent\n"); 75021.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 75031.103Skamil 75041.103Skamil if (flags & CLONE_VFORK) { 75051.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 75061.103Skamil child); 75071.103Skamil TWAIT_REQUIRE_SUCCESS( 75081.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 75091.103Skamil 75101.103Skamil validate_status_stopped(status, SIGTRAP); 75111.103Skamil 75121.103Skamil name[3] = child; 75131.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 75141.103Skamil 75151.103Skamil /* 75161.103Skamil * SIGCHLD is now pending in the signal queue and 75171.103Skamil * the kernel presents it to userland as a masked signal. 75181.103Skamil */ 75191.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 75201.103Skamil 75211.103Skamil if (masked) { 75221.103Skamil DPRINTF("kp_sigmask=" 75231.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 75241.103Skamil PRIx32 "\n", 75251.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 75261.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 75271.103Skamil 75281.103Skamil DPRINTF("kp.p_sigmask=" 75291.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 75301.103Skamil PRIx32 "\n", 75311.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 75321.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 75331.103Skamil 75341.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 75351.103Skamil sizeof(kp_sigmask))); 75361.103Skamil } 75371.103Skamil 75381.103Skamil if (ignored) { 75391.103Skamil DPRINTF("kp_sigignore=" 75401.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 75411.103Skamil PRIx32 "\n", 75421.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 75431.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 75441.103Skamil 75451.103Skamil DPRINTF("kp.p_sigignore=" 75461.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 75471.103Skamil PRIx32 "\n", 75481.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 75491.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 75501.103Skamil 75511.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 75521.103Skamil sizeof(kp_sigignore))); 75531.103Skamil } 75541.103Skamil 75551.103Skamil SYSCALL_REQUIRE( 75561.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 75571.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 75581.103Skamil 75591.103Skamil child2 = state.pe_other_pid; 75601.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 75611.103Skamil child2); 75621.103Skamil 75631.103Skamil DPRINTF("Before resuming the child process where it left off " 75641.103Skamil "and without signal to be sent\n"); 75651.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 75661.103Skamil } 75671.103Skamil 75681.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 75691.103Skamil "\n", TWAIT_FNAME); 75701.103Skamil TWAIT_REQUIRE_SUCCESS( 75711.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 75721.103Skamil 75731.103Skamil validate_status_exited(status, exitval2); 75741.103Skamil 75751.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 75761.103Skamil "process\n", TWAIT_FNAME); 75771.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 75781.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 75791.103Skamil 75801.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 75811.103Skamil "SIGCHLD\n", TWAIT_FNAME); 75821.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75831.103Skamil 75841.103Skamil validate_status_stopped(status, SIGCHLD); 75851.103Skamil 75861.103Skamil DPRINTF("Before resuming the child process where it left off and " 75871.103Skamil "without signal to be sent\n"); 75881.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 75891.103Skamil 75901.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 75911.103Skamil TWAIT_FNAME); 75921.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75931.103Skamil 75941.103Skamil validate_status_exited(status, exitval); 75951.103Skamil 75961.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 75971.103Skamil TWAIT_FNAME); 75981.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75991.103Skamil} 76001.103Skamil 76011.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 76021.103SkamilATF_TC(name); \ 76031.103SkamilATF_TC_HEAD(name, tc) \ 76041.103Skamil{ \ 76051.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 76061.103Skamil " regardless of signal %s%s", \ 76071.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 76081.103Skamil} \ 76091.103Skamil \ 76101.103SkamilATF_TC_BODY(name, tc) \ 76111.103Skamil{ \ 76121.103Skamil \ 76131.106Skamil clone_body2(flags, masked, ignored); \ 76141.103Skamil} 76151.103Skamil 76161.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 76171.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 76181.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 76191.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 76201.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 76211.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 76221.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 76231.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 76241.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 76251.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 76261.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 76271.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 76281.103Skamil#endif 76291.103Skamil 76301.103Skamil/// ---------------------------------------------------------------------------- 76311.103Skamil 76321.107Skamil#if defined(TWAIT_HAVE_PID) 76331.107Skamilstatic void 76341.107Skamiltraceme_vfork_clone_body(int flags) 76351.107Skamil{ 76361.107Skamil const int exitval = 5; 76371.107Skamil const int exitval2 = 15; 76381.107Skamil pid_t child, child2 = 0, wpid; 76391.107Skamil#if defined(TWAIT_HAVE_STATUS) 76401.107Skamil int status; 76411.107Skamil#endif 76421.107Skamil 76431.107Skamil const size_t stack_size = 1024 * 1024; 76441.107Skamil void *stack, *stack_base; 76451.107Skamil 76461.107Skamil stack = malloc(stack_size); 76471.107Skamil ATF_REQUIRE(stack != NULL); 76481.107Skamil 76491.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 76501.107Skamil stack_base = stack; 76511.107Skamil#else 76521.107Skamil stack_base = (char *)stack + stack_size; 76531.107Skamil#endif 76541.107Skamil 76551.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 76561.107Skamil if (child == 0) { 76571.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 76581.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 76591.107Skamil 76601.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 76611.107Skamil flags); 76621.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 76631.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 76641.107Skamil 76651.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 76661.107Skamil child2); 76671.107Skamil 76681.107Skamil // XXX WALLSIG? 76691.107Skamil FORKEE_REQUIRE_SUCCESS 76701.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 76711.107Skamil 76721.107Skamil forkee_status_exited(status, exitval2); 76731.107Skamil 76741.107Skamil DPRINTF("Before exiting of the child process\n"); 76751.107Skamil _exit(exitval); 76761.107Skamil } 76771.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 76781.107Skamil 76791.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 76801.107Skamil TWAIT_FNAME); 76811.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76821.107Skamil 76831.107Skamil validate_status_exited(status, exitval); 76841.107Skamil 76851.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 76861.107Skamil TWAIT_FNAME); 76871.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76881.107Skamil} 76891.107Skamil 76901.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 76911.107SkamilATF_TC(name); \ 76921.107SkamilATF_TC_HEAD(name, tc) \ 76931.107Skamil{ \ 76941.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 76951.107Skamil "handled correctly with vfork(2)ed tracer", \ 76961.107Skamil #flags); \ 76971.107Skamil} \ 76981.107Skamil \ 76991.107SkamilATF_TC_BODY(name, tc) \ 77001.107Skamil{ \ 77011.107Skamil \ 77021.107Skamil traceme_vfork_clone_body(flags); \ 77031.107Skamil} 77041.107Skamil 77051.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 77061.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 77071.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 77081.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 77091.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 77101.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 77111.107Skamil#endif 77121.107Skamil 77131.107Skamil/// ---------------------------------------------------------------------------- 77141.107Skamil 77151.122Skamilstatic void 77161.122Skamiluser_va0_disable(int operation) 77171.122Skamil{ 77181.122Skamil pid_t child, wpid; 77191.122Skamil#if defined(TWAIT_HAVE_STATUS) 77201.122Skamil int status; 77211.122Skamil#endif 77221.122Skamil const int sigval = SIGSTOP; 77231.122Skamil int rv; 77241.122Skamil 77251.122Skamil struct ptrace_siginfo info; 77261.122Skamil 77271.122Skamil if (get_user_va0_disable() == 0) 77281.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 77291.122Skamil 77301.122Skamil memset(&info, 0, sizeof(info)); 77311.122Skamil 77321.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 77331.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 77341.122Skamil if (child == 0) { 77351.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 77361.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 77371.122Skamil 77381.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 77391.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 77401.122Skamil 77411.122Skamil /* NOTREACHED */ 77421.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 77431.122Skamil __unreachable(); 77441.122Skamil } 77451.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 77461.122Skamil 77471.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77481.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77491.122Skamil 77501.122Skamil validate_status_stopped(status, sigval); 77511.122Skamil 77521.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 77531.122Skamil "child\n"); 77541.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 77551.122Skamil sizeof(info)) != -1); 77561.122Skamil 77571.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 77581.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 77591.122Skamil "si_errno=%#x\n", 77601.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 77611.122Skamil info.psi_siginfo.si_errno); 77621.122Skamil 77631.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 77641.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 77651.122Skamil 77661.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 77671.122Skamil "and without signal to be sent\n"); 77681.122Skamil errno = 0; 77691.122Skamil rv = ptrace(operation, child, (void *)0, 0); 77701.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 77711.122Skamil ATF_REQUIRE_EQ(rv, -1); 77721.122Skamil 77731.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 77741.122Skamil 77751.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77761.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77771.122Skamil validate_status_signaled(status, SIGKILL, 0); 77781.122Skamil 77791.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77801.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 77811.122Skamil} 77821.122Skamil 77831.122Skamil#define USER_VA0_DISABLE(test, operation) \ 77841.122SkamilATF_TC(test); \ 77851.122SkamilATF_TC_HEAD(test, tc) \ 77861.122Skamil{ \ 77871.122Skamil atf_tc_set_md_var(tc, "descr", \ 77881.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 77891.122Skamil} \ 77901.122Skamil \ 77911.122SkamilATF_TC_BODY(test, tc) \ 77921.122Skamil{ \ 77931.122Skamil \ 77941.122Skamil user_va0_disable(operation); \ 77951.122Skamil} 77961.122Skamil 77971.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 77981.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 77991.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 78001.122Skamil 78011.122Skamil/// ---------------------------------------------------------------------------- 78021.122Skamil 78031.130Smgorny/* 78041.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 78051.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 78061.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 78071.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 78081.130Smgorny * found, -1 is returned. 78091.130Smgorny */ 78101.130Smgornystatic ssize_t core_find_note(const char *core_path, 78111.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 78121.130Smgorny{ 78131.130Smgorny int core_fd; 78141.130Smgorny Elf *core_elf; 78151.130Smgorny size_t core_numhdr, i; 78161.130Smgorny ssize_t ret = -1; 78171.130Smgorny /* note: we assume note name will be null-terminated */ 78181.130Smgorny size_t name_len = strlen(note_name) + 1; 78191.130Smgorny 78201.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 78211.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 78221.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 78231.130Smgorny 78241.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 78251.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 78261.130Smgorny GElf_Phdr core_hdr; 78271.130Smgorny size_t offset; 78281.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 78291.130Smgorny if (core_hdr.p_type != PT_NOTE) 78301.130Smgorny continue; 78311.130Smgorny 78321.130Smgorny for (offset = core_hdr.p_offset; 78331.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 78341.130Smgorny Elf64_Nhdr note_hdr; 78351.130Smgorny char name_buf[64]; 78361.130Smgorny 78371.130Smgorny switch (gelf_getclass(core_elf)) { 78381.130Smgorny case ELFCLASS64: 78391.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 78401.130Smgorny sizeof(note_hdr), offset) 78411.130Smgorny == sizeof(note_hdr)); 78421.130Smgorny offset += sizeof(note_hdr); 78431.130Smgorny break; 78441.130Smgorny case ELFCLASS32: 78451.130Smgorny { 78461.130Smgorny Elf32_Nhdr tmp_hdr; 78471.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 78481.130Smgorny sizeof(tmp_hdr), offset) 78491.130Smgorny == sizeof(tmp_hdr)); 78501.130Smgorny offset += sizeof(tmp_hdr); 78511.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 78521.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 78531.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 78541.130Smgorny } 78551.130Smgorny break; 78561.130Smgorny } 78571.130Smgorny 78581.130Smgorny /* indicates end of notes */ 78591.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 78601.130Smgorny break; 78611.130Smgorny if (note_hdr.n_namesz == name_len && 78621.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 78631.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 78641.130Smgorny note_hdr.n_namesz, offset) 78651.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 78661.130Smgorny 78671.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 78681.130Smgorny note_hdr.n_type == note_type) 78691.130Smgorny ret = note_hdr.n_descsz; 78701.130Smgorny } 78711.130Smgorny 78721.130Smgorny offset += note_hdr.n_namesz; 78731.130Smgorny /* fix to alignment */ 78741.146Smgorny offset = roundup(offset, core_hdr.p_align); 78751.130Smgorny 78761.130Smgorny /* if name & type matched above */ 78771.130Smgorny if (ret != -1) { 78781.130Smgorny ssize_t read_len = MIN(buf_len, 78791.130Smgorny note_hdr.n_descsz); 78801.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 78811.130Smgorny read_len, offset) == read_len); 78821.130Smgorny break; 78831.130Smgorny } 78841.130Smgorny 78851.130Smgorny offset += note_hdr.n_descsz; 78861.146Smgorny /* fix to alignment */ 78871.146Smgorny offset = roundup(offset, core_hdr.p_align); 78881.130Smgorny } 78891.130Smgorny } 78901.130Smgorny 78911.130Smgorny elf_end(core_elf); 78921.130Smgorny close(core_fd); 78931.130Smgorny 78941.130Smgorny return ret; 78951.130Smgorny} 78961.130Smgorny 78971.130SmgornyATF_TC(core_dump_procinfo); 78981.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 78991.130Smgorny{ 79001.130Smgorny atf_tc_set_md_var(tc, "descr", 79011.130Smgorny "Trigger a core dump and verify its contents."); 79021.130Smgorny} 79031.130Smgorny 79041.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 79051.130Smgorny{ 79061.130Smgorny const int exitval = 5; 79071.130Smgorny pid_t child, wpid; 79081.130Smgorny#if defined(TWAIT_HAVE_STATUS) 79091.130Smgorny const int sigval = SIGTRAP; 79101.130Smgorny int status; 79111.130Smgorny#endif 79121.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 79131.130Smgorny int core_fd; 79141.130Smgorny struct netbsd_elfcore_procinfo procinfo; 79151.130Smgorny 79161.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 79171.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 79181.130Smgorny if (child == 0) { 79191.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 79201.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 79211.130Smgorny 79221.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 79231.130Smgorny trigger_trap(); 79241.130Smgorny 79251.130Smgorny DPRINTF("Before exiting of the child process\n"); 79261.130Smgorny _exit(exitval); 79271.130Smgorny } 79281.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 79291.130Smgorny 79301.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 79311.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 79321.130Smgorny 79331.130Smgorny validate_status_stopped(status, sigval); 79341.130Smgorny 79351.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 79361.130Smgorny close(core_fd); 79371.130Smgorny 79381.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 79391.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 79401.130Smgorny != -1); 79411.130Smgorny 79421.130Smgorny DPRINTF("Read core file\n"); 79431.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 79441.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 79451.130Smgorny sizeof(procinfo)); 79461.130Smgorny 79471.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 79481.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 79491.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 79501.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 79511.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 79521.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 79531.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 79541.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 79551.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 79561.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 79571.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 79581.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 79591.130Smgorny ATF_CHECK_EQ(procinfo.cpi_siglwp, 1); 79601.130Smgorny 79611.130Smgorny unlink(core_path); 79621.130Smgorny 79631.130Smgorny DPRINTF("Before resuming the child process where it left off and " 79641.130Smgorny "without signal to be sent\n"); 79651.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 79661.130Smgorny 79671.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 79681.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 79691.130Smgorny 79701.130Smgorny validate_status_exited(status, exitval); 79711.130Smgorny 79721.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 79731.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 79741.130Smgorny} 79751.130Smgorny 79761.130Smgorny/// ---------------------------------------------------------------------------- 79771.130Smgorny 79781.138Smgorny#if defined(TWAIT_HAVE_STATUS) 79791.138Smgorny 79801.138SmgornyATF_TC(thread_concurrent_signals); 79811.138SmgornyATF_TC_HEAD(thread_concurrent_signals, tc) 79821.138Smgorny{ 79831.138Smgorny atf_tc_set_md_var(tc, "descr", 79841.138Smgorny "Verify that concurrent signals issued to a single thread " 79851.138Smgorny "are reported correctly"); 79861.138Smgorny} 79871.138Smgorny 79881.138Smgorny/* List of signals to use for the test */ 79891.138Smgornyconst int thread_concurrent_signals_list[] = { 79901.138Smgorny SIGIO, 79911.138Smgorny SIGXCPU, 79921.138Smgorny SIGXFSZ, 79931.138Smgorny SIGVTALRM, 79941.138Smgorny SIGPROF, 79951.138Smgorny SIGWINCH, 79961.138Smgorny SIGINFO, 79971.138Smgorny SIGUSR1, 79981.138Smgorny SIGUSR2 79991.138Smgorny}; 80001.138Smgorny 80011.138Smgornypthread_barrier_t thread_concurrent_signals_barrier; 80021.138Smgorny 80031.138Smgornystatic void * 80041.138Smgornythread_concurrent_signals_thread(void *arg) 80051.138Smgorny{ 80061.138Smgorny int sigval = thread_concurrent_signals_list[ 80071.138Smgorny _lwp_self() % __arraycount(thread_concurrent_signals_list)]; 80081.138Smgorny pthread_barrier_wait(&thread_concurrent_signals_barrier); 80091.138Smgorny DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval), 80101.138Smgorny _lwp_self()); 80111.138Smgorny pthread_kill(pthread_self(), sigval); 80121.138Smgorny return NULL; 80131.138Smgorny} 80141.138Smgorny 80151.138Smgorny#define THREAD_CONCURRENT_SIGNALS_NUM 50 80161.138Smgorny 80171.138SmgornyATF_TC_BODY(thread_concurrent_signals, tc) 80181.138Smgorny{ 80191.138Smgorny const int exitval = 5; 80201.138Smgorny const int sigval = SIGSTOP; 80211.138Smgorny pid_t child, wpid; 80221.138Smgorny int status; 80231.141Skamil struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM] 80241.141Skamil = {{0, 0}}; 80251.138Smgorny unsigned int i; 80261.138Smgorny 80271.138Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 80281.138Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 80291.138Smgorny if (child == 0) { 80301.138Smgorny pthread_t threads[THREAD_CONCURRENT_SIGNALS_NUM]; 80311.138Smgorny 80321.138Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 80331.138Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 80341.138Smgorny 80351.138Smgorny DPRINTF("Before raising %s from child\n", strsignal(sigval)); 80361.138Smgorny FORKEE_ASSERT(raise(sigval) == 0); 80371.138Smgorny 80381.138Smgorny DPRINTF("Before starting threads from the child\n"); 80391.138Smgorny FORKEE_ASSERT(pthread_barrier_init( 80401.138Smgorny &thread_concurrent_signals_barrier, NULL, 80411.138Smgorny __arraycount(threads)) == 0); 80421.138Smgorny 80431.138Smgorny for (i = 0; i < __arraycount(threads); i++) { 80441.138Smgorny FORKEE_ASSERT(pthread_create(&threads[i], NULL, 80451.138Smgorny thread_concurrent_signals_thread, NULL) == 0); 80461.138Smgorny } 80471.138Smgorny 80481.138Smgorny DPRINTF("Before joining threads from the child\n"); 80491.138Smgorny for (i = 0; i < __arraycount(threads); i++) { 80501.138Smgorny FORKEE_ASSERT(pthread_join(threads[i], NULL) == 0); 80511.138Smgorny } 80521.138Smgorny 80531.138Smgorny FORKEE_ASSERT(pthread_barrier_destroy( 80541.138Smgorny &thread_concurrent_signals_barrier) == 0); 80551.138Smgorny 80561.138Smgorny DPRINTF("Before exiting of the child process\n"); 80571.138Smgorny _exit(exitval); 80581.138Smgorny } 80591.138Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 80601.138Smgorny 80611.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 80621.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 80631.138Smgorny 80641.138Smgorny validate_status_stopped(status, sigval); 80651.138Smgorny 80661.138Smgorny DPRINTF("Before resuming the child process where it left off\n"); 80671.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 80681.138Smgorny 80691.138Smgorny DPRINTF("Before entering signal collection loop\n"); 80701.138Smgorny while (1) { 80711.138Smgorny ptrace_siginfo_t info; 80721.138Smgorny int expected_sig; 80731.138Smgorny 80741.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 80751.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 80761.138Smgorny child); 80771.138Smgorny if (WIFEXITED(status)) 80781.138Smgorny break; 80791.138Smgorny /* Note: we use validate_status_stopped() to get nice error 80801.138Smgorny * message. Signal is irrelevant since it won't be reached. 80811.138Smgorny */ 80821.138Smgorny else if (!WIFSTOPPED(status)) 80831.138Smgorny validate_status_stopped(status, 0); 80841.138Smgorny 80851.138Smgorny DPRINTF("Before calling PT_GET_SIGINFO\n"); 80861.138Smgorny SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 80871.138Smgorny sizeof(info)) != -1); 80881.138Smgorny 80891.138Smgorny DPRINTF("Received signal %d from LWP %d (wait: %d)\n", 80901.138Smgorny info.psi_siginfo.si_signo, info.psi_lwpid, 80911.138Smgorny WSTOPSIG(status)); 80921.138Smgorny 80931.138Smgorny expected_sig = thread_concurrent_signals_list[info.psi_lwpid % 80941.138Smgorny __arraycount(thread_concurrent_signals_list)]; 80951.138Smgorny ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, expected_sig, 80961.138Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 80971.138Smgorny expected_sig, info.psi_siginfo.si_signo); 80981.138Smgorny ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig, 80991.138Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 81001.138Smgorny expected_sig, WSTOPSIG(status)); 81011.138Smgorny 81021.141Skamil *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1; 81031.138Smgorny 81041.138Smgorny DPRINTF("Before resuming the child process\n"); 81051.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 81061.138Smgorny } 81071.138Smgorny 81081.138Smgorny for (i = 0; i < __arraycount(signal_counts); i++) 81091.141Skamil ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1, 81101.141Skamil "signal_counts[%d].lec_count=%d; lec_lwp=%d", 81111.141Skamil i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 81121.138Smgorny 81131.138Smgorny validate_status_exited(status, exitval); 81141.138Smgorny} 81151.138Smgorny 81161.138Smgorny#endif /*defined(TWAIT_HAVE_STATUS)*/ 81171.138Smgorny 81181.138Smgorny/// ---------------------------------------------------------------------------- 81191.138Smgorny 81201.1Skamil#include "t_ptrace_amd64_wait.h" 81211.1Skamil#include "t_ptrace_i386_wait.h" 81221.1Skamil#include "t_ptrace_x86_wait.h" 81231.1Skamil 81241.1SkamilATF_TP_ADD_TCS(tp) 81251.1Skamil{ 81261.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 81271.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 81281.33Skamil 81291.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 81301.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 81311.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 81321.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 81331.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 81341.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 81351.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 81361.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 81371.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 81381.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 81391.33Skamil 81401.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 81411.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 81421.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 81431.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 81441.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 81451.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 81461.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 81471.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 81481.87Skamil 81491.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 81501.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 81511.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 81521.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 81531.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 81541.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 81551.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 81561.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 81571.86Skamil 81581.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 81591.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 81601.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 81611.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 81621.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 81631.59Skamil 81641.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 81651.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 81661.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 81671.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 81681.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 81691.88Skamil 81701.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 81711.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 81721.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 81731.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 81741.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 81751.88Skamil 81761.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 81771.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 81781.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 81791.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 81801.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 81811.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 81821.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 81831.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 81841.50Skamil 81851.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 81861.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 81871.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 81881.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 81891.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 81901.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 81911.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 81921.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 81931.50Skamil 81941.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 81951.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 81961.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 81971.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 81981.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 81991.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 82001.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 82011.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 82021.50Skamil 82031.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 82041.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 82051.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 82061.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 82071.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 82081.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 82091.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 82101.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 82111.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 82121.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 82131.1Skamil 82141.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 82151.37Skamil 82161.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 82171.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 82181.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 82191.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 82201.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 82211.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 82221.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 82231.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 82241.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 82251.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 82261.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 82271.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 82281.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 82291.40Skamil 82301.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 82311.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 82321.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 82331.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 82341.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 82351.41Skamil 82361.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 82371.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 82381.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 82391.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 82401.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 82411.92Skamil 82421.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 82431.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 82441.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 82451.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 82461.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 82471.92Skamil 82481.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 82491.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 82501.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 82511.43Skamil 82521.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 82531.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 82541.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 82551.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 82561.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 82571.59Skamil 82581.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82591.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 82601.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82611.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 82621.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82631.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 82641.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82651.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 82661.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82671.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 82681.94Skamil 82691.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82701.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 82711.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82721.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 82731.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82741.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 82751.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82761.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 82771.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82781.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 82791.94Skamil 82801.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 82811.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 82821.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 82831.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 82841.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 82851.51Skamil 82861.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 82871.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 82881.51Skamil 82891.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 82901.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 82911.51Skamil 82921.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82931.51Skamil tracee_sees_its_original_parent_getppid); 82941.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82951.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 82961.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 82971.51Skamil tracee_sees_its_original_parent_procfs_status); 82981.1Skamil 82991.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 83001.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 83011.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 83021.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 83031.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 83041.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 83051.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 83061.1Skamil 83071.31Skamil ATF_TP_ADD_TC(tp, fork1); 83081.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 83091.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 83101.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 83111.31Skamil ATF_TP_ADD_TC(tp, fork5); 83121.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 83131.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 83141.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 83151.125Skamil ATF_TP_ADD_TC(tp, fork9); 83161.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 83171.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 83181.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 83191.125Skamil ATF_TP_ADD_TC(tp, fork13); 83201.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 83211.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 83221.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 83231.31Skamil 83241.31Skamil ATF_TP_ADD_TC(tp, vfork1); 83251.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 83261.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 83271.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 83281.31Skamil ATF_TP_ADD_TC(tp, vfork5); 83291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 83301.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 83311.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 83321.125Skamil ATF_TP_ADD_TC(tp, vfork9); 83331.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 83341.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 83351.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 83361.125Skamil ATF_TP_ADD_TC(tp, vfork13); 83371.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 83381.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 83391.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 83401.1Skamil 83411.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 83421.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 83431.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 83441.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 83451.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 83461.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 83471.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 83481.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 83491.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 83501.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 83511.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 83521.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 83531.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 83541.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 83551.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 83561.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 83571.124Skamil 83581.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 83591.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 83601.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 83611.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 83621.126Skamil 83631.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 83641.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 83651.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 83661.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 83671.116Skamil 83681.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 83691.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 83701.108Skamil 83711.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 83721.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 83731.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 83741.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 83751.54Skamil 83761.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 83771.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 83781.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 83791.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 83801.54Skamil 83811.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 83821.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 83831.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 83841.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 83851.54Skamil 83861.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 83871.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 83881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 83891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 83901.54Skamil 83911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 83921.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 83931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 83941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 83951.54Skamil 83961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 83971.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 83981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 83991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 84001.54Skamil 84011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 84021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 84031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 84041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 84051.54Skamil 84061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 84071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 84081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 84091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 84101.54Skamil 84111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 84121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 84131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 84141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 84151.54Skamil 84161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 84171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 84181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 84191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 84201.1Skamil 84211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 84221.1Skamil 84231.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 84241.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 84251.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 84261.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 84271.101Skamil 84281.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 84291.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 84301.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 84311.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 84321.101Skamil 84331.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 84341.101Skamil 84351.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 84361.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 84371.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 84381.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 84391.115Skamil 84401.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 84411.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 84421.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 84431.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 84441.115Skamil 84451.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 84461.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 84471.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 84481.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 84491.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 84501.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 84511.1Skamil 84521.147Skamil ATF_TP_ADD_TC(tp, access_regs_set_unaligned_pc_0x1); 84531.147Skamil ATF_TP_ADD_TC(tp, access_regs_set_unaligned_pc_0x3); 84541.147Skamil ATF_TP_ADD_TC(tp, access_regs_set_unaligned_pc_0x7); 84551.147Skamil 84561.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 84571.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 84581.1Skamil 84591.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 84601.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 84611.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 84621.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 84631.1Skamil 84641.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 84651.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 84661.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 84671.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 84681.2Skamil 84691.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 84701.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 84711.95Skamil 84721.1Skamil ATF_TP_ADD_TC(tp, kill1); 84731.1Skamil ATF_TP_ADD_TC(tp, kill2); 84741.75Skamil ATF_TP_ADD_TC(tp, kill3); 84751.1Skamil 84761.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 84771.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 84781.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 84791.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 84801.77Skamil 84811.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus); 84821.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus); 84831.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus); 84841.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus); 84851.143Skamil 84861.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_sigmask); 84871.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_sigmask); 84881.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_sigmask); 84891.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_sigmask); 84901.143Skamil 84911.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_name); 84921.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_name); 84931.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_name); 84941.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_name); 84951.143Skamil 84961.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_private); 84971.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_private); 84981.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_private); 84991.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_private); 85001.143Skamil 85011.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0); 85021.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1); 85031.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2); 85041.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3); 85051.143Skamil 85061.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_sigmask); 85071.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_sigmask); 85081.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_sigmask); 85091.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_sigmask); 85101.143Skamil 85111.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_name); 85121.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_name); 85131.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_name); 85141.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_name); 85151.143Skamil 85161.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_private); 85171.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_private); 85181.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_private); 85191.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_private); 85201.143Skamil 85211.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 85221.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 85231.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 85241.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 85251.1Skamil 85261.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 85271.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 85281.79Skamil 85291.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 85301.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 85311.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 85321.1Skamil 85331.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 85341.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 85351.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 85361.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 85371.1Skamil 85381.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 85391.84Skamil 85401.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 85411.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 85421.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 85431.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 85441.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 85451.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 85461.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 85471.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 85481.99Skamil 85491.1Skamil ATF_TP_ADD_TC(tp, signal9); 85501.1Skamil ATF_TP_ADD_TC(tp, signal10); 85511.1Skamil 85521.1Skamil ATF_TP_ADD_TC(tp, suspend2); 85531.1Skamil 85541.1Skamil ATF_TP_ADD_TC(tp, resume1); 85551.1Skamil 85561.1Skamil ATF_TP_ADD_TC(tp, syscall1); 85571.1Skamil 85581.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 85591.1Skamil 85601.106Skamil ATF_TP_ADD_TC(tp, clone1); 85611.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 85621.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 85631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 85641.106Skamil ATF_TP_ADD_TC(tp, clone5); 85651.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 85661.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 85671.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 85681.106Skamil 85691.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 85701.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 85711.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 85721.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 85731.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 85741.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 85751.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 85761.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 85771.106Skamil 85781.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 85791.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 85801.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 85811.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 85821.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 85831.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 85841.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 85851.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 85861.106Skamil 85871.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 85881.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 85891.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 85901.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 85911.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 85921.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 85931.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 85941.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 85951.106Skamil 85961.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 85971.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 85981.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 85991.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 86001.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 86011.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 86021.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 86031.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 86041.106Skamil 86051.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 86061.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 86071.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 86081.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 86091.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 86101.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 86111.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 86121.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 86131.106Skamil 86141.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 86151.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 86161.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 86171.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 86181.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 86191.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 86201.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 86211.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 86221.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 86231.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 86241.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 86251.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 86261.103Skamil 86271.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 86281.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 86291.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 86301.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 86311.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 86321.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 86331.107Skamil 86341.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 86351.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 86361.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 86371.122Skamil 86381.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 86391.130Smgorny 86401.138Smgorny#if defined(TWAIT_HAVE_STATUS) 86411.138Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals); 86421.138Smgorny#endif 86431.138Smgorny 86441.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 86451.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 86461.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 86471.1Skamil 86481.1Skamil return atf_no_error(); 86491.1Skamil} 8650