t_ptrace_wait.c revision 1.141
11.141Skamil/* $NetBSD: t_ptrace_wait.c,v 1.141 2019/11/12 18:18:04 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.141Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.141 2019/11/12 18:18:04 kamil Exp $"); 311.1Skamil 321.1Skamil#include <sys/param.h> 331.1Skamil#include <sys/types.h> 341.130Smgorny#include <sys/exec_elf.h> 351.39Skamil#include <sys/mman.h> 361.1Skamil#include <sys/ptrace.h> 371.1Skamil#include <sys/resource.h> 381.1Skamil#include <sys/stat.h> 391.1Skamil#include <sys/syscall.h> 401.1Skamil#include <sys/sysctl.h> 411.129Smgorny#include <sys/uio.h> 421.1Skamil#include <sys/wait.h> 431.1Skamil#include <machine/reg.h> 441.132Skamil#include <assert.h> 451.1Skamil#include <elf.h> 461.1Skamil#include <err.h> 471.1Skamil#include <errno.h> 481.130Smgorny#include <fcntl.h> 491.1Skamil#include <lwp.h> 501.77Skamil#include <pthread.h> 511.1Skamil#include <sched.h> 521.1Skamil#include <signal.h> 531.124Skamil#include <spawn.h> 541.1Skamil#include <stdint.h> 551.1Skamil#include <stdio.h> 561.1Skamil#include <stdlib.h> 571.1Skamil#include <strings.h> 581.26Skamil#include <time.h> 591.1Skamil#include <unistd.h> 601.1Skamil 611.114Skamil#include <fenv.h> 621.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 631.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 641.114Skamil#endif 651.114Skamil 661.121Smgorny#if defined(__i386__) || defined(__x86_64__) 671.121Smgorny#include <cpuid.h> 681.121Smgorny#include <x86/cpu_extended_state.h> 691.129Smgorny#include <x86/specialreg.h> 701.121Smgorny#endif 711.121Smgorny 721.130Smgorny#include <libelf.h> 731.130Smgorny#include <gelf.h> 741.130Smgorny 751.1Skamil#include <atf-c.h> 761.1Skamil 771.132Skamil/* Assumptions in the kernel code that must be kept. */ 781.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_report_event) == 791.132Skamil sizeof(((siginfo_t *)0)->si_pe_report_event), 801.132Skamil "pe_report_event and si_pe_report_event must be of the same size"); 811.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 821.132Skamil sizeof(((siginfo_t *)0)->si_pe_other_pid), 831.132Skamil "pe_other_pid and si_pe_other_pid must be of the same size"); 841.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_lwp) == 851.132Skamil sizeof(((siginfo_t *)0)->si_pe_lwp), 861.132Skamil "pe_lwp and si_pe_lwp must be of the same size"); 871.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 881.132Skamil sizeof(((struct ptrace_state *)0)->pe_lwp), 891.132Skamil "pe_other_pid and pe_lwp must be of the same size"); 901.132Skamil 911.1Skamil#include "h_macros.h" 921.1Skamil 931.1Skamil#include "t_ptrace_wait.h" 941.1Skamil#include "msg.h" 951.1Skamil 961.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 971.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 981.61Skre sizeof(msg)) == 0) 991.1Skamil 1001.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 1011.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 1021.61Skre sizeof(msg)) == 0) 1031.1Skamil 1041.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 1051.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 1061.61Skre sizeof(msg)) == 0) 1071.1Skamil 1081.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 1091.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 1101.61Skre sizeof(msg)) == 0) 1111.13Schristos 1121.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 1131.13Schristos strerror(errno)) 1141.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 1151.18Schristos "%d(%s) != %d", res, strerror(res), exp) 1161.13Schristos 1171.13Schristosstatic int debug = 0; 1181.13Schristos 1191.13Schristos#define DPRINTF(a, ...) do \ 1201.123Skamil if (debug) \ 1211.123Skamil printf("%s() %s:%d " a, __func__, __FILE__, __LINE__, ##__VA_ARGS__); \ 1221.13Schristos while (/*CONSTCOND*/0) 1231.1Skamil 1241.34Skamil/// ---------------------------------------------------------------------------- 1251.34Skamil 1261.33Skamilstatic void 1271.33Skamiltraceme_raise(int sigval) 1281.1Skamil{ 1291.1Skamil const int exitval = 5; 1301.1Skamil pid_t child, wpid; 1311.1Skamil#if defined(TWAIT_HAVE_STATUS) 1321.1Skamil int status; 1331.1Skamil#endif 1341.1Skamil 1351.133Skamil ptrace_state_t state, zero_state; 1361.133Skamil const int slen = sizeof(state); 1371.45Skamil struct ptrace_siginfo info; 1381.133Skamil memset(&zero_state, 0, sizeof(zero_state)); 1391.45Skamil memset(&info, 0, sizeof(info)); 1401.45Skamil 1411.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1421.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1431.1Skamil if (child == 0) { 1441.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1451.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1461.1Skamil 1471.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1481.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1491.1Skamil 1501.36Skamil switch (sigval) { 1511.36Skamil case SIGKILL: 1521.36Skamil /* NOTREACHED */ 1531.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1541.70Smrg __unreachable(); 1551.36Skamil default: 1561.36Skamil DPRINTF("Before exiting of the child process\n"); 1571.36Skamil _exit(exitval); 1581.36Skamil } 1591.1Skamil } 1601.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1611.1Skamil 1621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1641.1Skamil 1651.36Skamil switch (sigval) { 1661.36Skamil case SIGKILL: 1671.36Skamil validate_status_signaled(status, sigval, 0); 1681.133Skamil SYSCALL_REQUIRE( 1691.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) == -1); 1701.133Skamil 1711.36Skamil break; 1721.36Skamil default: 1731.36Skamil validate_status_stopped(status, sigval); 1741.1Skamil 1751.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1761.61Skre "child\n"); 1771.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1781.61Skre sizeof(info)) != -1); 1791.45Skamil 1801.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1811.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1821.61Skre "si_errno=%#x\n", 1831.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1841.61Skre info.psi_siginfo.si_errno); 1851.45Skamil 1861.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1871.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1881.45Skamil 1891.133Skamil DPRINTF("Assert that PT_GET_PROCESS_STATE returns non-error"); 1901.133Skamil SYSCALL_REQUIRE( 1911.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 1921.133Skamil ATF_REQUIRE(memcmp(&state, &zero_state, slen) == 0); 1931.133Skamil 1941.36Skamil DPRINTF("Before resuming the child process where it left off " 1951.36Skamil "and without signal to be sent\n"); 1961.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1971.1Skamil 1981.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1991.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 2001.61Skre child); 2011.36Skamil break; 2021.36Skamil } 2031.1Skamil 2041.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2051.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2061.1Skamil} 2071.1Skamil 2081.61Skre#define TRACEME_RAISE(test, sig) \ 2091.61SkreATF_TC(test); \ 2101.61SkreATF_TC_HEAD(test, tc) \ 2111.61Skre{ \ 2121.61Skre atf_tc_set_md_var(tc, "descr", \ 2131.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 2141.61Skre} \ 2151.61Skre \ 2161.61SkreATF_TC_BODY(test, tc) \ 2171.61Skre{ \ 2181.61Skre \ 2191.61Skre traceme_raise(sig); \ 2201.33Skamil} 2211.33Skamil 2221.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2231.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2241.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2251.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2261.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2271.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2281.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2291.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2301.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2311.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2321.33Skamil 2331.34Skamil/// ---------------------------------------------------------------------------- 2341.1Skamil 2351.1Skamilstatic void 2361.87Skamiltraceme_raisesignal_ignored(int sigignored) 2371.87Skamil{ 2381.87Skamil const int exitval = 5; 2391.87Skamil const int sigval = SIGSTOP; 2401.87Skamil pid_t child, wpid; 2411.87Skamil struct sigaction sa; 2421.87Skamil#if defined(TWAIT_HAVE_STATUS) 2431.87Skamil int status; 2441.87Skamil#endif 2451.87Skamil struct ptrace_siginfo info; 2461.87Skamil 2471.87Skamil memset(&info, 0, sizeof(info)); 2481.87Skamil 2491.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2501.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2511.87Skamil if (child == 0) { 2521.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2531.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2541.87Skamil 2551.87Skamil memset(&sa, 0, sizeof(sa)); 2561.87Skamil sa.sa_handler = SIG_IGN; 2571.87Skamil sigemptyset(&sa.sa_mask); 2581.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2591.87Skamil 2601.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2611.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2621.87Skamil 2631.87Skamil DPRINTF("Before raising %s from child\n", 2641.87Skamil strsignal(sigignored)); 2651.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2661.87Skamil 2671.87Skamil DPRINTF("Before exiting of the child process\n"); 2681.87Skamil _exit(exitval); 2691.87Skamil } 2701.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2711.87Skamil 2721.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2731.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2741.87Skamil 2751.87Skamil validate_status_stopped(status, sigval); 2761.87Skamil 2771.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2781.87Skamil SYSCALL_REQUIRE( 2791.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2801.87Skamil 2811.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2821.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2831.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2841.87Skamil info.psi_siginfo.si_errno); 2851.87Skamil 2861.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2871.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2881.87Skamil 2891.87Skamil DPRINTF("Before resuming the child process where it left off and " 2901.87Skamil "without signal to be sent\n"); 2911.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2921.87Skamil 2931.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2941.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2951.87Skamil 2961.87Skamil validate_status_stopped(status, sigignored); 2971.87Skamil 2981.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2991.87Skamil SYSCALL_REQUIRE( 3001.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3011.87Skamil 3021.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3031.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3041.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3051.87Skamil info.psi_siginfo.si_errno); 3061.87Skamil 3071.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 3081.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3091.87Skamil 3101.87Skamil DPRINTF("Before resuming the child process where it left off and " 3111.87Skamil "without signal to be sent\n"); 3121.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3131.87Skamil 3141.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3151.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3161.87Skamil 3171.87Skamil validate_status_exited(status, exitval); 3181.87Skamil 3191.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3201.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3211.87Skamil} 3221.87Skamil 3231.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3241.87SkamilATF_TC(test); \ 3251.87SkamilATF_TC_HEAD(test, tc) \ 3261.87Skamil{ \ 3271.87Skamil atf_tc_set_md_var(tc, "descr", \ 3281.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3291.87Skamil "does not stop tracer from catching this raised signal"); \ 3301.87Skamil} \ 3311.87Skamil \ 3321.87SkamilATF_TC_BODY(test, tc) \ 3331.87Skamil{ \ 3341.87Skamil \ 3351.87Skamil traceme_raisesignal_ignored(sig); \ 3361.87Skamil} 3371.87Skamil 3381.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3391.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3401.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3411.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3421.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3431.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3441.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3451.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3461.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3471.87Skamil 3481.87Skamil/// ---------------------------------------------------------------------------- 3491.87Skamil 3501.87Skamilstatic void 3511.86Skamiltraceme_raisesignal_masked(int sigmasked) 3521.86Skamil{ 3531.86Skamil const int exitval = 5; 3541.86Skamil const int sigval = SIGSTOP; 3551.86Skamil pid_t child, wpid; 3561.86Skamil#if defined(TWAIT_HAVE_STATUS) 3571.86Skamil int status; 3581.86Skamil#endif 3591.86Skamil sigset_t intmask; 3601.86Skamil struct ptrace_siginfo info; 3611.86Skamil 3621.86Skamil memset(&info, 0, sizeof(info)); 3631.86Skamil 3641.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3651.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3661.86Skamil if (child == 0) { 3671.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3681.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3691.86Skamil 3701.86Skamil sigemptyset(&intmask); 3711.86Skamil sigaddset(&intmask, sigmasked); 3721.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3731.86Skamil 3741.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3751.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3761.86Skamil 3771.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3781.86Skamil strsignal(sigmasked)); 3791.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3801.86Skamil 3811.86Skamil DPRINTF("Before exiting of the child process\n"); 3821.86Skamil _exit(exitval); 3831.86Skamil } 3841.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3851.86Skamil 3861.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3871.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3881.86Skamil 3891.86Skamil validate_status_stopped(status, sigval); 3901.86Skamil 3911.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3921.86Skamil SYSCALL_REQUIRE( 3931.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3941.86Skamil 3951.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3961.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3971.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3981.86Skamil info.psi_siginfo.si_errno); 3991.86Skamil 4001.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 4011.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 4021.86Skamil 4031.86Skamil DPRINTF("Before resuming the child process where it left off and " 4041.86Skamil "without signal to be sent\n"); 4051.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 4061.86Skamil 4071.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4081.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4091.86Skamil 4101.86Skamil validate_status_exited(status, exitval); 4111.86Skamil 4121.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4131.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 4141.86Skamil} 4151.86Skamil 4161.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 4171.86SkamilATF_TC(test); \ 4181.86SkamilATF_TC_HEAD(test, tc) \ 4191.86Skamil{ \ 4201.86Skamil atf_tc_set_md_var(tc, "descr", \ 4211.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4221.86Skamil "stops tracer from catching this raised signal"); \ 4231.86Skamil} \ 4241.86Skamil \ 4251.86SkamilATF_TC_BODY(test, tc) \ 4261.86Skamil{ \ 4271.86Skamil \ 4281.86Skamil traceme_raisesignal_masked(sig); \ 4291.86Skamil} 4301.86Skamil 4311.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4321.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4331.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4341.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4351.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4361.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4371.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4381.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4391.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4401.86Skamil 4411.86Skamil/// ---------------------------------------------------------------------------- 4421.86Skamil 4431.86Skamilstatic void 4441.59Skamiltraceme_crash(int sig) 4451.59Skamil{ 4461.59Skamil pid_t child, wpid; 4471.59Skamil#if defined(TWAIT_HAVE_STATUS) 4481.59Skamil int status; 4491.59Skamil#endif 4501.59Skamil struct ptrace_siginfo info; 4511.61Skre 4521.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4531.71Skamil if (sig == SIGILL) 4541.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4551.71Skamil#endif 4561.71Skamil 4571.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4581.114Skamil atf_tc_skip("FP exceptions are not supported"); 4591.114Skamil 4601.59Skamil memset(&info, 0, sizeof(info)); 4611.59Skamil 4621.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4631.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4641.59Skamil if (child == 0) { 4651.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4661.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4671.59Skamil 4681.59Skamil DPRINTF("Before executing a trap\n"); 4691.59Skamil switch (sig) { 4701.59Skamil case SIGTRAP: 4711.59Skamil trigger_trap(); 4721.59Skamil break; 4731.59Skamil case SIGSEGV: 4741.59Skamil trigger_segv(); 4751.59Skamil break; 4761.59Skamil case SIGILL: 4771.59Skamil trigger_ill(); 4781.59Skamil break; 4791.59Skamil case SIGFPE: 4801.59Skamil trigger_fpe(); 4811.59Skamil break; 4821.59Skamil case SIGBUS: 4831.59Skamil trigger_bus(); 4841.59Skamil break; 4851.59Skamil default: 4861.59Skamil /* NOTREACHED */ 4871.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4881.59Skamil } 4891.59Skamil 4901.59Skamil /* NOTREACHED */ 4911.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4921.59Skamil } 4931.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4941.59Skamil 4951.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4961.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4971.59Skamil 4981.59Skamil validate_status_stopped(status, sig); 4991.59Skamil 5001.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 5011.61Skre SYSCALL_REQUIRE( 5021.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 5031.59Skamil 5041.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 5051.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 5061.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 5071.61Skre info.psi_siginfo.si_errno); 5081.59Skamil 5091.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 5101.59Skamil switch (sig) { 5111.59Skamil case SIGTRAP: 5121.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 5131.59Skamil break; 5141.59Skamil case SIGSEGV: 5151.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 5161.59Skamil break; 5171.71Skamil case SIGILL: 5181.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 5191.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5201.71Skamil break; 5211.59Skamil case SIGFPE: 5221.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5231.59Skamil break; 5241.59Skamil case SIGBUS: 5251.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5261.59Skamil break; 5271.59Skamil } 5281.59Skamil 5291.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5301.59Skamil 5311.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5321.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5331.59Skamil 5341.59Skamil validate_status_signaled(status, SIGKILL, 0); 5351.59Skamil 5361.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5371.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5381.59Skamil} 5391.59Skamil 5401.61Skre#define TRACEME_CRASH(test, sig) \ 5411.61SkreATF_TC(test); \ 5421.61SkreATF_TC_HEAD(test, tc) \ 5431.61Skre{ \ 5441.61Skre atf_tc_set_md_var(tc, "descr", \ 5451.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5461.61Skre} \ 5471.61Skre \ 5481.61SkreATF_TC_BODY(test, tc) \ 5491.61Skre{ \ 5501.61Skre \ 5511.61Skre traceme_crash(sig); \ 5521.59Skamil} 5531.59Skamil 5541.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5551.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5561.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5571.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5581.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5591.59Skamil 5601.59Skamil/// ---------------------------------------------------------------------------- 5611.59Skamil 5621.59Skamilstatic void 5631.88Skamiltraceme_signalmasked_crash(int sig) 5641.88Skamil{ 5651.89Skamil const int sigval = SIGSTOP; 5661.88Skamil pid_t child, wpid; 5671.88Skamil#if defined(TWAIT_HAVE_STATUS) 5681.88Skamil int status; 5691.88Skamil#endif 5701.88Skamil struct ptrace_siginfo info; 5711.88Skamil sigset_t intmask; 5721.89Skamil struct kinfo_proc2 kp; 5731.89Skamil size_t len = sizeof(kp); 5741.89Skamil 5751.89Skamil int name[6]; 5761.89Skamil const size_t namelen = __arraycount(name); 5771.89Skamil ki_sigset_t kp_sigmask; 5781.88Skamil 5791.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5801.88Skamil if (sig == SIGILL) 5811.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5821.88Skamil#endif 5831.88Skamil 5841.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5851.114Skamil atf_tc_skip("FP exceptions are not supported"); 5861.114Skamil 5871.88Skamil memset(&info, 0, sizeof(info)); 5881.88Skamil 5891.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5901.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5911.88Skamil if (child == 0) { 5921.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5931.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5941.88Skamil 5951.88Skamil sigemptyset(&intmask); 5961.88Skamil sigaddset(&intmask, sig); 5971.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5981.88Skamil 5991.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 6001.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 6011.89Skamil 6021.88Skamil DPRINTF("Before executing a trap\n"); 6031.88Skamil switch (sig) { 6041.88Skamil case SIGTRAP: 6051.88Skamil trigger_trap(); 6061.88Skamil break; 6071.88Skamil case SIGSEGV: 6081.88Skamil trigger_segv(); 6091.88Skamil break; 6101.88Skamil case SIGILL: 6111.88Skamil trigger_ill(); 6121.88Skamil break; 6131.88Skamil case SIGFPE: 6141.88Skamil trigger_fpe(); 6151.88Skamil break; 6161.88Skamil case SIGBUS: 6171.88Skamil trigger_bus(); 6181.88Skamil break; 6191.88Skamil default: 6201.88Skamil /* NOTREACHED */ 6211.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6221.88Skamil } 6231.88Skamil 6241.88Skamil /* NOTREACHED */ 6251.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6261.88Skamil } 6271.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6281.88Skamil 6291.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6301.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6311.88Skamil 6321.89Skamil validate_status_stopped(status, sigval); 6331.89Skamil 6341.89Skamil name[0] = CTL_KERN, 6351.89Skamil name[1] = KERN_PROC2, 6361.89Skamil name[2] = KERN_PROC_PID; 6371.89Skamil name[3] = child; 6381.89Skamil name[4] = sizeof(kp); 6391.89Skamil name[5] = 1; 6401.89Skamil 6411.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6421.89Skamil 6431.89Skamil kp_sigmask = kp.p_sigmask; 6441.89Skamil 6451.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6461.89Skamil SYSCALL_REQUIRE( 6471.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6481.89Skamil 6491.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6501.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6511.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6521.89Skamil info.psi_siginfo.si_errno); 6531.89Skamil 6541.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6551.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6561.89Skamil 6571.89Skamil DPRINTF("Before resuming the child process where it left off and " 6581.89Skamil "without signal to be sent\n"); 6591.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6601.89Skamil 6611.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6621.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6631.89Skamil 6641.88Skamil validate_status_stopped(status, sig); 6651.88Skamil 6661.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6671.88Skamil SYSCALL_REQUIRE( 6681.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6691.88Skamil 6701.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6711.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6721.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6731.88Skamil info.psi_siginfo.si_errno); 6741.88Skamil 6751.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6761.89Skamil 6771.89Skamil DPRINTF("kp_sigmask=" 6781.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6791.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6801.89Skamil kp_sigmask.__bits[3]); 6811.89Skamil 6821.89Skamil DPRINTF("kp.p_sigmask=" 6831.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6841.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6851.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6861.89Skamil 6871.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6881.89Skamil 6891.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6901.88Skamil switch (sig) { 6911.88Skamil case SIGTRAP: 6921.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6931.88Skamil break; 6941.88Skamil case SIGSEGV: 6951.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6961.88Skamil break; 6971.88Skamil case SIGILL: 6981.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6991.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 7001.88Skamil break; 7011.88Skamil case SIGFPE: 7021.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 7031.88Skamil break; 7041.88Skamil case SIGBUS: 7051.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 7061.88Skamil break; 7071.88Skamil } 7081.88Skamil 7091.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 7101.88Skamil 7111.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7121.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7131.88Skamil 7141.88Skamil validate_status_signaled(status, SIGKILL, 0); 7151.88Skamil 7161.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7171.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 7181.88Skamil} 7191.88Skamil 7201.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7211.88SkamilATF_TC(test); \ 7221.88SkamilATF_TC_HEAD(test, tc) \ 7231.88Skamil{ \ 7241.88Skamil atf_tc_set_md_var(tc, "descr", \ 7251.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7261.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7271.88Skamil} \ 7281.88Skamil \ 7291.88SkamilATF_TC_BODY(test, tc) \ 7301.88Skamil{ \ 7311.88Skamil \ 7321.88Skamil traceme_signalmasked_crash(sig); \ 7331.88Skamil} 7341.88Skamil 7351.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7361.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7371.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7381.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7391.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7401.88Skamil 7411.88Skamil/// ---------------------------------------------------------------------------- 7421.88Skamil 7431.88Skamilstatic void 7441.88Skamiltraceme_signalignored_crash(int sig) 7451.88Skamil{ 7461.90Skamil const int sigval = SIGSTOP; 7471.88Skamil pid_t child, wpid; 7481.88Skamil#if defined(TWAIT_HAVE_STATUS) 7491.88Skamil int status; 7501.88Skamil#endif 7511.88Skamil struct sigaction sa; 7521.88Skamil struct ptrace_siginfo info; 7531.90Skamil struct kinfo_proc2 kp; 7541.90Skamil size_t len = sizeof(kp); 7551.90Skamil 7561.90Skamil int name[6]; 7571.90Skamil const size_t namelen = __arraycount(name); 7581.90Skamil ki_sigset_t kp_sigignore; 7591.88Skamil 7601.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7611.88Skamil if (sig == SIGILL) 7621.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7631.88Skamil#endif 7641.88Skamil 7651.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7661.114Skamil atf_tc_skip("FP exceptions are not supported"); 7671.114Skamil 7681.88Skamil memset(&info, 0, sizeof(info)); 7691.88Skamil 7701.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7711.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7721.88Skamil if (child == 0) { 7731.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7741.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7751.88Skamil 7761.88Skamil memset(&sa, 0, sizeof(sa)); 7771.88Skamil sa.sa_handler = SIG_IGN; 7781.88Skamil sigemptyset(&sa.sa_mask); 7791.88Skamil 7801.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7811.88Skamil 7821.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7831.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7841.90Skamil 7851.88Skamil DPRINTF("Before executing a trap\n"); 7861.88Skamil switch (sig) { 7871.88Skamil case SIGTRAP: 7881.88Skamil trigger_trap(); 7891.88Skamil break; 7901.88Skamil case SIGSEGV: 7911.88Skamil trigger_segv(); 7921.88Skamil break; 7931.88Skamil case SIGILL: 7941.88Skamil trigger_ill(); 7951.88Skamil break; 7961.88Skamil case SIGFPE: 7971.88Skamil trigger_fpe(); 7981.88Skamil break; 7991.88Skamil case SIGBUS: 8001.88Skamil trigger_bus(); 8011.88Skamil break; 8021.88Skamil default: 8031.88Skamil /* NOTREACHED */ 8041.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8051.88Skamil } 8061.88Skamil 8071.88Skamil /* NOTREACHED */ 8081.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8091.88Skamil } 8101.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 8111.88Skamil 8121.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8131.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8141.88Skamil 8151.90Skamil validate_status_stopped(status, sigval); 8161.90Skamil 8171.90Skamil name[0] = CTL_KERN, 8181.90Skamil name[1] = KERN_PROC2, 8191.90Skamil name[2] = KERN_PROC_PID; 8201.90Skamil name[3] = child; 8211.90Skamil name[4] = sizeof(kp); 8221.90Skamil name[5] = 1; 8231.90Skamil 8241.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8251.90Skamil 8261.90Skamil kp_sigignore = kp.p_sigignore; 8271.90Skamil 8281.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8291.90Skamil SYSCALL_REQUIRE( 8301.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8311.90Skamil 8321.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8331.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8341.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8351.90Skamil info.psi_siginfo.si_errno); 8361.90Skamil 8371.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8381.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8391.90Skamil 8401.90Skamil DPRINTF("Before resuming the child process where it left off and " 8411.90Skamil "without signal to be sent\n"); 8421.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8431.90Skamil 8441.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8451.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8461.90Skamil 8471.88Skamil validate_status_stopped(status, sig); 8481.88Skamil 8491.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8501.88Skamil SYSCALL_REQUIRE( 8511.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8521.88Skamil 8531.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8541.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8551.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8561.88Skamil info.psi_siginfo.si_errno); 8571.88Skamil 8581.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8591.90Skamil 8601.90Skamil DPRINTF("kp_sigignore=" 8611.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8621.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8631.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8641.90Skamil 8651.90Skamil DPRINTF("kp.p_sigignore=" 8661.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8671.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8681.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8691.90Skamil 8701.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8711.90Skamil 8721.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8731.88Skamil switch (sig) { 8741.88Skamil case SIGTRAP: 8751.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8761.88Skamil break; 8771.88Skamil case SIGSEGV: 8781.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8791.88Skamil break; 8801.88Skamil case SIGILL: 8811.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8821.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8831.88Skamil break; 8841.88Skamil case SIGFPE: 8851.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8861.88Skamil break; 8871.88Skamil case SIGBUS: 8881.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8891.88Skamil break; 8901.88Skamil } 8911.88Skamil 8921.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8931.88Skamil 8941.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8951.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8961.88Skamil 8971.88Skamil validate_status_signaled(status, SIGKILL, 0); 8981.88Skamil 8991.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9001.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9011.88Skamil} 9021.88Skamil 9031.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 9041.88SkamilATF_TC(test); \ 9051.88SkamilATF_TC_HEAD(test, tc) \ 9061.88Skamil{ \ 9071.88Skamil atf_tc_set_md_var(tc, "descr", \ 9081.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 9091.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 9101.88Skamil} \ 9111.88Skamil \ 9121.88SkamilATF_TC_BODY(test, tc) \ 9131.88Skamil{ \ 9141.88Skamil \ 9151.88Skamil traceme_signalignored_crash(sig); \ 9161.88Skamil} 9171.88Skamil 9181.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 9191.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9201.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9211.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9221.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9231.88Skamil 9241.88Skamil/// ---------------------------------------------------------------------------- 9251.88Skamil 9261.88Skamilstatic void 9271.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9281.1Skamil{ 9291.1Skamil const int exitval = 5; 9301.34Skamil const int sigval = SIGSTOP; 9311.1Skamil pid_t child, wpid; 9321.1Skamil struct sigaction sa; 9331.1Skamil#if defined(TWAIT_HAVE_STATUS) 9341.1Skamil int status; 9351.1Skamil#endif 9361.61Skre struct ptrace_siginfo info; 9371.1Skamil 9381.45Skamil memset(&info, 0, sizeof(info)); 9391.45Skamil 9401.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9411.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9421.1Skamil if (child == 0) { 9431.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9441.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9451.1Skamil 9461.34Skamil sa.sa_handler = sah; 9471.1Skamil sa.sa_flags = SA_SIGINFO; 9481.1Skamil sigemptyset(&sa.sa_mask); 9491.1Skamil 9501.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9511.1Skamil 9521.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9531.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9541.1Skamil 9551.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9561.1Skamil 9571.13Schristos DPRINTF("Before exiting of the child process\n"); 9581.1Skamil _exit(exitval); 9591.1Skamil } 9601.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9611.1Skamil 9621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9641.1Skamil 9651.1Skamil validate_status_stopped(status, sigval); 9661.1Skamil 9671.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9681.61Skre SYSCALL_REQUIRE( 9691.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9701.45Skamil 9711.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9721.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9731.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9741.45Skamil info.psi_siginfo.si_errno); 9751.45Skamil 9761.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9771.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9781.45Skamil 9791.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9801.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9811.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9821.1Skamil 9831.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9851.1Skamil 9861.1Skamil validate_status_exited(status, exitval); 9871.1Skamil 9881.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9891.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9901.1Skamil} 9911.1Skamil 9921.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9931.61SkreATF_TC(test); \ 9941.61SkreATF_TC_HEAD(test, tc) \ 9951.61Skre{ \ 9961.61Skre atf_tc_set_md_var(tc, "descr", \ 9971.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9981.61Skre "handled correctly and caught by a signal handler"); \ 9991.61Skre} \ 10001.61Skre \ 10011.61Skrestatic int test##_caught = 0; \ 10021.61Skre \ 10031.61Skrestatic void \ 10041.61Skretest##_sighandler(int arg) \ 10051.61Skre{ \ 10061.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 10071.61Skre \ 10081.61Skre ++ test##_caught; \ 10091.61Skre} \ 10101.61Skre \ 10111.61SkreATF_TC_BODY(test, tc) \ 10121.61Skre{ \ 10131.61Skre \ 10141.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 10151.34Skamil} 10161.34Skamil 10171.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 10181.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 10191.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10201.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10211.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10221.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10231.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10241.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10251.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10261.34Skamil 10271.34Skamil/// ---------------------------------------------------------------------------- 10281.34Skamil 10291.35Skamilstatic void 10301.50Skamiltraceme_sendsignal_masked(int sigsent) 10311.50Skamil{ 10321.50Skamil const int exitval = 5; 10331.50Skamil const int sigval = SIGSTOP; 10341.50Skamil pid_t child, wpid; 10351.50Skamil sigset_t set; 10361.50Skamil#if defined(TWAIT_HAVE_STATUS) 10371.50Skamil int status; 10381.50Skamil#endif 10391.61Skre struct ptrace_siginfo info; 10401.50Skamil 10411.50Skamil memset(&info, 0, sizeof(info)); 10421.50Skamil 10431.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10441.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10451.50Skamil if (child == 0) { 10461.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10471.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10481.50Skamil 10491.50Skamil sigemptyset(&set); 10501.50Skamil sigaddset(&set, sigsent); 10511.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10521.50Skamil 10531.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10541.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10551.50Skamil 10561.50Skamil _exit(exitval); 10571.50Skamil } 10581.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10591.50Skamil 10601.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10611.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10621.50Skamil 10631.50Skamil validate_status_stopped(status, sigval); 10641.50Skamil 10651.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10661.61Skre SYSCALL_REQUIRE( 10671.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10681.50Skamil 10691.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10701.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10711.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10721.50Skamil info.psi_siginfo.si_errno); 10731.50Skamil 10741.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10751.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10761.50Skamil 10771.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10781.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10791.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10801.50Skamil 10811.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10821.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10831.50Skamil 10841.50Skamil validate_status_exited(status, exitval); 10851.50Skamil 10861.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10871.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10881.50Skamil} 10891.50Skamil 10901.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10911.61SkreATF_TC(test); \ 10921.61SkreATF_TC_HEAD(test, tc) \ 10931.61Skre{ \ 10941.61Skre atf_tc_set_md_var(tc, "descr", \ 10951.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10961.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10971.61Skre} \ 10981.61Skre \ 10991.61SkreATF_TC_BODY(test, tc) \ 11001.61Skre{ \ 11011.61Skre \ 11021.61Skre traceme_sendsignal_masked(sig); \ 11031.50Skamil} 11041.50Skamil 11051.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 11061.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 11071.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 11081.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 11091.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 11101.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 11111.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 11121.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 11131.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 11141.50Skamil 11151.50Skamil/// ---------------------------------------------------------------------------- 11161.50Skamil 11171.50Skamilstatic void 11181.50Skamiltraceme_sendsignal_ignored(int sigsent) 11191.50Skamil{ 11201.50Skamil const int exitval = 5; 11211.50Skamil const int sigval = SIGSTOP; 11221.50Skamil pid_t child, wpid; 11231.50Skamil struct sigaction sa; 11241.50Skamil#if defined(TWAIT_HAVE_STATUS) 11251.50Skamil int status; 11261.50Skamil#endif 11271.61Skre struct ptrace_siginfo info; 11281.50Skamil 11291.50Skamil memset(&info, 0, sizeof(info)); 11301.50Skamil 11311.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11321.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11331.50Skamil if (child == 0) { 11341.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11351.61Skre 11361.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11371.50Skamil 11381.50Skamil memset(&sa, 0, sizeof(sa)); 11391.50Skamil sa.sa_handler = SIG_IGN; 11401.50Skamil sigemptyset(&sa.sa_mask); 11411.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11421.50Skamil 11431.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11441.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11451.50Skamil 11461.50Skamil _exit(exitval); 11471.50Skamil } 11481.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11491.50Skamil 11501.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11511.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11521.50Skamil 11531.50Skamil validate_status_stopped(status, sigval); 11541.50Skamil 11551.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11561.61Skre SYSCALL_REQUIRE( 11571.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11581.50Skamil 11591.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11601.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11611.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11621.50Skamil info.psi_siginfo.si_errno); 11631.50Skamil 11641.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11651.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11661.50Skamil 11671.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11681.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11691.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11701.50Skamil 11711.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11721.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11731.50Skamil 11741.50Skamil validate_status_exited(status, exitval); 11751.50Skamil 11761.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11771.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11781.50Skamil} 11791.50Skamil 11801.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11811.61SkreATF_TC(test); \ 11821.61SkreATF_TC_HEAD(test, tc) \ 11831.61Skre{ \ 11841.61Skre atf_tc_set_md_var(tc, "descr", \ 11851.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11861.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11871.61Skre} \ 11881.61Skre \ 11891.61SkreATF_TC_BODY(test, tc) \ 11901.61Skre{ \ 11911.61Skre \ 11921.61Skre traceme_sendsignal_ignored(sig); \ 11931.50Skamil} 11941.50Skamil 11951.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11961.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11971.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11981.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11991.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 12001.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 12011.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 12021.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 12031.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 12041.50Skamil 12051.50Skamil/// ---------------------------------------------------------------------------- 12061.50Skamil 12071.50Skamilstatic void 12081.50Skamiltraceme_sendsignal_simple(int sigsent) 12091.1Skamil{ 12101.35Skamil const int sigval = SIGSTOP; 12111.35Skamil int exitval = 0; 12121.1Skamil pid_t child, wpid; 12131.1Skamil#if defined(TWAIT_HAVE_STATUS) 12141.1Skamil int status; 12151.85Skamil int expect_core; 12161.85Skamil 12171.85Skamil switch (sigsent) { 12181.85Skamil case SIGABRT: 12191.85Skamil case SIGTRAP: 12201.85Skamil case SIGBUS: 12211.85Skamil case SIGILL: 12221.85Skamil case SIGFPE: 12231.85Skamil case SIGSEGV: 12241.85Skamil expect_core = 1; 12251.85Skamil break; 12261.85Skamil default: 12271.85Skamil expect_core = 0; 12281.85Skamil break; 12291.85Skamil } 12301.1Skamil#endif 12311.61Skre struct ptrace_siginfo info; 12321.1Skamil 12331.45Skamil memset(&info, 0, sizeof(info)); 12341.45Skamil 12351.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12361.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12371.1Skamil if (child == 0) { 12381.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12391.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12401.1Skamil 12411.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12421.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12431.1Skamil 12441.35Skamil switch (sigsent) { 12451.35Skamil case SIGCONT: 12461.48Skamil case SIGSTOP: 12471.35Skamil _exit(exitval); 12481.35Skamil default: 12491.35Skamil /* NOTREACHED */ 12501.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12511.35Skamil } 12521.1Skamil } 12531.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12541.1Skamil 12551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12571.1Skamil 12581.1Skamil validate_status_stopped(status, sigval); 12591.1Skamil 12601.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12611.61Skre SYSCALL_REQUIRE( 12621.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12631.45Skamil 12641.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12651.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12661.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12671.45Skamil info.psi_siginfo.si_errno); 12681.45Skamil 12691.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12701.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12711.45Skamil 12721.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12731.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12741.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12751.1Skamil 12761.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12781.1Skamil 12791.35Skamil switch (sigsent) { 12801.48Skamil case SIGSTOP: 12811.48Skamil validate_status_stopped(status, sigsent); 12821.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12831.61Skre "child\n"); 12841.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12851.61Skre sizeof(info)) != -1); 12861.48Skamil 12871.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12881.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12891.61Skre "si_errno=%#x\n", 12901.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12911.61Skre info.psi_siginfo.si_errno); 12921.48Skamil 12931.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12941.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12951.48Skamil 12961.48Skamil DPRINTF("Before resuming the child process where it left off " 12971.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12981.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12991.48Skamil 13001.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13011.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 13021.61Skre child); 13031.48Skamil /* FALLTHROUGH */ 13041.35Skamil case SIGCONT: 13051.35Skamil validate_status_exited(status, exitval); 13061.35Skamil break; 13071.35Skamil default: 13081.35Skamil validate_status_signaled(status, sigsent, expect_core); 13091.35Skamil break; 13101.35Skamil } 13111.1Skamil 13121.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 13131.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 13141.1Skamil} 13151.1Skamil 13161.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 13171.61SkreATF_TC(test); \ 13181.61SkreATF_TC_HEAD(test, tc) \ 13191.61Skre{ \ 13201.61Skre atf_tc_set_md_var(tc, "descr", \ 13211.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13221.61Skre "handled correctly in a child without a signal handler"); \ 13231.61Skre} \ 13241.61Skre \ 13251.61SkreATF_TC_BODY(test, tc) \ 13261.61Skre{ \ 13271.61Skre \ 13281.61Skre traceme_sendsignal_simple(sig); \ 13291.35Skamil} 13301.35Skamil 13311.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13321.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13331.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13341.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13351.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13361.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13371.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13381.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13391.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13401.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13411.35Skamil 13421.35Skamil/// ---------------------------------------------------------------------------- 13431.35Skamil 13441.37SkamilATF_TC(traceme_pid1_parent); 13451.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13461.37Skamil{ 13471.37Skamil atf_tc_set_md_var(tc, "descr", 13481.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13491.37Skamil} 13501.37Skamil 13511.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13521.37Skamil{ 13531.37Skamil struct msg_fds parent_child; 13541.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13551.37Skamil pid_t child1, child2, wpid; 13561.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13571.37Skamil#if defined(TWAIT_HAVE_STATUS) 13581.37Skamil int status; 13591.37Skamil#endif 13601.37Skamil 13611.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13621.37Skamil 13631.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13641.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13651.37Skamil if (child1 == 0) { 13661.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13671.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13681.37Skamil if (child2 != 0) { 13691.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13701.61Skre getpid(), child2); 13711.37Skamil _exit(exitval_child1); 13721.37Skamil } 13731.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13741.37Skamil 13751.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13761.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13771.37Skamil 13781.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13791.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13801.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13811.37Skamil 13821.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13831.37Skamil 13841.37Skamil _exit(exitval_child2); 13851.37Skamil } 13861.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13871.37Skamil 13881.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13891.61Skre TWAIT_REQUIRE_SUCCESS( 13901.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13911.37Skamil 13921.37Skamil validate_status_exited(status, exitval_child1); 13931.37Skamil 13941.37Skamil DPRINTF("Notify that child1 is dead\n"); 13951.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13961.37Skamil 13971.37Skamil DPRINTF("Wait for exiting of child2\n"); 13981.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13991.37Skamil} 14001.37Skamil 14011.37Skamil/// ---------------------------------------------------------------------------- 14021.37Skamil 14031.40Skamilstatic void 14041.40Skamiltraceme_vfork_raise(int sigval) 14051.40Skamil{ 14061.46Skamil const int exitval = 5, exitval_watcher = 10; 14071.46Skamil pid_t child, parent, watcher, wpid; 14081.46Skamil int rv; 14091.40Skamil#if defined(TWAIT_HAVE_STATUS) 14101.40Skamil int status; 14111.85Skamil 14121.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 14131.85Skamil volatile int expect_core; 14141.85Skamil 14151.85Skamil switch (sigval) { 14161.85Skamil case SIGABRT: 14171.85Skamil case SIGTRAP: 14181.85Skamil case SIGBUS: 14191.85Skamil case SIGILL: 14201.85Skamil case SIGFPE: 14211.85Skamil case SIGSEGV: 14221.85Skamil expect_core = 1; 14231.85Skamil break; 14241.85Skamil default: 14251.85Skamil expect_core = 0; 14261.85Skamil break; 14271.85Skamil } 14281.40Skamil#endif 14291.40Skamil 14301.46Skamil /* 14311.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14321.46Skamil * the SIGKILL signal to it. 14331.46Skamil * 14341.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14351.46Skamil * simpler to reparent this process to initproc and forget about it. 14361.46Skamil */ 14371.46Skamil if (sigval == SIGSTOP) { 14381.46Skamil parent = getpid(); 14391.46Skamil 14401.46Skamil watcher = fork(); 14411.46Skamil ATF_REQUIRE(watcher != 1); 14421.46Skamil if (watcher == 0) { 14431.46Skamil /* Double fork(2) trick to reparent to initproc */ 14441.46Skamil watcher = fork(); 14451.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14461.46Skamil if (watcher != 0) 14471.46Skamil _exit(exitval_watcher); 14481.46Skamil 14491.46Skamil child = await_stopped_child(parent); 14501.46Skamil 14511.46Skamil errno = 0; 14521.46Skamil rv = kill(child, SIGKILL); 14531.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14541.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14551.46Skamil 14561.46Skamil /* This exit value will be collected by initproc */ 14571.46Skamil _exit(0); 14581.46Skamil } 14591.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14601.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14611.61Skre watcher); 14621.46Skamil 14631.46Skamil validate_status_exited(status, exitval_watcher); 14641.46Skamil 14651.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14661.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14671.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14681.46Skamil } 14691.46Skamil 14701.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14711.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14721.40Skamil if (child == 0) { 14731.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14741.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14751.40Skamil 14761.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14771.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14781.40Skamil 14791.40Skamil switch (sigval) { 14801.46Skamil case SIGSTOP: 14811.40Skamil case SIGKILL: 14821.40Skamil case SIGABRT: 14831.40Skamil case SIGHUP: 14841.85Skamil case SIGTRAP: 14851.85Skamil case SIGBUS: 14861.85Skamil case SIGILL: 14871.85Skamil case SIGFPE: 14881.85Skamil case SIGSEGV: 14891.40Skamil /* NOTREACHED */ 14901.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14911.70Smrg __unreachable(); 14921.40Skamil default: 14931.40Skamil DPRINTF("Before exiting of the child process\n"); 14941.40Skamil _exit(exitval); 14951.40Skamil } 14961.40Skamil } 14971.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14981.40Skamil 14991.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15001.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15011.40Skamil 15021.40Skamil switch (sigval) { 15031.40Skamil case SIGKILL: 15041.40Skamil case SIGABRT: 15051.40Skamil case SIGHUP: 15061.85Skamil case SIGTRAP: 15071.85Skamil case SIGBUS: 15081.85Skamil case SIGILL: 15091.85Skamil case SIGFPE: 15101.85Skamil case SIGSEGV: 15111.40Skamil validate_status_signaled(status, sigval, expect_core); 15121.40Skamil break; 15131.40Skamil case SIGSTOP: 15141.46Skamil validate_status_signaled(status, SIGKILL, 0); 15151.46Skamil break; 15161.40Skamil case SIGCONT: 15171.47Skamil case SIGTSTP: 15181.47Skamil case SIGTTIN: 15191.47Skamil case SIGTTOU: 15201.40Skamil validate_status_exited(status, exitval); 15211.40Skamil break; 15221.40Skamil default: 15231.40Skamil /* NOTREACHED */ 15241.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15251.40Skamil break; 15261.40Skamil } 15271.40Skamil 15281.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15291.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15301.40Skamil} 15311.40Skamil 15321.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15331.61SkreATF_TC(test); \ 15341.61SkreATF_TC_HEAD(test, tc) \ 15351.61Skre{ \ 15361.61Skre atf_tc_set_md_var(tc, "descr", \ 15371.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15381.61Skre "vfork(2)ed child"); \ 15391.61Skre} \ 15401.61Skre \ 15411.61SkreATF_TC_BODY(test, tc) \ 15421.61Skre{ \ 15431.61Skre \ 15441.61Skre traceme_vfork_raise(sig); \ 15451.40Skamil} 15461.40Skamil 15471.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15481.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15491.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15501.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15511.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15521.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15531.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15541.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15551.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15561.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15571.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15581.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15591.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15601.40Skamil 15611.40Skamil/// ---------------------------------------------------------------------------- 15621.40Skamil 15631.52Skamilstatic void 15641.52Skamiltraceme_vfork_crash(int sig) 15651.41Skamil{ 15661.41Skamil pid_t child, wpid; 15671.41Skamil#if defined(TWAIT_HAVE_STATUS) 15681.41Skamil int status; 15691.41Skamil#endif 15701.41Skamil 15711.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15721.71Skamil if (sig == SIGILL) 15731.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15741.71Skamil#endif 15751.71Skamil 15761.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15771.114Skamil atf_tc_skip("FP exceptions are not supported"); 15781.114Skamil 15791.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15801.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15811.41Skamil if (child == 0) { 15821.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15831.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15841.41Skamil 15851.52Skamil DPRINTF("Before executing a trap\n"); 15861.52Skamil switch (sig) { 15871.52Skamil case SIGTRAP: 15881.52Skamil trigger_trap(); 15891.52Skamil break; 15901.52Skamil case SIGSEGV: 15911.52Skamil trigger_segv(); 15921.52Skamil break; 15931.52Skamil case SIGILL: 15941.52Skamil trigger_ill(); 15951.52Skamil break; 15961.52Skamil case SIGFPE: 15971.52Skamil trigger_fpe(); 15981.52Skamil break; 15991.52Skamil case SIGBUS: 16001.52Skamil trigger_bus(); 16011.52Skamil break; 16021.52Skamil default: 16031.52Skamil /* NOTREACHED */ 16041.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16051.52Skamil } 16061.41Skamil 16071.41Skamil /* NOTREACHED */ 16081.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16091.41Skamil } 16101.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16111.41Skamil 16121.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16131.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16141.41Skamil 16151.52Skamil validate_status_signaled(status, sig, 1); 16161.41Skamil 16171.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16181.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16191.41Skamil} 16201.41Skamil 16211.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16221.61SkreATF_TC(test); \ 16231.61SkreATF_TC_HEAD(test, tc) \ 16241.61Skre{ \ 16251.61Skre atf_tc_set_md_var(tc, "descr", \ 16261.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16271.61Skre "vfork(2)ed child"); \ 16281.61Skre} \ 16291.61Skre \ 16301.61SkreATF_TC_BODY(test, tc) \ 16311.61Skre{ \ 16321.61Skre \ 16331.61Skre traceme_vfork_crash(sig); \ 16341.52Skamil} 16351.52Skamil 16361.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16371.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16381.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16391.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16401.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16411.52Skamil 16421.41Skamil/// ---------------------------------------------------------------------------- 16431.41Skamil 16441.92Skamilstatic void 16451.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16461.92Skamil{ 16471.92Skamil pid_t child, wpid; 16481.92Skamil#if defined(TWAIT_HAVE_STATUS) 16491.92Skamil int status; 16501.92Skamil#endif 16511.92Skamil sigset_t intmask; 16521.92Skamil 16531.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16541.92Skamil if (sig == SIGILL) 16551.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16561.92Skamil#endif 16571.92Skamil 16581.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16591.114Skamil atf_tc_skip("FP exceptions are not supported"); 16601.114Skamil 16611.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16621.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16631.92Skamil if (child == 0) { 16641.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16651.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16661.92Skamil 16671.92Skamil sigemptyset(&intmask); 16681.92Skamil sigaddset(&intmask, sig); 16691.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16701.92Skamil 16711.92Skamil DPRINTF("Before executing a trap\n"); 16721.92Skamil switch (sig) { 16731.92Skamil case SIGTRAP: 16741.92Skamil trigger_trap(); 16751.92Skamil break; 16761.92Skamil case SIGSEGV: 16771.92Skamil trigger_segv(); 16781.92Skamil break; 16791.92Skamil case SIGILL: 16801.92Skamil trigger_ill(); 16811.92Skamil break; 16821.92Skamil case SIGFPE: 16831.92Skamil trigger_fpe(); 16841.92Skamil break; 16851.92Skamil case SIGBUS: 16861.92Skamil trigger_bus(); 16871.92Skamil break; 16881.92Skamil default: 16891.92Skamil /* NOTREACHED */ 16901.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16911.92Skamil } 16921.92Skamil 16931.92Skamil /* NOTREACHED */ 16941.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16951.92Skamil } 16961.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16971.92Skamil 16981.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16991.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17001.92Skamil 17011.92Skamil validate_status_signaled(status, sig, 1); 17021.92Skamil 17031.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17041.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17051.92Skamil} 17061.92Skamil 17071.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 17081.92SkamilATF_TC(test); \ 17091.92SkamilATF_TC_HEAD(test, tc) \ 17101.92Skamil{ \ 17111.92Skamil atf_tc_set_md_var(tc, "descr", \ 17121.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17131.92Skamil "vfork(2)ed child with a masked signal"); \ 17141.92Skamil} \ 17151.92Skamil \ 17161.92SkamilATF_TC_BODY(test, tc) \ 17171.92Skamil{ \ 17181.92Skamil \ 17191.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17201.92Skamil} 17211.92Skamil 17221.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17231.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17241.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17251.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17261.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17271.92Skamil 17281.92Skamil/// ---------------------------------------------------------------------------- 17291.92Skamil 17301.92Skamilstatic void 17311.92Skamiltraceme_vfork_signalignored_crash(int sig) 17321.92Skamil{ 17331.92Skamil pid_t child, wpid; 17341.92Skamil#if defined(TWAIT_HAVE_STATUS) 17351.92Skamil int status; 17361.92Skamil#endif 17371.92Skamil struct sigaction sa; 17381.92Skamil 17391.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17401.92Skamil if (sig == SIGILL) 17411.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17421.92Skamil#endif 17431.92Skamil 17441.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17451.114Skamil atf_tc_skip("FP exceptions are not supported"); 17461.114Skamil 17471.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17481.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17491.92Skamil if (child == 0) { 17501.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17511.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17521.92Skamil 17531.92Skamil memset(&sa, 0, sizeof(sa)); 17541.92Skamil sa.sa_handler = SIG_IGN; 17551.92Skamil sigemptyset(&sa.sa_mask); 17561.92Skamil 17571.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17581.92Skamil 17591.92Skamil DPRINTF("Before executing a trap\n"); 17601.92Skamil switch (sig) { 17611.92Skamil case SIGTRAP: 17621.92Skamil trigger_trap(); 17631.92Skamil break; 17641.92Skamil case SIGSEGV: 17651.92Skamil trigger_segv(); 17661.92Skamil break; 17671.92Skamil case SIGILL: 17681.92Skamil trigger_ill(); 17691.92Skamil break; 17701.92Skamil case SIGFPE: 17711.92Skamil trigger_fpe(); 17721.92Skamil break; 17731.92Skamil case SIGBUS: 17741.92Skamil trigger_bus(); 17751.92Skamil break; 17761.92Skamil default: 17771.92Skamil /* NOTREACHED */ 17781.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17791.92Skamil } 17801.92Skamil 17811.92Skamil /* NOTREACHED */ 17821.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17831.92Skamil } 17841.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17851.92Skamil 17861.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17871.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17881.92Skamil 17891.92Skamil validate_status_signaled(status, sig, 1); 17901.92Skamil 17911.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17921.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17931.92Skamil} 17941.92Skamil 17951.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17961.92SkamilATF_TC(test); \ 17971.92SkamilATF_TC_HEAD(test, tc) \ 17981.92Skamil{ \ 17991.92Skamil atf_tc_set_md_var(tc, "descr", \ 18001.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 18011.92Skamil "vfork(2)ed child with ignored signal"); \ 18021.92Skamil} \ 18031.92Skamil \ 18041.92SkamilATF_TC_BODY(test, tc) \ 18051.92Skamil{ \ 18061.92Skamil \ 18071.92Skamil traceme_vfork_signalignored_crash(sig); \ 18081.92Skamil} 18091.92Skamil 18101.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 18111.92Skamil SIGTRAP) 18121.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 18131.92Skamil SIGSEGV) 18141.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 18151.92Skamil SIGILL) 18161.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 18171.92Skamil SIGFPE) 18181.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 18191.92Skamil SIGBUS) 18201.92Skamil 18211.92Skamil/// ---------------------------------------------------------------------------- 18221.92Skamil 18231.96Skamilstatic void 18241.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18251.43Skamil{ 18261.43Skamil const int sigval = SIGTRAP; 18271.43Skamil pid_t child, wpid; 18281.43Skamil#if defined(TWAIT_HAVE_STATUS) 18291.43Skamil int status; 18301.43Skamil#endif 18311.96Skamil struct sigaction sa; 18321.61Skre struct ptrace_siginfo info; 18331.96Skamil sigset_t intmask; 18341.96Skamil struct kinfo_proc2 kp; 18351.96Skamil size_t len = sizeof(kp); 18361.96Skamil 18371.96Skamil int name[6]; 18381.96Skamil const size_t namelen = __arraycount(name); 18391.96Skamil ki_sigset_t kp_sigmask; 18401.96Skamil ki_sigset_t kp_sigignore; 18411.43Skamil 18421.43Skamil memset(&info, 0, sizeof(info)); 18431.43Skamil 18441.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18451.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18461.43Skamil if (child == 0) { 18471.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18481.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18491.43Skamil 18501.96Skamil if (masked) { 18511.96Skamil sigemptyset(&intmask); 18521.96Skamil sigaddset(&intmask, sigval); 18531.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18541.96Skamil } 18551.96Skamil 18561.96Skamil if (ignored) { 18571.96Skamil memset(&sa, 0, sizeof(sa)); 18581.96Skamil sa.sa_handler = SIG_IGN; 18591.96Skamil sigemptyset(&sa.sa_mask); 18601.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18611.96Skamil } 18621.96Skamil 18631.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18641.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18651.43Skamil 18661.43Skamil /* NOTREACHED */ 18671.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18681.43Skamil } 18691.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18701.43Skamil 18711.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18721.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18731.43Skamil 18741.43Skamil validate_status_stopped(status, sigval); 18751.43Skamil 18761.96Skamil name[0] = CTL_KERN, 18771.96Skamil name[1] = KERN_PROC2, 18781.96Skamil name[2] = KERN_PROC_PID; 18791.96Skamil name[3] = getpid(); 18801.96Skamil name[4] = sizeof(kp); 18811.96Skamil name[5] = 1; 18821.96Skamil 18831.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18841.96Skamil 18851.96Skamil if (masked) 18861.96Skamil kp_sigmask = kp.p_sigmask; 18871.96Skamil 18881.96Skamil if (ignored) 18891.96Skamil kp_sigignore = kp.p_sigignore; 18901.96Skamil 18911.96Skamil name[3] = getpid(); 18921.96Skamil 18931.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18941.96Skamil 18951.96Skamil if (masked) { 18961.96Skamil DPRINTF("kp_sigmask=" 18971.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18981.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18991.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 19001.96Skamil 19011.96Skamil DPRINTF("kp.p_sigmask=" 19021.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19031.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 19041.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 19051.96Skamil 19061.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 19071.96Skamil sizeof(kp_sigmask))); 19081.96Skamil } 19091.96Skamil 19101.96Skamil if (ignored) { 19111.96Skamil DPRINTF("kp_sigignore=" 19121.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19131.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 19141.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 19151.96Skamil 19161.96Skamil DPRINTF("kp.p_sigignore=" 19171.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19181.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 19191.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19201.96Skamil 19211.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19221.96Skamil sizeof(kp_sigignore))); 19231.96Skamil } 19241.96Skamil 19251.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19261.61Skre SYSCALL_REQUIRE( 19271.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19281.43Skamil 19291.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19301.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19311.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19321.43Skamil info.psi_siginfo.si_errno); 19331.43Skamil 19341.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19351.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19361.43Skamil 19371.43Skamil DPRINTF("Before resuming the child process where it left off and " 19381.43Skamil "without signal to be sent\n"); 19391.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19401.43Skamil 19411.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19421.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19431.43Skamil 19441.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19451.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19461.43Skamil} 19471.43Skamil 19481.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19491.96SkamilATF_TC(test); \ 19501.96SkamilATF_TC_HEAD(test, tc) \ 19511.96Skamil{ \ 19521.96Skamil atf_tc_set_md_var(tc, "descr", \ 19531.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19541.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19551.96Skamil masked ? " with ignored signal" : ""); \ 19561.96Skamil} \ 19571.96Skamil \ 19581.96SkamilATF_TC_BODY(test, tc) \ 19591.96Skamil{ \ 19601.96Skamil \ 19611.96Skamil traceme_vfork_exec(masked, ignored); \ 19621.96Skamil} 19631.96Skamil 19641.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19651.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19661.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19671.96Skamil 19681.43Skamil/// ---------------------------------------------------------------------------- 19691.43Skamil 19701.1Skamil#if defined(TWAIT_HAVE_PID) 19711.51Skamilstatic void 19721.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19731.59Skamil{ 19741.94Skamil const int sigval = SIGSTOP; 19751.59Skamil struct msg_fds parent_tracee, parent_tracer; 19761.59Skamil const int exitval = 10; 19771.59Skamil pid_t tracee, tracer, wpid; 19781.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19791.59Skamil#if defined(TWAIT_HAVE_STATUS) 19801.59Skamil int status; 19811.59Skamil#endif 19821.94Skamil struct sigaction sa; 19831.59Skamil struct ptrace_siginfo info; 19841.94Skamil sigset_t intmask; 19851.94Skamil struct kinfo_proc2 kp; 19861.94Skamil size_t len = sizeof(kp); 19871.94Skamil 19881.94Skamil int name[6]; 19891.94Skamil const size_t namelen = __arraycount(name); 19901.94Skamil ki_sigset_t kp_sigmask; 19911.94Skamil ki_sigset_t kp_sigignore; 19921.61Skre 19931.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19941.71Skamil if (sig == SIGILL) 19951.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19961.71Skamil#endif 19971.71Skamil 19981.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19991.114Skamil atf_tc_skip("FP exceptions are not supported"); 20001.114Skamil 20011.59Skamil memset(&info, 0, sizeof(info)); 20021.59Skamil 20031.59Skamil DPRINTF("Spawn tracee\n"); 20041.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 20051.59Skamil tracee = atf_utils_fork(); 20061.59Skamil if (tracee == 0) { 20071.59Skamil // Wait for parent to let us crash 20081.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 20091.61Skre 20101.94Skamil if (masked) { 20111.94Skamil sigemptyset(&intmask); 20121.94Skamil sigaddset(&intmask, sig); 20131.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 20141.94Skamil } 20151.94Skamil 20161.94Skamil if (ignored) { 20171.94Skamil memset(&sa, 0, sizeof(sa)); 20181.94Skamil sa.sa_handler = SIG_IGN; 20191.94Skamil sigemptyset(&sa.sa_mask); 20201.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20211.94Skamil } 20221.94Skamil 20231.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20241.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20251.94Skamil 20261.59Skamil DPRINTF("Before executing a trap\n"); 20271.59Skamil switch (sig) { 20281.59Skamil case SIGTRAP: 20291.59Skamil trigger_trap(); 20301.59Skamil break; 20311.59Skamil case SIGSEGV: 20321.59Skamil trigger_segv(); 20331.59Skamil break; 20341.59Skamil case SIGILL: 20351.59Skamil trigger_ill(); 20361.59Skamil break; 20371.59Skamil case SIGFPE: 20381.59Skamil trigger_fpe(); 20391.59Skamil break; 20401.59Skamil case SIGBUS: 20411.59Skamil trigger_bus(); 20421.59Skamil break; 20431.59Skamil default: 20441.59Skamil /* NOTREACHED */ 20451.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20461.59Skamil } 20471.59Skamil 20481.59Skamil /* NOTREACHED */ 20491.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20501.59Skamil } 20511.59Skamil 20521.59Skamil DPRINTF("Spawn debugger\n"); 20531.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20541.59Skamil tracer = atf_utils_fork(); 20551.59Skamil if (tracer == 0) { 20561.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20571.59Skamil tracer = atf_utils_fork(); 20581.59Skamil if (tracer != 0) 20591.61Skre _exit(exitval); 20601.59Skamil 20611.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20621.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20631.59Skamil 20641.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20651.59Skamil FORKEE_REQUIRE_SUCCESS( 20661.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20671.59Skamil 20681.59Skamil forkee_status_stopped(status, SIGSTOP); 20691.59Skamil 20701.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20711.94Skamil "traced process\n"); 20721.94Skamil SYSCALL_REQUIRE( 20731.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20741.94Skamil 20751.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20761.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20771.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20781.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20791.94Skamil 20801.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20811.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20821.94Skamil 20831.59Skamil /* Resume tracee with PT_CONTINUE */ 20841.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20851.59Skamil 20861.59Skamil /* Inform parent that tracer has attached to tracee */ 20871.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20881.59Skamil 20891.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20901.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20911.59Skamil 20921.59Skamil /* Wait for tracee and assert that it exited */ 20931.59Skamil FORKEE_REQUIRE_SUCCESS( 20941.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20951.59Skamil 20961.94Skamil forkee_status_stopped(status, sigval); 20971.94Skamil 20981.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20991.94Skamil "traced process\n"); 21001.94Skamil SYSCALL_REQUIRE( 21011.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21021.94Skamil 21031.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21041.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21051.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 21061.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21071.94Skamil 21081.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 21091.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 21101.94Skamil 21111.94Skamil name[0] = CTL_KERN, 21121.94Skamil name[1] = KERN_PROC2, 21131.94Skamil name[2] = KERN_PROC_PID; 21141.94Skamil name[3] = tracee; 21151.94Skamil name[4] = sizeof(kp); 21161.94Skamil name[5] = 1; 21171.94Skamil 21181.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21191.94Skamil 21201.94Skamil if (masked) 21211.94Skamil kp_sigmask = kp.p_sigmask; 21221.94Skamil 21231.94Skamil if (ignored) 21241.94Skamil kp_sigignore = kp.p_sigignore; 21251.94Skamil 21261.94Skamil /* Resume tracee with PT_CONTINUE */ 21271.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21281.94Skamil 21291.94Skamil /* Wait for tracee and assert that it exited */ 21301.94Skamil FORKEE_REQUIRE_SUCCESS( 21311.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21321.94Skamil 21331.93Skamil forkee_status_stopped(status, sig); 21341.59Skamil 21351.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21361.61Skre "traced process\n"); 21371.61Skre SYSCALL_REQUIRE( 21381.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21391.59Skamil 21401.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21411.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21421.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21431.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21441.59Skamil 21451.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21461.94Skamil 21471.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21481.94Skamil 21491.94Skamil if (masked) { 21501.94Skamil DPRINTF("kp_sigmask=" 21511.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21521.94Skamil PRIx32 "\n", 21531.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21541.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21551.94Skamil 21561.94Skamil DPRINTF("kp.p_sigmask=" 21571.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21581.94Skamil PRIx32 "\n", 21591.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21601.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21611.94Skamil 21621.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21631.94Skamil sizeof(kp_sigmask))); 21641.94Skamil } 21651.94Skamil 21661.94Skamil if (ignored) { 21671.94Skamil DPRINTF("kp_sigignore=" 21681.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21691.94Skamil PRIx32 "\n", 21701.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21711.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21721.94Skamil 21731.94Skamil DPRINTF("kp.p_sigignore=" 21741.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21751.94Skamil PRIx32 "\n", 21761.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21771.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21781.94Skamil 21791.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21801.94Skamil sizeof(kp_sigignore))); 21811.94Skamil } 21821.94Skamil 21831.59Skamil switch (sig) { 21841.59Skamil case SIGTRAP: 21851.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21861.59Skamil break; 21871.59Skamil case SIGSEGV: 21881.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21891.59Skamil break; 21901.71Skamil case SIGILL: 21911.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21921.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21931.71Skamil break; 21941.59Skamil case SIGFPE: 21951.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21961.59Skamil break; 21971.59Skamil case SIGBUS: 21981.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21991.59Skamil break; 22001.59Skamil } 22011.59Skamil 22021.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 22031.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 22041.93Skamil FORKEE_REQUIRE_SUCCESS( 22051.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22061.59Skamil 22071.93Skamil forkee_status_signaled(status, SIGKILL, 0); 22081.59Skamil 22091.71Skamil /* Inform parent that tracer is exiting normally */ 22101.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 22111.71Skamil 22121.59Skamil DPRINTF("Before exiting of the tracer process\n"); 22131.59Skamil _exit(0 /* collect by initproc */); 22141.59Skamil } 22151.59Skamil 22161.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 22171.59Skamil "calling %s()\n", TWAIT_FNAME); 22181.59Skamil TWAIT_REQUIRE_SUCCESS( 22191.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22201.59Skamil 22211.59Skamil validate_status_exited(status, exitval); 22221.59Skamil 22231.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22241.59Skamil TWAIT_FNAME); 22251.59Skamil TWAIT_REQUIRE_SUCCESS( 22261.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22271.59Skamil 22281.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22291.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22301.59Skamil 22311.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22321.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22331.59Skamil 22341.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22351.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22361.59Skamil 22371.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22381.59Skamil TWAIT_FNAME); 22391.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22401.59Skamil 22411.59Skamil validate_status_signaled(status, SIGKILL, 0); 22421.59Skamil 22431.71Skamil DPRINTF("Await normal exit of tracer\n"); 22441.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22451.71Skamil 22461.59Skamil msg_close(&parent_tracer); 22471.59Skamil msg_close(&parent_tracee); 22481.59Skamil} 22491.59Skamil 22501.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22511.61SkreATF_TC(test); \ 22521.61SkreATF_TC_HEAD(test, tc) \ 22531.61Skre{ \ 22541.61Skre atf_tc_set_md_var(tc, "descr", \ 22551.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22561.94Skamil "the debuggee"); \ 22571.61Skre} \ 22581.61Skre \ 22591.61SkreATF_TC_BODY(test, tc) \ 22601.61Skre{ \ 22611.61Skre \ 22621.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22631.59Skamil} 22641.59Skamil 22651.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22661.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22671.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22681.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22691.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22701.94Skamil 22711.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22721.94SkamilATF_TC(test); \ 22731.94SkamilATF_TC_HEAD(test, tc) \ 22741.94Skamil{ \ 22751.94Skamil atf_tc_set_md_var(tc, "descr", \ 22761.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22771.94Skamil "the debuggee with masked signal"); \ 22781.94Skamil} \ 22791.94Skamil \ 22801.94SkamilATF_TC_BODY(test, tc) \ 22811.94Skamil{ \ 22821.94Skamil \ 22831.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22841.94Skamil} 22851.94Skamil 22861.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22871.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22881.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22891.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22901.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22911.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22921.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22931.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22941.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22951.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22961.94Skamil 22971.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22981.94SkamilATF_TC(test); \ 22991.94SkamilATF_TC_HEAD(test, tc) \ 23001.94Skamil{ \ 23011.94Skamil atf_tc_set_md_var(tc, "descr", \ 23021.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 23031.94Skamil "the debuggee with signal ignored"); \ 23041.94Skamil} \ 23051.94Skamil \ 23061.94SkamilATF_TC_BODY(test, tc) \ 23071.94Skamil{ \ 23081.94Skamil \ 23091.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 23101.94Skamil} 23111.94Skamil 23121.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23131.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 23141.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23151.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 23161.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23171.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 23181.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23191.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23201.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23211.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23221.59Skamil#endif 23231.59Skamil 23241.59Skamil/// ---------------------------------------------------------------------------- 23251.59Skamil 23261.59Skamil#if defined(TWAIT_HAVE_PID) 23271.59Skamilstatic void 23281.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23291.67Skamil bool stopped) 23301.1Skamil{ 23311.51Skamil /* 23321.51Skamil * notimeout - disable timeout in await zombie function 23331.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23341.67Skamil * stopped - attach to a stopped process 23351.51Skamil */ 23361.1Skamil 23371.1Skamil struct msg_fds parent_tracee, parent_tracer; 23381.1Skamil const int exitval_tracee = 5; 23391.1Skamil const int exitval_tracer = 10; 23401.1Skamil pid_t tracee, tracer, wpid; 23411.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23421.1Skamil#if defined(TWAIT_HAVE_STATUS) 23431.1Skamil int status; 23441.1Skamil#endif 23451.1Skamil 23461.67Skamil /* 23471.67Skamil * Only a subset of options are supported. 23481.67Skamil */ 23491.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23501.67Skamil (!notimeout && unrelated && !stopped) || 23511.67Skamil (notimeout && !unrelated && !stopped) || 23521.67Skamil (!notimeout && unrelated && stopped)); 23531.67Skamil 23541.13Schristos DPRINTF("Spawn tracee\n"); 23551.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23561.1Skamil tracee = atf_utils_fork(); 23571.1Skamil if (tracee == 0) { 23581.67Skamil if (stopped) { 23591.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23601.67Skamil raise(SIGSTOP); 23611.67Skamil } 23621.67Skamil 23631.1Skamil // Wait for parent to let us exit 23641.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23651.1Skamil _exit(exitval_tracee); 23661.1Skamil } 23671.1Skamil 23681.13Schristos DPRINTF("Spawn debugger\n"); 23691.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23701.1Skamil tracer = atf_utils_fork(); 23711.1Skamil if (tracer == 0) { 23721.51Skamil if(unrelated) { 23731.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23741.51Skamil tracer = atf_utils_fork(); 23751.51Skamil if (tracer != 0) 23761.51Skamil _exit(exitval_tracer); 23771.51Skamil } 23781.51Skamil 23791.67Skamil if (stopped) { 23801.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23811.67Skamil await_stopped(tracee); 23821.67Skamil } 23831.67Skamil 23841.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23851.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23861.1Skamil 23871.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23881.1Skamil FORKEE_REQUIRE_SUCCESS( 23891.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23901.1Skamil 23911.1Skamil forkee_status_stopped(status, SIGSTOP); 23921.1Skamil 23931.1Skamil /* Resume tracee with PT_CONTINUE */ 23941.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23951.1Skamil 23961.1Skamil /* Inform parent that tracer has attached to tracee */ 23971.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23981.1Skamil 23991.1Skamil /* Wait for parent to tell use that tracee should have exited */ 24001.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 24011.1Skamil 24021.1Skamil /* Wait for tracee and assert that it exited */ 24031.1Skamil FORKEE_REQUIRE_SUCCESS( 24041.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24051.1Skamil 24061.1Skamil forkee_status_exited(status, exitval_tracee); 24071.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 24081.1Skamil 24091.13Schristos DPRINTF("Before exiting of the tracer process\n"); 24101.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 24111.51Skamil } 24121.51Skamil 24131.51Skamil if (unrelated) { 24141.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 24151.51Skamil "calling %s()\n", TWAIT_FNAME); 24161.51Skamil TWAIT_REQUIRE_SUCCESS( 24171.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 24181.51Skamil 24191.51Skamil validate_status_exited(status, exitval_tracer); 24201.51Skamil 24211.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24221.51Skamil TWAIT_FNAME); 24231.51Skamil TWAIT_REQUIRE_SUCCESS( 24241.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24251.1Skamil } 24261.1Skamil 24271.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24281.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24291.1Skamil 24301.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24311.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24321.1Skamil 24331.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24341.51Skamil if (notimeout) 24351.26Skamil await_zombie_raw(tracee, 0); 24361.26Skamil else 24371.26Skamil await_zombie(tracee); 24381.1Skamil 24391.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24401.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24411.1Skamil TWAIT_FNAME); 24421.1Skamil TWAIT_REQUIRE_SUCCESS( 24431.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24441.1Skamil 24451.51Skamil if (unrelated) { 24461.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24471.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24481.51Skamil } else { 24491.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24501.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24511.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24521.59Skamil "%s()\n", TWAIT_FNAME); 24531.51Skamil 24541.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24551.59Skamil "tracee\n"); 24561.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24571.51Skamil tracer); 24581.1Skamil 24591.51Skamil validate_status_exited(status, exitval_tracer); 24601.51Skamil } 24611.1Skamil 24621.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24631.1Skamil TWAIT_FNAME); 24641.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24651.1Skamil 24661.1Skamil validate_status_exited(status, exitval_tracee); 24671.1Skamil 24681.1Skamil msg_close(&parent_tracer); 24691.1Skamil msg_close(&parent_tracee); 24701.1Skamil} 24711.26Skamil 24721.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24731.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24741.51Skamil{ 24751.51Skamil atf_tc_set_md_var(tc, "descr", 24761.51Skamil "Assert that tracer sees process termination before the parent"); 24771.51Skamil} 24781.51Skamil 24791.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24801.26Skamil{ 24811.26Skamil 24821.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24831.26Skamil} 24841.26Skamil 24851.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24861.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24871.1Skamil{ 24881.1Skamil atf_tc_set_md_var(tc, "descr", 24891.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24901.51Skamil "process and no other error is reported"); 24911.1Skamil} 24921.1Skamil 24931.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24941.1Skamil{ 24951.51Skamil time_t start, end; 24961.51Skamil double diff; 24971.51Skamil unsigned long N = 0; 24981.1Skamil 24991.51Skamil /* 25001.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 25011.51Skamil * This test body isn't specific to this race, however it's just good 25021.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 25031.51Skamil */ 25041.1Skamil 25051.51Skamil start = time(NULL); 25061.51Skamil while (true) { 25071.51Skamil DPRINTF("Step: %lu\n", N); 25081.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 25091.67Skamil false); 25101.51Skamil end = time(NULL); 25111.51Skamil diff = difftime(end, start); 25121.51Skamil if (diff >= 5.0) 25131.51Skamil break; 25141.51Skamil ++N; 25151.1Skamil } 25161.51Skamil DPRINTF("Iterations: %lu\n", N); 25171.51Skamil} 25181.1Skamil 25191.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25201.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25211.51Skamil{ 25221.51Skamil atf_tc_set_md_var(tc, "descr", 25231.51Skamil "Assert that tracer sees process termination before the parent"); 25241.51Skamil} 25251.1Skamil 25261.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25271.51Skamil{ 25281.1Skamil 25291.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25301.67Skamil} 25311.67Skamil 25321.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25331.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25341.67Skamil{ 25351.67Skamil atf_tc_set_md_var(tc, "descr", 25361.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25371.67Skamil} 25381.67Skamil 25391.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25401.67Skamil{ 25411.67Skamil 25421.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25431.1Skamil} 25441.1Skamil#endif 25451.1Skamil 25461.51Skamil/// ---------------------------------------------------------------------------- 25471.51Skamil 25481.66Skamilstatic void 25491.66Skamilparent_attach_to_its_child(bool stopped) 25501.1Skamil{ 25511.1Skamil struct msg_fds parent_tracee; 25521.1Skamil const int exitval_tracee = 5; 25531.1Skamil pid_t tracee, wpid; 25541.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25551.1Skamil#if defined(TWAIT_HAVE_STATUS) 25561.1Skamil int status; 25571.1Skamil#endif 25581.1Skamil 25591.13Schristos DPRINTF("Spawn tracee\n"); 25601.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25611.1Skamil tracee = atf_utils_fork(); 25621.1Skamil if (tracee == 0) { 25631.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25641.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25651.1Skamil 25661.66Skamil if (stopped) { 25671.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25681.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25691.66Skamil } 25701.66Skamil 25711.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25721.1Skamil /* Wait for message from the parent */ 25731.1Skamil _exit(exitval_tracee); 25741.1Skamil } 25751.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25761.57Skamil 25771.66Skamil if (stopped) { 25781.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25791.66Skamil await_stopped(tracee); 25801.66Skamil } 25811.66Skamil 25821.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25831.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25841.1Skamil 25851.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25861.1Skamil TWAIT_FNAME); 25871.1Skamil TWAIT_REQUIRE_SUCCESS( 25881.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25891.1Skamil 25901.1Skamil validate_status_stopped(status, SIGSTOP); 25911.1Skamil 25921.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25941.1Skamil 25951.13Schristos DPRINTF("Let the tracee exit now\n"); 25961.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25971.1Skamil 25981.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25991.1Skamil TWAIT_REQUIRE_SUCCESS( 26001.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 26011.1Skamil 26021.1Skamil validate_status_exited(status, exitval_tracee); 26031.1Skamil 26041.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 26051.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26061.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 26071.1Skamil 26081.1Skamil msg_close(&parent_tracee); 26091.1Skamil} 26101.1Skamil 26111.66SkamilATF_TC(parent_attach_to_its_child); 26121.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 26131.66Skamil{ 26141.66Skamil atf_tc_set_md_var(tc, "descr", 26151.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 26161.66Skamil} 26171.66Skamil 26181.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26191.66Skamil{ 26201.66Skamil 26211.66Skamil parent_attach_to_its_child(false); 26221.66Skamil} 26231.66Skamil 26241.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26251.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26261.66Skamil{ 26271.66Skamil atf_tc_set_md_var(tc, "descr", 26281.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26291.66Skamil} 26301.66Skamil 26311.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26321.66Skamil{ 26331.66Skamil 26341.66Skamil parent_attach_to_its_child(true); 26351.66Skamil} 26361.66Skamil 26371.51Skamil/// ---------------------------------------------------------------------------- 26381.51Skamil 26391.65Skamilstatic void 26401.65Skamilchild_attach_to_its_parent(bool stopped) 26411.1Skamil{ 26421.1Skamil struct msg_fds parent_tracee; 26431.1Skamil const int exitval_tracer = 5; 26441.1Skamil pid_t tracer, wpid; 26451.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26461.1Skamil#if defined(TWAIT_HAVE_STATUS) 26471.1Skamil int status; 26481.1Skamil#endif 26491.1Skamil 26501.13Schristos DPRINTF("Spawn tracer\n"); 26511.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26521.1Skamil tracer = atf_utils_fork(); 26531.1Skamil if (tracer == 0) { 26541.1Skamil /* Wait for message from the parent */ 26551.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26561.1Skamil 26571.65Skamil if (stopped) { 26581.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26591.65Skamil getppid()); 26601.65Skamil await_stopped(getppid()); 26611.65Skamil } 26621.65Skamil 26631.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26641.1Skamil getppid()); 26651.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26661.1Skamil 26671.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26681.1Skamil TWAIT_FNAME); 26691.1Skamil FORKEE_REQUIRE_SUCCESS( 26701.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26711.1Skamil 26721.1Skamil forkee_status_stopped(status, SIGSTOP); 26731.1Skamil 26741.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26751.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26761.1Skamil != -1); 26771.1Skamil 26781.1Skamil /* Tell parent we are ready */ 26791.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26801.1Skamil 26811.1Skamil _exit(exitval_tracer); 26821.1Skamil } 26831.1Skamil 26841.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26851.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26861.65Skamil 26871.65Skamil if (stopped) { 26881.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26891.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26901.65Skamil } 26911.65Skamil 26921.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26931.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26941.1Skamil 26951.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26961.1Skamil TWAIT_REQUIRE_SUCCESS( 26971.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26981.1Skamil 26991.1Skamil validate_status_exited(status, exitval_tracer); 27001.1Skamil 27011.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 27021.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 27031.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 27041.1Skamil 27051.1Skamil msg_close(&parent_tracee); 27061.1Skamil} 27071.1Skamil 27081.65SkamilATF_TC(child_attach_to_its_parent); 27091.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 27101.65Skamil{ 27111.65Skamil atf_tc_set_md_var(tc, "descr", 27121.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 27131.65Skamil} 27141.65Skamil 27151.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 27161.65Skamil{ 27171.65Skamil 27181.65Skamil child_attach_to_its_parent(false); 27191.65Skamil} 27201.65Skamil 27211.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27221.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27231.65Skamil{ 27241.65Skamil atf_tc_set_md_var(tc, "descr", 27251.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27261.65Skamil} 27271.65Skamil 27281.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27291.65Skamil{ 27301.65Skamil /* 27311.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27321.65Skamil * this causes a pipe (established from atf-run) to be broken. 27331.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27341.65Skamil * 27351.65Skamil * As a workaround spawn this test as a subprocess. 27361.65Skamil */ 27371.65Skamil 27381.65Skamil const int exitval = 15; 27391.65Skamil pid_t child, wpid; 27401.65Skamil#if defined(TWAIT_HAVE_STATUS) 27411.65Skamil int status; 27421.65Skamil#endif 27431.65Skamil 27441.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27451.65Skamil if (child == 0) { 27461.65Skamil child_attach_to_its_parent(true); 27471.65Skamil _exit(exitval); 27481.65Skamil } else { 27491.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27501.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27511.65Skamil 27521.65Skamil validate_status_exited(status, exitval); 27531.65Skamil 27541.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27551.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27561.65Skamil } 27571.65Skamil} 27581.65Skamil 27591.51Skamil/// ---------------------------------------------------------------------------- 27601.51Skamil 27611.1Skamil#if defined(TWAIT_HAVE_PID) 27621.1Skamil 27631.51Skamilenum tracee_sees_its_original_parent_type { 27641.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27651.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27661.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27671.51Skamil}; 27681.51Skamil 27691.51Skamilstatic void 27701.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27711.1Skamil{ 27721.1Skamil struct msg_fds parent_tracer, parent_tracee; 27731.1Skamil const int exitval_tracee = 5; 27741.1Skamil const int exitval_tracer = 10; 27751.1Skamil pid_t parent, tracee, tracer, wpid; 27761.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27771.1Skamil#if defined(TWAIT_HAVE_STATUS) 27781.1Skamil int status; 27791.1Skamil#endif 27801.51Skamil /* sysctl(3) - kinfo_proc2 */ 27811.51Skamil int name[CTL_MAXNAME]; 27821.51Skamil struct kinfo_proc2 kp; 27831.51Skamil size_t len = sizeof(kp); 27841.51Skamil unsigned int namelen; 27851.51Skamil 27861.51Skamil /* procfs - status */ 27871.51Skamil FILE *fp; 27881.51Skamil struct stat st; 27891.51Skamil const char *fname = "/proc/curproc/status"; 27901.51Skamil char s_executable[MAXPATHLEN]; 27911.51Skamil int s_pid, s_ppid; 27921.51Skamil int rv; 27931.51Skamil 27941.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27951.61Skre SYSCALL_REQUIRE( 27961.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27971.61Skre if (rv != 0) 27981.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27991.51Skamil } 28001.1Skamil 28011.13Schristos DPRINTF("Spawn tracee\n"); 28021.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 28031.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 28041.1Skamil tracee = atf_utils_fork(); 28051.1Skamil if (tracee == 0) { 28061.1Skamil parent = getppid(); 28071.1Skamil 28081.1Skamil /* Emit message to the parent */ 28091.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 28101.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 28111.1Skamil 28121.51Skamil switch (type) { 28131.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 28141.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 28151.51Skamil break; 28161.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 28171.51Skamil namelen = 0; 28181.51Skamil name[namelen++] = CTL_KERN; 28191.51Skamil name[namelen++] = KERN_PROC2; 28201.51Skamil name[namelen++] = KERN_PROC_PID; 28211.51Skamil name[namelen++] = getpid(); 28221.51Skamil name[namelen++] = len; 28231.51Skamil name[namelen++] = 1; 28241.51Skamil 28251.61Skre FORKEE_ASSERT_EQ( 28261.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28271.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28281.51Skamil break; 28291.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28301.51Skamil /* 28311.51Skamil * Format: 28321.51Skamil * EXECUTABLE PID PPID ... 28331.51Skamil */ 28341.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28351.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28361.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28371.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28381.51Skamil break; 28391.51Skamil } 28401.1Skamil 28411.1Skamil _exit(exitval_tracee); 28421.1Skamil } 28431.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28441.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28451.1Skamil 28461.13Schristos DPRINTF("Spawn debugger\n"); 28471.1Skamil tracer = atf_utils_fork(); 28481.1Skamil if (tracer == 0) { 28491.1Skamil /* No IPC to communicate with the child */ 28501.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28511.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28521.1Skamil 28531.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28541.1Skamil FORKEE_REQUIRE_SUCCESS( 28551.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28561.1Skamil 28571.1Skamil forkee_status_stopped(status, SIGSTOP); 28581.1Skamil 28591.1Skamil /* Resume tracee with PT_CONTINUE */ 28601.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28611.1Skamil 28621.1Skamil /* Inform parent that tracer has attached to tracee */ 28631.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28641.1Skamil 28651.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28661.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28671.1Skamil 28681.1Skamil /* Wait for tracee and assert that it exited */ 28691.1Skamil FORKEE_REQUIRE_SUCCESS( 28701.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28711.1Skamil 28721.1Skamil forkee_status_exited(status, exitval_tracee); 28731.1Skamil 28741.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28751.1Skamil _exit(exitval_tracer); 28761.1Skamil } 28771.1Skamil 28781.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28791.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28801.1Skamil 28811.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28821.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28831.1Skamil 28841.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28851.1Skamil await_zombie(tracee); 28861.1Skamil 28871.13Schristos DPRINTF("Assert that there is no status about tracee - " 28881.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28891.1Skamil TWAIT_REQUIRE_SUCCESS( 28901.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28911.1Skamil 28921.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28931.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28941.1Skamil 28951.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28971.1Skamil tracer); 28981.1Skamil 28991.1Skamil validate_status_exited(status, exitval_tracer); 29001.1Skamil 29011.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 29021.1Skamil TWAIT_FNAME); 29031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 29041.1Skamil tracee); 29051.1Skamil 29061.1Skamil validate_status_exited(status, exitval_tracee); 29071.1Skamil 29081.1Skamil msg_close(&parent_tracer); 29091.1Skamil msg_close(&parent_tracee); 29101.1Skamil} 29111.1Skamil 29121.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 29131.61SkreATF_TC(test); \ 29141.61SkreATF_TC_HEAD(test, tc) \ 29151.61Skre{ \ 29161.61Skre atf_tc_set_md_var(tc, "descr", \ 29171.61Skre "Assert that tracee sees its original parent when being traced " \ 29181.61Skre "(check " descr ")"); \ 29191.61Skre} \ 29201.61Skre \ 29211.61SkreATF_TC_BODY(test, tc) \ 29221.61Skre{ \ 29231.61Skre \ 29241.61Skre tracee_sees_its_original_parent(type); \ 29251.1Skamil} 29261.1Skamil 29271.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29281.51Skamil tracee_sees_its_original_parent_getppid, 29291.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29301.51Skamil "getppid(2)"); 29311.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29321.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29331.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29341.51Skamil "sysctl(3) and kinfo_proc2"); 29351.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29361.51Skamil tracee_sees_its_original_parent_procfs_status, 29371.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29381.51Skamil "the status file in procfs"); 29391.1Skamil#endif 29401.1Skamil 29411.51Skamil/// ---------------------------------------------------------------------------- 29421.1Skamil 29431.53Skamilstatic void 29441.53Skamileventmask_preserved(int event) 29451.1Skamil{ 29461.1Skamil const int exitval = 5; 29471.1Skamil const int sigval = SIGSTOP; 29481.1Skamil pid_t child, wpid; 29491.1Skamil#if defined(TWAIT_HAVE_STATUS) 29501.1Skamil int status; 29511.1Skamil#endif 29521.1Skamil ptrace_event_t set_event, get_event; 29531.1Skamil const int len = sizeof(ptrace_event_t); 29541.1Skamil 29551.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29561.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29571.1Skamil if (child == 0) { 29581.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29591.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29601.1Skamil 29611.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29621.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29631.1Skamil 29641.13Schristos DPRINTF("Before exiting of the child process\n"); 29651.1Skamil _exit(exitval); 29661.1Skamil } 29671.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29681.1Skamil 29691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29711.1Skamil 29721.1Skamil validate_status_stopped(status, sigval); 29731.1Skamil 29741.53Skamil set_event.pe_set_event = event; 29751.61Skre SYSCALL_REQUIRE( 29761.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29771.61Skre SYSCALL_REQUIRE( 29781.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29791.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29801.125Skamil get_event.pe_set_event); 29811.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29821.1Skamil 29831.13Schristos DPRINTF("Before resuming the child process where it left off and " 29841.1Skamil "without signal to be sent\n"); 29851.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29861.1Skamil 29871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29891.1Skamil 29901.1Skamil validate_status_exited(status, exitval); 29911.1Skamil 29921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29931.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29941.1Skamil} 29951.1Skamil 29961.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29971.61SkreATF_TC(test); \ 29981.61SkreATF_TC_HEAD(test, tc) \ 29991.61Skre{ \ 30001.61Skre atf_tc_set_md_var(tc, "descr", \ 30011.61Skre "Verify that eventmask " #event " is preserved"); \ 30021.61Skre} \ 30031.61Skre \ 30041.61SkreATF_TC_BODY(test, tc) \ 30051.61Skre{ \ 30061.61Skre \ 30071.61Skre eventmask_preserved(event); \ 30081.1Skamil} 30091.1Skamil 30101.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 30111.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 30121.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 30131.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 30141.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 30151.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 30161.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 30171.1Skamil 30181.53Skamil/// ---------------------------------------------------------------------------- 30191.1Skamil 30201.28Skamilstatic void 30211.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 30221.105Skamil bool trackvforkdone) 30231.1Skamil{ 30241.1Skamil const int exitval = 5; 30251.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30261.1Skamil const int sigval = SIGSTOP; 30271.31Skamil pid_t child, child2 = 0, wpid; 30281.1Skamil#if defined(TWAIT_HAVE_STATUS) 30291.1Skamil int status; 30301.1Skamil#endif 30311.1Skamil ptrace_state_t state; 30321.1Skamil const int slen = sizeof(state); 30331.1Skamil ptrace_event_t event; 30341.1Skamil const int elen = sizeof(event); 30351.1Skamil 30361.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30371.124Skamil 30381.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30391.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30401.1Skamil if (child == 0) { 30411.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30421.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30431.1Skamil 30441.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30451.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30461.1Skamil 30471.125Skamil if (strcmp(fn, "spawn") == 0) { 30481.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30491.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30501.125Skamil } else { 30511.125Skamil if (strcmp(fn, "fork") == 0) { 30521.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30531.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30541.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30551.125Skamil } 30561.1Skamil 30571.124Skamil if (child2 == 0) 30581.124Skamil _exit(exitval2); 30591.124Skamil } 30601.1Skamil FORKEE_REQUIRE_SUCCESS 30611.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30621.1Skamil 30631.1Skamil forkee_status_exited(status, exitval2); 30641.1Skamil 30651.13Schristos DPRINTF("Before exiting of the child process\n"); 30661.1Skamil _exit(exitval); 30671.1Skamil } 30681.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30691.1Skamil 30701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30721.1Skamil 30731.1Skamil validate_status_stopped(status, sigval); 30741.1Skamil 30751.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30761.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30771.61Skre trackfork ? "|PTRACE_FORK" : "", 30781.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30791.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30801.30Skamil event.pe_set_event = 0; 30811.125Skamil if (trackspawn) 30821.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30831.30Skamil if (trackfork) 30841.30Skamil event.pe_set_event |= PTRACE_FORK; 30851.30Skamil if (trackvfork) 30861.30Skamil event.pe_set_event |= PTRACE_VFORK; 30871.30Skamil if (trackvforkdone) 30881.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30891.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30901.1Skamil 30911.13Schristos DPRINTF("Before resuming the child process where it left off and " 30921.1Skamil "without signal to be sent\n"); 30931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30941.1Skamil 30951.29Skamil#if defined(TWAIT_HAVE_PID) 30961.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 30971.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 30981.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 30991.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31001.61Skre child); 31011.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 31021.61Skre child); 31031.1Skamil 31041.29Skamil validate_status_stopped(status, SIGTRAP); 31051.1Skamil 31061.61Skre SYSCALL_REQUIRE( 31071.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31081.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31091.125Skamil ATF_REQUIRE_EQ( 31101.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31111.125Skamil PTRACE_POSIX_SPAWN); 31121.125Skamil } 31131.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31141.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31151.30Skamil PTRACE_FORK); 31161.30Skamil } 31171.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31181.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31191.30Skamil PTRACE_VFORK); 31201.30Skamil } 31211.29Skamil 31221.29Skamil child2 = state.pe_other_pid; 31231.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31241.29Skamil 31251.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31261.61Skre "%d\n", TWAIT_FNAME, child2, child); 31271.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31281.29Skamil child2); 31291.1Skamil 31301.29Skamil validate_status_stopped(status, SIGTRAP); 31311.1Skamil 31321.61Skre SYSCALL_REQUIRE( 31331.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31341.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31351.125Skamil ATF_REQUIRE_EQ( 31361.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31371.125Skamil PTRACE_POSIX_SPAWN); 31381.125Skamil } 31391.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31401.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31411.30Skamil PTRACE_FORK); 31421.30Skamil } 31431.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31441.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31451.30Skamil PTRACE_VFORK); 31461.30Skamil } 31471.30Skamil 31481.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31491.29Skamil 31501.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31511.29Skamil "and without signal to be sent\n"); 31521.61Skre SYSCALL_REQUIRE( 31531.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31541.29Skamil 31551.29Skamil DPRINTF("Before resuming the child process where it left off " 31561.61Skre "and without signal to be sent\n"); 31571.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31581.30Skamil } 31591.30Skamil#endif 31601.30Skamil 31611.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31621.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31631.61Skre child); 31641.61Skre TWAIT_REQUIRE_SUCCESS( 31651.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31661.30Skamil 31671.30Skamil validate_status_stopped(status, SIGTRAP); 31681.30Skamil 31691.61Skre SYSCALL_REQUIRE( 31701.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31711.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31721.30Skamil 31731.30Skamil child2 = state.pe_other_pid; 31741.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31751.61Skre child2); 31761.30Skamil 31771.30Skamil DPRINTF("Before resuming the child process where it left off " 31781.61Skre "and without signal to be sent\n"); 31791.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31801.30Skamil } 31811.29Skamil 31821.30Skamil#if defined(TWAIT_HAVE_PID) 31831.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31841.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31851.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31861.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31871.61Skre "\n", TWAIT_FNAME); 31881.61Skre TWAIT_REQUIRE_SUCCESS( 31891.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31901.29Skamil 31911.29Skamil validate_status_exited(status, exitval2); 31921.29Skamil 31931.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31941.61Skre "process\n", TWAIT_FNAME); 31951.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31961.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31971.29Skamil } 31981.29Skamil#endif 31991.1Skamil 32001.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 32011.1Skamil "SIGCHLD\n", TWAIT_FNAME); 32021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32031.1Skamil 32041.1Skamil validate_status_stopped(status, SIGCHLD); 32051.1Skamil 32061.13Schristos DPRINTF("Before resuming the child process where it left off and " 32071.1Skamil "without signal to be sent\n"); 32081.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 32091.1Skamil 32101.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 32111.1Skamil TWAIT_FNAME); 32121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32131.1Skamil 32141.1Skamil validate_status_exited(status, exitval); 32151.1Skamil 32161.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 32171.1Skamil TWAIT_FNAME); 32181.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32191.1Skamil} 32201.28Skamil 32211.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 32221.61SkreATF_TC(name); \ 32231.61SkreATF_TC_HEAD(name, tc) \ 32241.61Skre{ \ 32251.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32261.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32271.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32281.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32291.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32301.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32311.61Skre} \ 32321.61Skre \ 32331.61SkreATF_TC_BODY(name, tc) \ 32341.61Skre{ \ 32351.61Skre \ 32361.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32371.32Skamil} 32381.32Skamil 32391.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32401.31Skamil#if defined(TWAIT_HAVE_PID) 32411.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32421.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32431.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32441.31Skamil#endif 32451.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32461.31Skamil#if defined(TWAIT_HAVE_PID) 32471.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32481.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32491.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32501.125Skamil#endif 32511.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32521.125Skamil#if defined(TWAIT_HAVE_PID) 32531.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32541.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32551.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32561.125Skamil#endif 32571.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32581.125Skamil#if defined(TWAIT_HAVE_PID) 32591.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32601.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32611.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32621.31Skamil#endif 32631.1Skamil 32641.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32651.31Skamil#if defined(TWAIT_HAVE_PID) 32661.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32671.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32681.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32691.31Skamil#endif 32701.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32711.31Skamil#if defined(TWAIT_HAVE_PID) 32721.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32731.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32741.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32751.31Skamil#endif 32761.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32771.125Skamil#if defined(TWAIT_HAVE_PID) 32781.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32791.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32801.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32811.110Skamil#endif 32821.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32831.124Skamil#if defined(TWAIT_HAVE_PID) 32841.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32851.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32861.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32871.124Skamil#endif 32881.125Skamil 32891.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32901.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32911.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32921.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32931.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32941.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32951.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32961.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 32971.124Skamil#if defined(TWAIT_HAVE_PID) 32981.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 32991.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 33001.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 33011.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 33021.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 33031.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 33041.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 33051.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 33061.124Skamil#endif 33071.124Skamil 33081.54Skamil/// ---------------------------------------------------------------------------- 33091.31Skamil 33101.116Skamil#if defined(TWAIT_HAVE_PID) 33111.116Skamilstatic void 33121.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 33131.116Skamil{ 33141.116Skamil const int exitval = 5; 33151.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 33161.116Skamil const int sigval = SIGSTOP; 33171.116Skamil pid_t child, child2 = 0, wpid; 33181.116Skamil#if defined(TWAIT_HAVE_STATUS) 33191.116Skamil int status; 33201.116Skamil#endif 33211.116Skamil ptrace_state_t state; 33221.116Skamil const int slen = sizeof(state); 33231.116Skamil ptrace_event_t event; 33241.116Skamil const int elen = sizeof(event); 33251.116Skamil 33261.116Skamil int op; 33271.116Skamil 33281.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33291.116Skamil 33301.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33311.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 33321.116Skamil if (child == 0) { 33331.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33341.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33351.116Skamil 33361.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33371.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 33381.116Skamil 33391.126Skamil if (strcmp(fn, "spawn") == 0) { 33401.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 33411.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 33421.126Skamil } else { 33431.126Skamil if (strcmp(fn, "fork") == 0) { 33441.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 33451.126Skamil } else { 33461.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 33471.126Skamil } 33481.116Skamil 33491.126Skamil if (child2 == 0) 33501.126Skamil _exit(exitval2); 33511.126Skamil } 33521.116Skamil 33531.116Skamil FORKEE_REQUIRE_SUCCESS 33541.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33551.116Skamil 33561.116Skamil forkee_status_exited(status, exitval2); 33571.116Skamil 33581.116Skamil DPRINTF("Before exiting of the child process\n"); 33591.116Skamil _exit(exitval); 33601.116Skamil } 33611.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33621.116Skamil 33631.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33641.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33651.116Skamil 33661.116Skamil validate_status_stopped(status, sigval); 33671.116Skamil 33681.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 33691.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 33701.126Skamil | PTRACE_VFORK_DONE; 33711.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 33721.116Skamil 33731.116Skamil DPRINTF("Before resuming the child process where it left off and " 33741.116Skamil "without signal to be sent\n"); 33751.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 33761.116Skamil 33771.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 33781.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33791.116Skamil 33801.116Skamil validate_status_stopped(status, SIGTRAP); 33811.116Skamil 33821.116Skamil SYSCALL_REQUIRE( 33831.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33841.126Skamil 33851.126Skamil if (strcmp(fn, "spawn") == 0) 33861.126Skamil op = PTRACE_POSIX_SPAWN; 33871.126Skamil else if (strcmp(fn, "fork") == 0) 33881.126Skamil op = PTRACE_FORK; 33891.126Skamil else 33901.126Skamil op = PTRACE_VFORK; 33911.126Skamil 33921.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33931.116Skamil 33941.116Skamil child2 = state.pe_other_pid; 33951.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 33961.116Skamil 33971.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 33981.126Skamil strcmp(fn, "vfork") == 0) 33991.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34001.116Skamil else 34011.116Skamil op = PT_CONTINUE; 34021.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34031.116Skamil 34041.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 34051.116Skamil TWAIT_FNAME, child2, child); 34061.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34071.116Skamil 34081.116Skamil validate_status_stopped(status, SIGTRAP); 34091.116Skamil 34101.116Skamil SYSCALL_REQUIRE( 34111.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 34121.126Skamil if (strcmp(fn, "spawn") == 0) 34131.126Skamil op = PTRACE_POSIX_SPAWN; 34141.126Skamil else if (strcmp(fn, "fork") == 0) 34151.126Skamil op = PTRACE_FORK; 34161.126Skamil else 34171.126Skamil op = PTRACE_VFORK; 34181.126Skamil 34191.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 34201.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 34211.116Skamil 34221.116Skamil DPRINTF("Before resuming the forkee process where it left off " 34231.116Skamil "and without signal to be sent\n"); 34241.116Skamil SYSCALL_REQUIRE( 34251.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 34261.116Skamil 34271.126Skamil if (strcmp(fn, "vforkdone") == 0) { 34281.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 34291.116Skamil child); 34301.116Skamil TWAIT_REQUIRE_SUCCESS( 34311.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 34321.116Skamil 34331.116Skamil validate_status_stopped(status, SIGTRAP); 34341.116Skamil 34351.116Skamil SYSCALL_REQUIRE( 34361.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 34371.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 34381.116Skamil 34391.116Skamil child2 = state.pe_other_pid; 34401.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 34411.116Skamil child2); 34421.116Skamil 34431.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34441.116Skamil DPRINTF("Before resuming the child process where it left off " 34451.116Skamil "and without signal to be sent\n"); 34461.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34471.116Skamil } 34481.116Skamil 34491.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34501.116Skamil TWAIT_FNAME); 34511.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34521.116Skamil 34531.116Skamil validate_status_exited(status, exitval2); 34541.116Skamil 34551.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 34561.116Skamil TWAIT_FNAME); 34571.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 34581.116Skamil 34591.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34601.116Skamil TWAIT_FNAME); 34611.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34621.116Skamil 34631.116Skamil if (kill_process) { 34641.116Skamil validate_status_signaled(status, SIGKILL, 0); 34651.116Skamil } else { 34661.116Skamil validate_status_exited(status, exitval); 34671.116Skamil } 34681.116Skamil 34691.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34701.116Skamil TWAIT_FNAME); 34711.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34721.116Skamil} 34731.116Skamil 34741.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 34751.116SkamilATF_TC(name); \ 34761.116SkamilATF_TC_HEAD(name, tc) \ 34771.116Skamil{ \ 34781.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 34791.126Skamil kprocess ? "killed" : "detached"); \ 34801.116Skamil} \ 34811.116Skamil \ 34821.116SkamilATF_TC_BODY(name, tc) \ 34831.116Skamil{ \ 34841.116Skamil \ 34851.126Skamil fork_detach_forker_body(event, kprocess); \ 34861.116Skamil} 34871.116Skamil 34881.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 34891.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 34901.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 34911.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 34921.126Skamil 34931.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 34941.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 34951.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 34961.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 34971.116Skamil#endif 34981.116Skamil 34991.116Skamil/// ---------------------------------------------------------------------------- 35001.116Skamil 35011.108Skamilstatic void 35021.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 35031.108Skamil{ 35041.108Skamil const int exitval = 5; 35051.108Skamil const int exitval2 = 15; 35061.108Skamil pid_t child, child2 = 0, wpid; 35071.108Skamil#if defined(TWAIT_HAVE_STATUS) 35081.108Skamil int status; 35091.108Skamil#endif 35101.108Skamil 35111.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 35121.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 35131.108Skamil if (child == 0) { 35141.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 35151.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 35161.108Skamil 35171.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 35181.108Skamil 35191.108Skamil if (child2 == 0) 35201.108Skamil _exit(exitval2); 35211.108Skamil 35221.108Skamil FORKEE_REQUIRE_SUCCESS 35231.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 35241.108Skamil 35251.108Skamil forkee_status_exited(status, exitval2); 35261.108Skamil 35271.108Skamil DPRINTF("Before exiting of the child process\n"); 35281.108Skamil _exit(exitval); 35291.108Skamil } 35301.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35311.108Skamil 35321.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 35331.108Skamil TWAIT_FNAME); 35341.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35351.108Skamil 35361.108Skamil validate_status_exited(status, exitval); 35371.108Skamil 35381.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 35391.108Skamil TWAIT_FNAME); 35401.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35411.108Skamil} 35421.108Skamil 35431.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 35441.108SkamilATF_TC(name); \ 35451.108SkamilATF_TC_HEAD(name, tc) \ 35461.108Skamil{ \ 35471.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 35481.108Skamil "called from vfork(2)ed child"); \ 35491.108Skamil} \ 35501.108Skamil \ 35511.108SkamilATF_TC_BODY(name, tc) \ 35521.108Skamil{ \ 35531.108Skamil \ 35541.108Skamil traceme_vfork_fork_body(fun); \ 35551.108Skamil} 35561.108Skamil 35571.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 35581.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 35591.108Skamil 35601.108Skamil/// ---------------------------------------------------------------------------- 35611.108Skamil 35621.54Skamilenum bytes_transfer_type { 35631.54Skamil BYTES_TRANSFER_DATA, 35641.54Skamil BYTES_TRANSFER_DATAIO, 35651.54Skamil BYTES_TRANSFER_TEXT, 35661.54Skamil BYTES_TRANSFER_TEXTIO, 35671.54Skamil BYTES_TRANSFER_AUXV 35681.54Skamil}; 35691.31Skamil 35701.54Skamilstatic int __used 35711.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 35721.54Skamil{ 35731.54Skamil int e, f, g, h; 35741.1Skamil 35751.54Skamil a *= 4; 35761.54Skamil b += 3; 35771.54Skamil c -= 2; 35781.54Skamil d /= 1; 35791.1Skamil 35801.54Skamil e = strtol("10", NULL, 10); 35811.54Skamil f = strtol("20", NULL, 10); 35821.54Skamil g = strtol("30", NULL, 10); 35831.54Skamil h = strtol("40", NULL, 10); 35841.1Skamil 35851.54Skamil return (a + b * c - d) + (e * f - g / h); 35861.1Skamil} 35871.1Skamil 35881.54Skamilstatic void 35891.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 35901.1Skamil{ 35911.1Skamil const int exitval = 5; 35921.1Skamil const int sigval = SIGSTOP; 35931.1Skamil pid_t child, wpid; 35941.54Skamil bool skip = false; 35951.1Skamil 35961.54Skamil int lookup_me = 0; 35971.54Skamil uint8_t lookup_me8 = 0; 35981.54Skamil uint16_t lookup_me16 = 0; 35991.54Skamil uint32_t lookup_me32 = 0; 36001.54Skamil uint64_t lookup_me64 = 0; 36011.1Skamil 36021.54Skamil int magic = 0x13579246; 36031.54Skamil uint8_t magic8 = 0xab; 36041.54Skamil uint16_t magic16 = 0x1234; 36051.54Skamil uint32_t magic32 = 0x98765432; 36061.54Skamil uint64_t magic64 = 0xabcdef0123456789; 36071.1Skamil 36081.54Skamil struct ptrace_io_desc io; 36091.1Skamil#if defined(TWAIT_HAVE_STATUS) 36101.1Skamil int status; 36111.1Skamil#endif 36121.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 36131.60Skre AuxInfo ai[513], *aip; 36141.55Schristos 36151.55Schristos ATF_REQUIRE(size < sizeof(ai)); 36161.1Skamil 36171.54Skamil /* Prepare variables for .TEXT transfers */ 36181.54Skamil switch (type) { 36191.54Skamil case BYTES_TRANSFER_TEXT: 36201.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 36211.54Skamil break; 36221.54Skamil case BYTES_TRANSFER_TEXTIO: 36231.54Skamil switch (size) { 36241.54Skamil case 8: 36251.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 36261.54Skamil break; 36271.54Skamil case 16: 36281.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 36291.54Skamil break; 36301.54Skamil case 32: 36311.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 36321.54Skamil break; 36331.54Skamil case 64: 36341.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 36351.54Skamil break; 36361.54Skamil } 36371.54Skamil break; 36381.54Skamil default: 36391.54Skamil break; 36401.54Skamil } 36411.1Skamil 36421.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 36431.54Skamil switch (type) { 36441.54Skamil case BYTES_TRANSFER_TEXTIO: 36451.54Skamil case BYTES_TRANSFER_DATAIO: 36461.54Skamil io.piod_op = operation; 36471.54Skamil switch (size) { 36481.54Skamil case 8: 36491.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36501.54Skamil (void *)bytes_transfer_dummy : 36511.54Skamil &lookup_me8; 36521.54Skamil io.piod_addr = &lookup_me8; 36531.54Skamil io.piod_len = sizeof(lookup_me8); 36541.54Skamil break; 36551.54Skamil case 16: 36561.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36571.54Skamil (void *)bytes_transfer_dummy : 36581.54Skamil &lookup_me16; 36591.54Skamil io.piod_addr = &lookup_me16; 36601.54Skamil io.piod_len = sizeof(lookup_me16); 36611.54Skamil break; 36621.54Skamil case 32: 36631.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36641.54Skamil (void *)bytes_transfer_dummy : 36651.54Skamil &lookup_me32; 36661.54Skamil io.piod_addr = &lookup_me32; 36671.54Skamil io.piod_len = sizeof(lookup_me32); 36681.54Skamil break; 36691.54Skamil case 64: 36701.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36711.54Skamil (void *)bytes_transfer_dummy : 36721.54Skamil &lookup_me64; 36731.54Skamil io.piod_addr = &lookup_me64; 36741.54Skamil io.piod_len = sizeof(lookup_me64); 36751.54Skamil break; 36761.54Skamil default: 36771.54Skamil break; 36781.54Skamil } 36791.54Skamil break; 36801.54Skamil case BYTES_TRANSFER_AUXV: 36811.54Skamil io.piod_op = operation; 36821.54Skamil io.piod_offs = 0; 36831.54Skamil io.piod_addr = ai; 36841.54Skamil io.piod_len = size; 36851.54Skamil break; 36861.54Skamil default: 36871.54Skamil break; 36881.1Skamil } 36891.1Skamil 36901.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36911.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36921.1Skamil if (child == 0) { 36931.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36941.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36951.1Skamil 36961.54Skamil switch (type) { 36971.54Skamil case BYTES_TRANSFER_DATA: 36981.54Skamil switch (operation) { 36991.54Skamil case PT_READ_D: 37001.54Skamil case PT_READ_I: 37011.54Skamil lookup_me = magic; 37021.54Skamil break; 37031.54Skamil default: 37041.54Skamil break; 37051.54Skamil } 37061.54Skamil break; 37071.54Skamil case BYTES_TRANSFER_DATAIO: 37081.54Skamil switch (operation) { 37091.54Skamil case PIOD_READ_D: 37101.54Skamil case PIOD_READ_I: 37111.54Skamil switch (size) { 37121.54Skamil case 8: 37131.54Skamil lookup_me8 = magic8; 37141.54Skamil break; 37151.54Skamil case 16: 37161.54Skamil lookup_me16 = magic16; 37171.54Skamil break; 37181.54Skamil case 32: 37191.54Skamil lookup_me32 = magic32; 37201.54Skamil break; 37211.54Skamil case 64: 37221.54Skamil lookup_me64 = magic64; 37231.54Skamil break; 37241.54Skamil default: 37251.54Skamil break; 37261.54Skamil } 37271.54Skamil break; 37281.54Skamil default: 37291.54Skamil break; 37301.54Skamil } 37311.54Skamil default: 37321.54Skamil break; 37331.54Skamil } 37341.54Skamil 37351.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37361.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37371.1Skamil 37381.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 37391.54Skamil switch (type) { 37401.54Skamil case BYTES_TRANSFER_DATA: 37411.54Skamil switch (operation) { 37421.54Skamil case PT_WRITE_D: 37431.54Skamil case PT_WRITE_I: 37441.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 37451.54Skamil break; 37461.54Skamil default: 37471.54Skamil break; 37481.54Skamil } 37491.54Skamil break; 37501.54Skamil case BYTES_TRANSFER_DATAIO: 37511.54Skamil switch (operation) { 37521.54Skamil case PIOD_WRITE_D: 37531.54Skamil case PIOD_WRITE_I: 37541.54Skamil switch (size) { 37551.54Skamil case 8: 37561.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 37571.54Skamil break; 37581.54Skamil case 16: 37591.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 37601.54Skamil break; 37611.54Skamil case 32: 37621.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 37631.54Skamil break; 37641.54Skamil case 64: 37651.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 37661.54Skamil break; 37671.54Skamil default: 37681.54Skamil break; 37691.54Skamil } 37701.54Skamil break; 37711.54Skamil default: 37721.54Skamil break; 37731.54Skamil } 37741.54Skamil break; 37751.54Skamil case BYTES_TRANSFER_TEXT: 37761.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 37771.54Skamil sizeof(magic)) == 0); 37781.54Skamil break; 37791.54Skamil case BYTES_TRANSFER_TEXTIO: 37801.54Skamil switch (size) { 37811.54Skamil case 8: 37821.54Skamil FORKEE_ASSERT(memcmp(&magic8, 37831.54Skamil bytes_transfer_dummy, 37841.54Skamil sizeof(magic8)) == 0); 37851.54Skamil break; 37861.54Skamil case 16: 37871.54Skamil FORKEE_ASSERT(memcmp(&magic16, 37881.54Skamil bytes_transfer_dummy, 37891.54Skamil sizeof(magic16)) == 0); 37901.54Skamil break; 37911.54Skamil case 32: 37921.54Skamil FORKEE_ASSERT(memcmp(&magic32, 37931.54Skamil bytes_transfer_dummy, 37941.54Skamil sizeof(magic32)) == 0); 37951.54Skamil break; 37961.54Skamil case 64: 37971.54Skamil FORKEE_ASSERT(memcmp(&magic64, 37981.54Skamil bytes_transfer_dummy, 37991.54Skamil sizeof(magic64)) == 0); 38001.54Skamil break; 38011.54Skamil } 38021.54Skamil break; 38031.54Skamil default: 38041.54Skamil break; 38051.54Skamil } 38061.54Skamil 38071.13Schristos DPRINTF("Before exiting of the child process\n"); 38081.1Skamil _exit(exitval); 38091.1Skamil } 38101.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 38111.1Skamil 38121.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38131.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38141.1Skamil 38151.1Skamil validate_status_stopped(status, sigval); 38161.1Skamil 38171.54Skamil /* Check PaX MPROTECT */ 38181.54Skamil if (!can_we_write_to_text(child)) { 38191.54Skamil switch (type) { 38201.54Skamil case BYTES_TRANSFER_TEXTIO: 38211.54Skamil switch (operation) { 38221.54Skamil case PIOD_WRITE_D: 38231.54Skamil case PIOD_WRITE_I: 38241.54Skamil skip = true; 38251.54Skamil break; 38261.54Skamil default: 38271.54Skamil break; 38281.54Skamil } 38291.54Skamil break; 38301.54Skamil case BYTES_TRANSFER_TEXT: 38311.54Skamil switch (operation) { 38321.54Skamil case PT_WRITE_D: 38331.54Skamil case PT_WRITE_I: 38341.54Skamil skip = true; 38351.54Skamil break; 38361.54Skamil default: 38371.54Skamil break; 38381.54Skamil } 38391.54Skamil break; 38401.54Skamil default: 38411.54Skamil break; 38421.54Skamil } 38431.54Skamil } 38441.1Skamil 38451.54Skamil /* Bailout cleanly killing the child process */ 38461.54Skamil if (skip) { 38471.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 38481.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38491.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38501.54Skamil child); 38511.1Skamil 38521.54Skamil validate_status_signaled(status, SIGKILL, 0); 38531.1Skamil 38541.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 38551.54Skamil } 38561.1Skamil 38571.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 38581.54Skamil "parent=%d\n", child, getpid()); 38591.1Skamil 38601.54Skamil switch (type) { 38611.54Skamil case BYTES_TRANSFER_TEXTIO: 38621.54Skamil case BYTES_TRANSFER_DATAIO: 38631.54Skamil case BYTES_TRANSFER_AUXV: 38641.54Skamil switch (operation) { 38651.54Skamil case PIOD_WRITE_D: 38661.54Skamil case PIOD_WRITE_I: 38671.54Skamil switch (size) { 38681.54Skamil case 8: 38691.54Skamil lookup_me8 = magic8; 38701.54Skamil break; 38711.54Skamil case 16: 38721.54Skamil lookup_me16 = magic16; 38731.54Skamil break; 38741.54Skamil case 32: 38751.54Skamil lookup_me32 = magic32; 38761.54Skamil break; 38771.54Skamil case 64: 38781.54Skamil lookup_me64 = magic64; 38791.54Skamil break; 38801.54Skamil default: 38811.54Skamil break; 38821.54Skamil } 38831.54Skamil break; 38841.54Skamil default: 38851.54Skamil break; 38861.54Skamil } 38871.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 38881.54Skamil switch (operation) { 38891.54Skamil case PIOD_READ_D: 38901.54Skamil case PIOD_READ_I: 38911.54Skamil switch (size) { 38921.54Skamil case 8: 38931.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 38941.54Skamil break; 38951.54Skamil case 16: 38961.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 38971.54Skamil break; 38981.54Skamil case 32: 38991.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 39001.54Skamil break; 39011.54Skamil case 64: 39021.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 39031.54Skamil break; 39041.54Skamil default: 39051.54Skamil break; 39061.54Skamil } 39071.54Skamil break; 39081.54Skamil case PIOD_READ_AUXV: 39091.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 39101.54Skamil io.piod_len); 39111.54Skamil ATF_REQUIRE(io.piod_len > 0); 39121.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 39131.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 39141.54Skamil (long long int)aip->a_type, 39151.54Skamil (long long int)aip->a_v); 39161.54Skamil break; 39171.54Skamil default: 39181.54Skamil break; 39191.54Skamil } 39201.54Skamil break; 39211.54Skamil case BYTES_TRANSFER_TEXT: 39221.54Skamil switch (operation) { 39231.54Skamil case PT_READ_D: 39241.54Skamil case PT_READ_I: 39251.54Skamil errno = 0; 39261.54Skamil lookup_me = ptrace(operation, child, 39271.54Skamil bytes_transfer_dummy, 0); 39281.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39291.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39301.54Skamil break; 39311.54Skamil case PT_WRITE_D: 39321.54Skamil case PT_WRITE_I: 39331.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 39341.54Skamil bytes_transfer_dummy, magic) 39351.54Skamil != -1); 39361.54Skamil break; 39371.54Skamil default: 39381.54Skamil break; 39391.54Skamil } 39401.54Skamil break; 39411.54Skamil case BYTES_TRANSFER_DATA: 39421.54Skamil switch (operation) { 39431.54Skamil case PT_READ_D: 39441.54Skamil case PT_READ_I: 39451.54Skamil errno = 0; 39461.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 39471.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39481.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39491.54Skamil break; 39501.54Skamil case PT_WRITE_D: 39511.54Skamil case PT_WRITE_I: 39521.54Skamil lookup_me = magic; 39531.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 39541.54Skamil magic) != -1); 39551.54Skamil break; 39561.54Skamil default: 39571.54Skamil break; 39581.54Skamil } 39591.54Skamil break; 39601.54Skamil default: 39611.54Skamil break; 39621.54Skamil } 39631.1Skamil 39641.13Schristos DPRINTF("Before resuming the child process where it left off and " 39651.1Skamil "without signal to be sent\n"); 39661.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39671.1Skamil 39681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39691.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39701.1Skamil 39711.1Skamil validate_status_exited(status, exitval); 39721.1Skamil 39731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39741.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39751.1Skamil} 39761.1Skamil 39771.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 39781.61SkreATF_TC(test); \ 39791.61SkreATF_TC_HEAD(test, tc) \ 39801.61Skre{ \ 39811.61Skre atf_tc_set_md_var(tc, "descr", \ 39821.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 39831.61Skre " of type " #type); \ 39841.61Skre} \ 39851.61Skre \ 39861.61SkreATF_TC_BODY(test, tc) \ 39871.61Skre{ \ 39881.61Skre \ 39891.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 39901.1Skamil} 39911.1Skamil 39921.54Skamil// DATA 39931.1Skamil 39941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 39951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 39961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 39971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 39981.54Skamil 39991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 40001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 40011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 40021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 40031.54Skamil 40041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 40051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 40061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 40071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 40081.54Skamil 40091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 40101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 40131.54Skamil 40141.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 40151.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 40161.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 40171.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 40181.54Skamil 40191.54Skamil// TEXT 40201.54Skamil 40211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 40221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 40231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 40241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 40251.54Skamil 40261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 40271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 40281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 40291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 40301.54Skamil 40311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 40321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 40331.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 40341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 40351.54Skamil 40361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 40371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 40381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 40391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 40401.54Skamil 40411.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 40421.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 40431.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 40441.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 40451.1Skamil 40461.54Skamil// AUXV 40471.1Skamil 40481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 40491.1Skamil 40501.54Skamil/// ---------------------------------------------------------------------------- 40511.1Skamil 40521.101Skamilstatic void 40531.101Skamilbytes_transfer_alignment(const char *operation) 40541.101Skamil{ 40551.101Skamil const int exitval = 5; 40561.101Skamil const int sigval = SIGSTOP; 40571.101Skamil pid_t child, wpid; 40581.101Skamil#if defined(TWAIT_HAVE_STATUS) 40591.101Skamil int status; 40601.101Skamil#endif 40611.101Skamil char *buffer; 40621.101Skamil int vector; 40631.101Skamil size_t len; 40641.101Skamil size_t i; 40651.101Skamil int op; 40661.101Skamil 40671.101Skamil struct ptrace_io_desc io; 40681.101Skamil struct ptrace_siginfo info; 40691.101Skamil 40701.101Skamil memset(&io, 0, sizeof(io)); 40711.101Skamil memset(&info, 0, sizeof(info)); 40721.101Skamil 40731.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 40741.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 40751.101Skamil buffer = malloc(len); 40761.101Skamil ATF_REQUIRE(buffer != NULL); 40771.101Skamil 40781.101Skamil /* Initialize the buffer with random data */ 40791.101Skamil for (i = 0; i < len; i++) 40801.101Skamil buffer[i] = i & 0xff; 40811.101Skamil 40821.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 40831.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 40841.101Skamil if (child == 0) { 40851.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40861.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40871.101Skamil 40881.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40891.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 40901.101Skamil 40911.101Skamil DPRINTF("Before exiting of the child process\n"); 40921.101Skamil _exit(exitval); 40931.101Skamil } 40941.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 40951.101Skamil 40961.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40971.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40981.101Skamil 40991.101Skamil validate_status_stopped(status, sigval); 41001.101Skamil 41011.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 41021.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 41031.101Skamil != -1); 41041.101Skamil 41051.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 41061.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 41071.101Skamil "si_errno=%#x\n", 41081.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 41091.101Skamil info.psi_siginfo.si_errno); 41101.101Skamil 41111.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 41121.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 41131.101Skamil 41141.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 41151.101Skamil strcmp(operation, "PT_READ_D") == 0) { 41161.101Skamil if (strcmp(operation, "PT_READ_I")) 41171.101Skamil op = PT_READ_I; 41181.101Skamil else 41191.101Skamil op = PT_READ_D; 41201.101Skamil 41211.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41221.101Skamil errno = 0; 41231.101Skamil vector = ptrace(op, child, buffer + i, 0); 41241.101Skamil ATF_REQUIRE_EQ(errno, 0); 41251.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41261.101Skamil } 41271.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41281.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41291.101Skamil if (strcmp(operation, "PT_WRITE_I")) 41301.101Skamil op = PT_WRITE_I; 41311.101Skamil else 41321.101Skamil op = PT_WRITE_D; 41331.101Skamil 41341.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41351.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 41361.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 41371.101Skamil != -1); 41381.101Skamil } 41391.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41401.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41411.101Skamil if (strcmp(operation, "PIOD_READ_I")) 41421.101Skamil op = PIOD_READ_I; 41431.101Skamil else 41441.101Skamil op = PIOD_READ_D; 41451.101Skamil 41461.101Skamil io.piod_op = op; 41471.101Skamil io.piod_addr = &vector; 41481.101Skamil io.piod_len = sizeof(int); 41491.101Skamil 41501.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41511.101Skamil io.piod_offs = buffer + i; 41521.101Skamil 41531.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41541.101Skamil != -1); 41551.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41561.101Skamil } 41571.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 41581.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 41591.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 41601.101Skamil op = PIOD_WRITE_I; 41611.101Skamil else 41621.101Skamil op = PIOD_WRITE_D; 41631.101Skamil 41641.101Skamil io.piod_op = op; 41651.101Skamil io.piod_addr = &vector; 41661.101Skamil io.piod_len = sizeof(int); 41671.101Skamil 41681.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41691.101Skamil io.piod_offs = buffer + i; 41701.101Skamil 41711.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41721.101Skamil != -1); 41731.101Skamil } 41741.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 41751.101Skamil io.piod_op = PIOD_READ_AUXV; 41761.101Skamil io.piod_addr = &vector; 41771.101Skamil io.piod_len = sizeof(int); 41781.101Skamil 41791.101Skamil errno = 0; 41801.101Skamil i = 0; 41811.101Skamil /* Read the whole AUXV vector, it has no clear length */ 41821.120Skamil while (io.piod_len > 0) { 41831.101Skamil io.piod_offs = (void *)(intptr_t)i; 41841.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41851.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 41861.101Skamil ++i; 41871.101Skamil } 41881.101Skamil } 41891.101Skamil 41901.101Skamil DPRINTF("Before resuming the child process where it left off " 41911.101Skamil "and without signal to be sent\n"); 41921.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41931.101Skamil 41941.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41951.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 41961.101Skamil child); 41971.101Skamil 41981.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41991.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 42001.101Skamil} 42011.101Skamil 42021.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 42031.101SkamilATF_TC(test); \ 42041.101SkamilATF_TC_HEAD(test, tc) \ 42051.101Skamil{ \ 42061.101Skamil atf_tc_set_md_var(tc, "descr", \ 42071.101Skamil "Verify bytes transfer for potentially misaligned " \ 42081.101Skamil "operation " operation); \ 42091.101Skamil} \ 42101.101Skamil \ 42111.101SkamilATF_TC_BODY(test, tc) \ 42121.101Skamil{ \ 42131.101Skamil \ 42141.101Skamil bytes_transfer_alignment(operation); \ 42151.101Skamil} 42161.101Skamil 42171.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 42181.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 42191.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 42201.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 42211.101Skamil 42221.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 42231.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 42241.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 42251.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 42261.101Skamil 42271.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 42281.101Skamil 42291.101Skamil/// ---------------------------------------------------------------------------- 42301.101Skamil 42311.115Skamilstatic void 42321.115Skamilbytes_transfer_eof(const char *operation) 42331.115Skamil{ 42341.115Skamil const int exitval = 5; 42351.115Skamil const int sigval = SIGSTOP; 42361.115Skamil pid_t child, wpid; 42371.115Skamil#if defined(TWAIT_HAVE_STATUS) 42381.115Skamil int status; 42391.115Skamil#endif 42401.115Skamil FILE *fp; 42411.115Skamil char *p; 42421.115Skamil int vector; 42431.115Skamil int op; 42441.115Skamil 42451.115Skamil struct ptrace_io_desc io; 42461.115Skamil struct ptrace_siginfo info; 42471.115Skamil 42481.115Skamil memset(&io, 0, sizeof(io)); 42491.115Skamil memset(&info, 0, sizeof(info)); 42501.115Skamil 42511.115Skamil vector = 0; 42521.115Skamil 42531.115Skamil fp = tmpfile(); 42541.115Skamil ATF_REQUIRE(fp != NULL); 42551.115Skamil 42561.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 42571.115Skamil ATF_REQUIRE(p != MAP_FAILED); 42581.115Skamil 42591.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42601.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42611.115Skamil if (child == 0) { 42621.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42631.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42641.115Skamil 42651.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42661.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 42671.115Skamil 42681.115Skamil DPRINTF("Before exiting of the child process\n"); 42691.115Skamil _exit(exitval); 42701.115Skamil } 42711.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42721.115Skamil 42731.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42741.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42751.115Skamil 42761.115Skamil validate_status_stopped(status, sigval); 42771.115Skamil 42781.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42791.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 42801.115Skamil != -1); 42811.115Skamil 42821.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42831.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42841.115Skamil "si_errno=%#x\n", 42851.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42861.115Skamil info.psi_siginfo.si_errno); 42871.115Skamil 42881.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42891.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42901.115Skamil 42911.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 42921.115Skamil strcmp(operation, "PT_READ_D") == 0) { 42931.115Skamil if (strcmp(operation, "PT_READ_I")) 42941.115Skamil op = PT_READ_I; 42951.115Skamil else 42961.115Skamil op = PT_READ_D; 42971.115Skamil 42981.115Skamil errno = 0; 42991.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 43001.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43011.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 43021.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 43031.115Skamil if (strcmp(operation, "PT_WRITE_I")) 43041.115Skamil op = PT_WRITE_I; 43051.115Skamil else 43061.115Skamil op = PT_WRITE_D; 43071.115Skamil 43081.115Skamil errno = 0; 43091.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 43101.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43111.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 43121.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 43131.115Skamil if (strcmp(operation, "PIOD_READ_I")) 43141.115Skamil op = PIOD_READ_I; 43151.115Skamil else 43161.115Skamil op = PIOD_READ_D; 43171.115Skamil 43181.115Skamil io.piod_op = op; 43191.115Skamil io.piod_addr = &vector; 43201.115Skamil io.piod_len = sizeof(int); 43211.115Skamil io.piod_offs = p; 43221.115Skamil 43231.115Skamil errno = 0; 43241.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43251.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43261.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 43271.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 43281.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 43291.115Skamil op = PIOD_WRITE_I; 43301.115Skamil else 43311.115Skamil op = PIOD_WRITE_D; 43321.115Skamil 43331.115Skamil io.piod_op = op; 43341.115Skamil io.piod_addr = &vector; 43351.115Skamil io.piod_len = sizeof(int); 43361.115Skamil io.piod_offs = p; 43371.115Skamil 43381.115Skamil errno = 0; 43391.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43401.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43411.115Skamil } 43421.115Skamil 43431.115Skamil DPRINTF("Before resuming the child process where it left off " 43441.115Skamil "and without signal to be sent\n"); 43451.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43461.115Skamil 43471.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43481.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43491.115Skamil child); 43501.115Skamil 43511.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43521.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43531.115Skamil} 43541.115Skamil 43551.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 43561.115SkamilATF_TC(test); \ 43571.115SkamilATF_TC_HEAD(test, tc) \ 43581.115Skamil{ \ 43591.115Skamil atf_tc_set_md_var(tc, "descr", \ 43601.115Skamil "Verify bytes EOF byte transfer for the " operation \ 43611.115Skamil " operation"); \ 43621.115Skamil} \ 43631.115Skamil \ 43641.115SkamilATF_TC_BODY(test, tc) \ 43651.115Skamil{ \ 43661.115Skamil \ 43671.115Skamil bytes_transfer_eof(operation); \ 43681.115Skamil} 43691.115Skamil 43701.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 43711.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 43721.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 43731.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 43741.115Skamil 43751.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 43761.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 43771.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 43781.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 43791.115Skamil 43801.115Skamil/// ---------------------------------------------------------------------------- 43811.115Skamil 43821.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 43831.72Skamilstatic void 43841.72Skamilaccess_regs(const char *regset, const char *aux) 43851.1Skamil{ 43861.1Skamil const int exitval = 5; 43871.1Skamil const int sigval = SIGSTOP; 43881.1Skamil pid_t child, wpid; 43891.1Skamil#if defined(TWAIT_HAVE_STATUS) 43901.1Skamil int status; 43911.1Skamil#endif 43921.72Skamil#if defined(HAVE_GPREGS) 43931.72Skamil struct reg gpr; 43941.76Sscole register_t rgstr; 43951.1Skamil#endif 43961.72Skamil#if defined(HAVE_FPREGS) 43971.72Skamil struct fpreg fpr; 43981.1Skamil#endif 43991.76Sscole 44001.72Skamil#if !defined(HAVE_GPREGS) 44011.72Skamil if (strcmp(regset, "regs") == 0) 44021.72Skamil atf_tc_fail("Impossible test scenario!"); 44031.1Skamil#endif 44041.1Skamil 44051.72Skamil#if !defined(HAVE_FPREGS) 44061.72Skamil if (strcmp(regset, "fpregs") == 0) 44071.72Skamil atf_tc_fail("Impossible test scenario!"); 44081.1Skamil#endif 44091.1Skamil 44101.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44111.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44121.1Skamil if (child == 0) { 44131.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44141.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44151.1Skamil 44161.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44171.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44181.1Skamil 44191.13Schristos DPRINTF("Before exiting of the child process\n"); 44201.1Skamil _exit(exitval); 44211.1Skamil } 44221.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44231.1Skamil 44241.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44261.1Skamil 44271.1Skamil validate_status_stopped(status, sigval); 44281.1Skamil 44291.1Skamil#if defined(HAVE_GPREGS) 44301.72Skamil if (strcmp(regset, "regs") == 0) { 44311.72Skamil DPRINTF("Call GETREGS for the child process\n"); 44321.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44331.72Skamil 44341.72Skamil if (strcmp(aux, "none") == 0) { 44351.72Skamil DPRINTF("Retrieved registers\n"); 44361.72Skamil } else if (strcmp(aux, "pc") == 0) { 44371.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44381.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44391.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 44401.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44411.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 44421.72Skamil } else if (strcmp(aux, "sp") == 0) { 44431.72Skamil rgstr = PTRACE_REG_SP(&gpr); 44441.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44451.72Skamil } else if (strcmp(aux, "intrv") == 0) { 44461.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 44471.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44481.72Skamil } else if (strcmp(aux, "setregs") == 0) { 44491.72Skamil DPRINTF("Call SETREGS for the child process\n"); 44501.72Skamil SYSCALL_REQUIRE( 44511.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44521.72Skamil } 44531.72Skamil } 44541.1Skamil#endif 44551.1Skamil 44561.72Skamil#if defined(HAVE_FPREGS) 44571.72Skamil if (strcmp(regset, "fpregs") == 0) { 44581.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 44591.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 44601.72Skamil 44611.72Skamil if (strcmp(aux, "getfpregs") == 0) { 44621.72Skamil DPRINTF("Retrieved FP registers\n"); 44631.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 44641.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 44651.72Skamil SYSCALL_REQUIRE( 44661.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 44671.72Skamil } 44681.1Skamil } 44691.1Skamil#endif 44701.1Skamil 44711.13Schristos DPRINTF("Before resuming the child process where it left off and " 44721.1Skamil "without signal to be sent\n"); 44731.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44741.1Skamil 44751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44771.1Skamil 44781.1Skamil validate_status_exited(status, exitval); 44791.1Skamil 44801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44811.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44821.1Skamil} 44831.1Skamil 44841.72Skamil#define ACCESS_REGS(test, regset, aux) \ 44851.72SkamilATF_TC(test); \ 44861.72SkamilATF_TC_HEAD(test, tc) \ 44871.72Skamil{ \ 44881.72Skamil atf_tc_set_md_var(tc, "descr", \ 44891.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 44901.72Skamil} \ 44911.72Skamil \ 44921.72SkamilATF_TC_BODY(test, tc) \ 44931.72Skamil{ \ 44941.72Skamil \ 44951.72Skamil access_regs(regset, aux); \ 44961.1Skamil} 44971.1Skamil#endif 44981.1Skamil 44991.72Skamil#if defined(HAVE_GPREGS) 45001.72SkamilACCESS_REGS(access_regs1, "regs", "none") 45011.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 45021.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 45031.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 45041.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 45051.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 45061.1Skamil#endif 45071.1Skamil#if defined(HAVE_FPREGS) 45081.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 45091.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 45101.1Skamil#endif 45111.1Skamil 45121.72Skamil/// ---------------------------------------------------------------------------- 45131.1Skamil 45141.1Skamil#if defined(PT_STEP) 45151.1Skamilstatic void 45161.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 45171.1Skamil{ 45181.1Skamil const int exitval = 5; 45191.1Skamil const int sigval = SIGSTOP; 45201.1Skamil pid_t child, wpid; 45211.1Skamil#if defined(TWAIT_HAVE_STATUS) 45221.1Skamil int status; 45231.1Skamil#endif 45241.1Skamil int happy; 45251.95Skamil struct sigaction sa; 45261.81Skamil struct ptrace_siginfo info; 45271.95Skamil sigset_t intmask; 45281.95Skamil struct kinfo_proc2 kp; 45291.95Skamil size_t len = sizeof(kp); 45301.95Skamil 45311.95Skamil int name[6]; 45321.95Skamil const size_t namelen = __arraycount(name); 45331.95Skamil ki_sigset_t kp_sigmask; 45341.95Skamil ki_sigset_t kp_sigignore; 45351.1Skamil 45361.1Skamil#if defined(__arm__) 45371.1Skamil /* PT_STEP not supported on arm 32-bit */ 45381.1Skamil atf_tc_expect_fail("PR kern/52119"); 45391.1Skamil#endif 45401.1Skamil 45411.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45421.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45431.1Skamil if (child == 0) { 45441.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45451.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45461.1Skamil 45471.95Skamil if (masked) { 45481.95Skamil sigemptyset(&intmask); 45491.95Skamil sigaddset(&intmask, SIGTRAP); 45501.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 45511.95Skamil } 45521.95Skamil 45531.95Skamil if (ignored) { 45541.95Skamil memset(&sa, 0, sizeof(sa)); 45551.95Skamil sa.sa_handler = SIG_IGN; 45561.95Skamil sigemptyset(&sa.sa_mask); 45571.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 45581.95Skamil } 45591.95Skamil 45601.1Skamil happy = check_happy(999); 45611.1Skamil 45621.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 45631.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 45641.1Skamil 45651.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 45661.1Skamil 45671.13Schristos DPRINTF("Before exiting of the child process\n"); 45681.1Skamil _exit(exitval); 45691.1Skamil } 45701.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45711.1Skamil 45721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45741.1Skamil 45751.1Skamil validate_status_stopped(status, sigval); 45761.1Skamil 45771.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45781.81Skamil SYSCALL_REQUIRE( 45791.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45801.81Skamil 45811.81Skamil DPRINTF("Before checking siginfo_t\n"); 45821.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45831.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 45841.81Skamil 45851.95Skamil name[0] = CTL_KERN, 45861.95Skamil name[1] = KERN_PROC2, 45871.95Skamil name[2] = KERN_PROC_PID; 45881.95Skamil name[3] = child; 45891.95Skamil name[4] = sizeof(kp); 45901.95Skamil name[5] = 1; 45911.95Skamil 45921.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45931.95Skamil 45941.95Skamil if (masked) 45951.95Skamil kp_sigmask = kp.p_sigmask; 45961.95Skamil 45971.95Skamil if (ignored) 45981.95Skamil kp_sigignore = kp.p_sigignore; 45991.95Skamil 46001.1Skamil while (N --> 0) { 46011.2Skamil if (setstep) { 46021.13Schristos DPRINTF("Before resuming the child process where it " 46031.2Skamil "left off and without signal to be sent (use " 46041.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 46051.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 46061.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 46071.2Skamil != -1); 46081.2Skamil } else { 46091.13Schristos DPRINTF("Before resuming the child process where it " 46101.2Skamil "left off and without signal to be sent (use " 46111.2Skamil "PT_STEP)\n"); 46121.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 46131.2Skamil != -1); 46141.2Skamil } 46151.1Skamil 46161.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46171.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 46181.1Skamil child); 46191.1Skamil 46201.1Skamil validate_status_stopped(status, SIGTRAP); 46211.2Skamil 46221.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46231.81Skamil SYSCALL_REQUIRE( 46241.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46251.81Skamil 46261.81Skamil DPRINTF("Before checking siginfo_t\n"); 46271.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46281.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 46291.81Skamil 46301.2Skamil if (setstep) { 46311.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 46321.2Skamil } 46331.95Skamil 46341.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46351.95Skamil 46361.95Skamil if (masked) { 46371.95Skamil DPRINTF("kp_sigmask=" 46381.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46391.95Skamil PRIx32 "\n", 46401.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 46411.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 46421.95Skamil 46431.95Skamil DPRINTF("kp.p_sigmask=" 46441.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46451.95Skamil PRIx32 "\n", 46461.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 46471.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 46481.95Skamil 46491.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 46501.95Skamil sizeof(kp_sigmask))); 46511.95Skamil } 46521.95Skamil 46531.95Skamil if (ignored) { 46541.95Skamil DPRINTF("kp_sigignore=" 46551.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46561.95Skamil PRIx32 "\n", 46571.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 46581.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 46591.95Skamil 46601.95Skamil DPRINTF("kp.p_sigignore=" 46611.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46621.95Skamil PRIx32 "\n", 46631.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 46641.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 46651.95Skamil 46661.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 46671.95Skamil sizeof(kp_sigignore))); 46681.95Skamil } 46691.1Skamil } 46701.1Skamil 46711.13Schristos DPRINTF("Before resuming the child process where it left off and " 46721.1Skamil "without signal to be sent\n"); 46731.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46741.1Skamil 46751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46771.1Skamil 46781.1Skamil validate_status_exited(status, exitval); 46791.1Skamil 46801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46811.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46821.1Skamil} 46831.1Skamil 46841.73Skamil#define PTRACE_STEP(test, N, setstep) \ 46851.73SkamilATF_TC(test); \ 46861.73SkamilATF_TC_HEAD(test, tc) \ 46871.73Skamil{ \ 46881.73Skamil atf_tc_set_md_var(tc, "descr", \ 46891.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 46901.73Skamil} \ 46911.73Skamil \ 46921.73SkamilATF_TC_BODY(test, tc) \ 46931.73Skamil{ \ 46941.73Skamil \ 46951.95Skamil ptrace_step(N, setstep, false, false); \ 46961.1Skamil} 46971.1Skamil 46981.73SkamilPTRACE_STEP(step1, 1, 0) 46991.73SkamilPTRACE_STEP(step2, 2, 0) 47001.73SkamilPTRACE_STEP(step3, 3, 0) 47011.73SkamilPTRACE_STEP(step4, 4, 0) 47021.73SkamilPTRACE_STEP(setstep1, 1, 1) 47031.73SkamilPTRACE_STEP(setstep2, 2, 1) 47041.73SkamilPTRACE_STEP(setstep3, 3, 1) 47051.73SkamilPTRACE_STEP(setstep4, 4, 1) 47061.95Skamil 47071.95SkamilATF_TC(step_signalmasked); 47081.95SkamilATF_TC_HEAD(step_signalmasked, tc) 47091.95Skamil{ 47101.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 47111.95Skamil} 47121.95Skamil 47131.95SkamilATF_TC_BODY(step_signalmasked, tc) 47141.95Skamil{ 47151.95Skamil 47161.95Skamil ptrace_step(1, 0, true, false); 47171.95Skamil} 47181.95Skamil 47191.95SkamilATF_TC(step_signalignored); 47201.95SkamilATF_TC_HEAD(step_signalignored, tc) 47211.95Skamil{ 47221.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 47231.95Skamil} 47241.95Skamil 47251.95SkamilATF_TC_BODY(step_signalignored, tc) 47261.95Skamil{ 47271.95Skamil 47281.95Skamil ptrace_step(1, 0, false, true); 47291.95Skamil} 47301.1Skamil#endif 47311.1Skamil 47321.73Skamil/// ---------------------------------------------------------------------------- 47331.1Skamil 47341.75Skamilstatic void 47351.75Skamilptrace_kill(const char *type) 47361.1Skamil{ 47371.75Skamil const int sigval = SIGSTOP; 47381.1Skamil pid_t child, wpid; 47391.1Skamil#if defined(TWAIT_HAVE_STATUS) 47401.1Skamil int status; 47411.1Skamil#endif 47421.1Skamil 47431.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47441.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47451.1Skamil if (child == 0) { 47461.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47471.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47481.1Skamil 47491.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47501.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47511.1Skamil 47521.1Skamil /* NOTREACHED */ 47531.1Skamil FORKEE_ASSERTX(0 && 47541.1Skamil "Child should be terminated by a signal from its parent"); 47551.1Skamil } 47561.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47571.1Skamil 47581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47601.1Skamil 47611.1Skamil validate_status_stopped(status, sigval); 47621.1Skamil 47631.75Skamil DPRINTF("Before killing the child process with %s\n", type); 47641.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 47651.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 47661.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 47671.75Skamil kill(child, SIGKILL); 47681.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 47691.75Skamil setpgid(child, 0); 47701.75Skamil killpg(getpgid(child), SIGKILL); 47711.75Skamil } 47721.1Skamil 47731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47751.1Skamil 47761.75Skamil validate_status_signaled(status, SIGKILL, 0); 47771.1Skamil 47781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47791.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47801.1Skamil} 47811.1Skamil 47821.75Skamil#define PTRACE_KILL(test, type) \ 47831.75SkamilATF_TC(test); \ 47841.75SkamilATF_TC_HEAD(test, tc) \ 47851.75Skamil{ \ 47861.75Skamil atf_tc_set_md_var(tc, "descr", \ 47871.75Skamil "Verify killing the child with " type); \ 47881.75Skamil} \ 47891.75Skamil \ 47901.75SkamilATF_TC_BODY(test, tc) \ 47911.75Skamil{ \ 47921.75Skamil \ 47931.75Skamil ptrace_kill(type); \ 47941.1Skamil} 47951.1Skamil 47961.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 47971.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 47981.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 47991.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 48001.1Skamil 48011.75Skamil/// ---------------------------------------------------------------------------- 48021.1Skamil 48031.77Skamilstatic void 48041.77Skamiltraceme_lwpinfo(const int threads) 48051.1Skamil{ 48061.1Skamil const int sigval = SIGSTOP; 48071.77Skamil const int sigval2 = SIGINT; 48081.1Skamil pid_t child, wpid; 48091.1Skamil#if defined(TWAIT_HAVE_STATUS) 48101.1Skamil int status; 48111.1Skamil#endif 48121.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 48131.77Skamil struct ptrace_siginfo info; 48141.77Skamil 48151.77Skamil /* Maximum number of supported threads in this test */ 48161.77Skamil pthread_t t[3]; 48171.77Skamil int n, rv; 48181.77Skamil 48191.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 48201.1Skamil 48211.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48221.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48231.1Skamil if (child == 0) { 48241.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48251.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48261.1Skamil 48271.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48281.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48291.1Skamil 48301.77Skamil for (n = 0; n < threads; n++) { 48311.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48321.77Skamil FORKEE_ASSERT(rv == 0); 48331.77Skamil } 48341.77Skamil 48351.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 48361.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 48371.77Skamil 48381.77Skamil /* NOTREACHED */ 48391.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48401.1Skamil } 48411.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48421.1Skamil 48431.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48441.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48451.1Skamil 48461.1Skamil validate_status_stopped(status, sigval); 48471.1Skamil 48481.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48491.77Skamil SYSCALL_REQUIRE( 48501.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48511.77Skamil 48521.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48531.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48541.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48551.77Skamil info.psi_siginfo.si_errno); 48561.77Skamil 48571.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 48581.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48591.77Skamil 48601.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48611.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48621.1Skamil 48631.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48641.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48651.1Skamil 48661.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 48671.77Skamil lwp.pl_lwpid); 48681.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 48691.1Skamil 48701.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48711.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48721.1Skamil 48731.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48741.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48751.1Skamil 48761.13Schristos DPRINTF("Before resuming the child process where it left off and " 48771.1Skamil "without signal to be sent\n"); 48781.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48791.1Skamil 48801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48821.1Skamil 48831.77Skamil validate_status_stopped(status, sigval2); 48841.77Skamil 48851.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48861.77Skamil SYSCALL_REQUIRE( 48871.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48881.77Skamil 48891.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48901.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48911.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48921.77Skamil info.psi_siginfo.si_errno); 48931.77Skamil 48941.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 48951.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48961.77Skamil 48971.77Skamil memset(&lwp, 0, sizeof(lwp)); 48981.77Skamil 48991.77Skamil for (n = 0; n <= threads; n++) { 49001.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49011.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 49021.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49031.77Skamil 49041.77Skamil DPRINTF("Assert that the thread exists\n"); 49051.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 49061.77Skamil 49071.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 49081.77Skamil lwp.pl_lwpid); 49091.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 49101.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 49111.77Skamil } 49121.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49131.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 49141.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49151.77Skamil 49161.77Skamil DPRINTF("Assert that there are no more threads\n"); 49171.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 49181.77Skamil 49191.77Skamil DPRINTF("Before resuming the child process where it left off and " 49201.77Skamil "without signal to be sent\n"); 49211.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 49221.77Skamil 49231.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49241.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49251.77Skamil 49261.77Skamil validate_status_signaled(status, SIGKILL, 0); 49271.1Skamil 49281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49291.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49301.1Skamil} 49311.1Skamil 49321.77Skamil#define TRACEME_LWPINFO(test, threads) \ 49331.77SkamilATF_TC(test); \ 49341.77SkamilATF_TC_HEAD(test, tc) \ 49351.77Skamil{ \ 49361.77Skamil atf_tc_set_md_var(tc, "descr", \ 49371.77Skamil "Verify LWPINFO with the child with " #threads \ 49381.77Skamil " spawned extra threads"); \ 49391.77Skamil} \ 49401.77Skamil \ 49411.77SkamilATF_TC_BODY(test, tc) \ 49421.77Skamil{ \ 49431.77Skamil \ 49441.77Skamil traceme_lwpinfo(threads); \ 49451.1Skamil} 49461.1Skamil 49471.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 49481.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 49491.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 49501.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 49511.77Skamil 49521.77Skamil/// ---------------------------------------------------------------------------- 49531.77Skamil 49541.77Skamil#if defined(TWAIT_HAVE_PID) 49551.77Skamilstatic void 49561.77Skamilattach_lwpinfo(const int threads) 49571.1Skamil{ 49581.77Skamil const int sigval = SIGINT; 49591.1Skamil struct msg_fds parent_tracee, parent_tracer; 49601.1Skamil const int exitval_tracer = 10; 49611.1Skamil pid_t tracee, tracer, wpid; 49621.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 49631.1Skamil#if defined(TWAIT_HAVE_STATUS) 49641.1Skamil int status; 49651.1Skamil#endif 49661.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 49671.77Skamil struct ptrace_siginfo info; 49681.77Skamil 49691.77Skamil /* Maximum number of supported threads in this test */ 49701.77Skamil pthread_t t[3]; 49711.77Skamil int n, rv; 49721.1Skamil 49731.13Schristos DPRINTF("Spawn tracee\n"); 49741.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 49751.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 49761.1Skamil tracee = atf_utils_fork(); 49771.1Skamil if (tracee == 0) { 49781.1Skamil /* Wait for message from the parent */ 49791.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 49801.1Skamil 49811.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 49821.77Skamil 49831.77Skamil for (n = 0; n < threads; n++) { 49841.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 49851.77Skamil FORKEE_ASSERT(rv == 0); 49861.77Skamil } 49871.77Skamil 49881.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 49891.77Skamil 49901.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49911.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 49921.77Skamil 49931.77Skamil /* NOTREACHED */ 49941.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 49951.1Skamil } 49961.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 49971.1Skamil 49981.13Schristos DPRINTF("Spawn debugger\n"); 49991.1Skamil tracer = atf_utils_fork(); 50001.1Skamil if (tracer == 0) { 50011.1Skamil /* No IPC to communicate with the child */ 50021.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 50031.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 50041.1Skamil 50051.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 50061.1Skamil FORKEE_REQUIRE_SUCCESS( 50071.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50081.1Skamil 50091.1Skamil forkee_status_stopped(status, SIGSTOP); 50101.1Skamil 50111.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50121.77Skamil "tracee"); 50131.77Skamil FORKEE_ASSERT( 50141.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50151.77Skamil 50161.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50171.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50181.77Skamil "si_errno=%#x\n", 50191.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50201.77Skamil info.psi_siginfo.si_errno); 50211.77Skamil 50221.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 50231.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 50241.77Skamil 50251.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 50261.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50271.1Skamil != -1); 50281.1Skamil 50291.13Schristos DPRINTF("Assert that there exists a thread\n"); 50301.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 50311.1Skamil 50321.13Schristos DPRINTF("Assert that lwp thread %d received event " 50331.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 50341.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 50351.1Skamil 50361.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50371.77Skamil "tracee\n"); 50381.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50391.1Skamil != -1); 50401.1Skamil 50411.77Skamil DPRINTF("Assert that there are no more lwp threads in " 50421.77Skamil "tracee\n"); 50431.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50441.1Skamil 50451.1Skamil /* Resume tracee with PT_CONTINUE */ 50461.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 50471.1Skamil 50481.1Skamil /* Inform parent that tracer has attached to tracee */ 50491.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 50501.77Skamil 50511.1Skamil /* Wait for parent */ 50521.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 50531.1Skamil 50541.77Skamil /* Wait for tracee and assert that it raised a signal */ 50551.77Skamil FORKEE_REQUIRE_SUCCESS( 50561.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50571.77Skamil 50581.77Skamil forkee_status_stopped(status, SIGINT); 50591.77Skamil 50601.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50611.77Skamil "child"); 50621.77Skamil FORKEE_ASSERT( 50631.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50641.77Skamil 50651.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50661.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50671.77Skamil "si_errno=%#x\n", 50681.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50691.77Skamil info.psi_siginfo.si_errno); 50701.77Skamil 50711.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 50721.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 50731.77Skamil 50741.77Skamil memset(&lwp, 0, sizeof(lwp)); 50751.77Skamil 50761.77Skamil for (n = 0; n <= threads; n++) { 50771.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50781.77Skamil "child\n"); 50791.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 50801.77Skamil sizeof(lwp)) != -1); 50811.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50821.77Skamil 50831.77Skamil DPRINTF("Assert that the thread exists\n"); 50841.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 50851.77Skamil 50861.77Skamil DPRINTF("Assert that lwp thread %d received expected " 50871.77Skamil "event\n", lwp.pl_lwpid); 50881.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 50891.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 50901.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 50911.77Skamil } 50921.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50931.77Skamil "tracee\n"); 50941.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50951.77Skamil != -1); 50961.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50971.77Skamil 50981.77Skamil DPRINTF("Assert that there are no more threads\n"); 50991.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 51001.77Skamil 51011.77Skamil DPRINTF("Before resuming the child process where it left off " 51021.77Skamil "and without signal to be sent\n"); 51031.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 51041.77Skamil != -1); 51051.77Skamil 51061.1Skamil /* Wait for tracee and assert that it exited */ 51071.1Skamil FORKEE_REQUIRE_SUCCESS( 51081.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 51091.1Skamil 51101.77Skamil forkee_status_signaled(status, SIGKILL, 0); 51111.1Skamil 51121.13Schristos DPRINTF("Before exiting of the tracer process\n"); 51131.1Skamil _exit(exitval_tracer); 51141.1Skamil } 51151.1Skamil 51161.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 51171.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 51181.1Skamil 51191.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 51201.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 51211.77Skamil 51221.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 51231.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 51241.1Skamil 51251.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 51261.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 51271.1Skamil 51281.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 51291.1Skamil TWAIT_FNAME); 51301.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 51311.1Skamil tracer); 51321.1Skamil 51331.1Skamil validate_status_exited(status, exitval_tracer); 51341.1Skamil 51351.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 51361.1Skamil TWAIT_FNAME); 51371.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 51381.1Skamil tracee); 51391.1Skamil 51401.77Skamil validate_status_signaled(status, SIGKILL, 0); 51411.1Skamil 51421.1Skamil msg_close(&parent_tracer); 51431.1Skamil msg_close(&parent_tracee); 51441.1Skamil} 51451.77Skamil 51461.77Skamil#define ATTACH_LWPINFO(test, threads) \ 51471.77SkamilATF_TC(test); \ 51481.77SkamilATF_TC_HEAD(test, tc) \ 51491.77Skamil{ \ 51501.77Skamil atf_tc_set_md_var(tc, "descr", \ 51511.77Skamil "Verify LWPINFO with the child with " #threads \ 51521.77Skamil " spawned extra threads (tracer is not the original " \ 51531.77Skamil "parent)"); \ 51541.77Skamil} \ 51551.77Skamil \ 51561.77SkamilATF_TC_BODY(test, tc) \ 51571.77Skamil{ \ 51581.77Skamil \ 51591.77Skamil attach_lwpinfo(threads); \ 51601.77Skamil} 51611.77Skamil 51621.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 51631.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 51641.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 51651.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 51661.1Skamil#endif 51671.1Skamil 51681.77Skamil/// ---------------------------------------------------------------------------- 51691.77Skamil 51701.1Skamilstatic void 51711.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 51721.1Skamil{ 51731.1Skamil const int exitval = 5; 51741.1Skamil const int sigval = SIGINT; 51751.1Skamil const int sigfaked = SIGTRAP; 51761.1Skamil const int sicodefaked = TRAP_BRKPT; 51771.1Skamil pid_t child, wpid; 51781.1Skamil struct sigaction sa; 51791.1Skamil#if defined(TWAIT_HAVE_STATUS) 51801.1Skamil int status; 51811.1Skamil#endif 51821.1Skamil struct ptrace_siginfo info; 51831.1Skamil memset(&info, 0, sizeof(info)); 51841.1Skamil 51851.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 51861.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 51871.1Skamil if (child == 0) { 51881.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51891.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51901.1Skamil 51911.79Skamil sa.sa_sigaction = sah; 51921.1Skamil sa.sa_flags = SA_SIGINFO; 51931.1Skamil sigemptyset(&sa.sa_mask); 51941.1Skamil 51951.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 51961.79Skamil != -1); 51971.1Skamil 51981.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 51991.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 52001.1Skamil 52011.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 52021.1Skamil 52031.13Schristos DPRINTF("Before exiting of the child process\n"); 52041.1Skamil _exit(exitval); 52051.1Skamil } 52061.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52071.1Skamil 52081.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52101.1Skamil 52111.1Skamil validate_status_stopped(status, sigval); 52121.1Skamil 52131.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52141.61Skre SYSCALL_REQUIRE( 52151.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52161.1Skamil 52171.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52181.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52191.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52201.1Skamil info.psi_siginfo.si_errno); 52211.1Skamil 52221.79Skamil if (faked) { 52231.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 52241.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 52251.79Skamil info.psi_siginfo.si_signo = sigfaked; 52261.79Skamil info.psi_siginfo.si_code = sicodefaked; 52271.79Skamil } 52281.1Skamil 52291.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 52301.61Skre SYSCALL_REQUIRE( 52311.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 52321.1Skamil 52331.79Skamil if (faked) { 52341.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52351.79Skamil "child\n"); 52361.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 52371.79Skamil sizeof(info)) != -1); 52381.1Skamil 52391.79Skamil DPRINTF("Before checking siginfo_t\n"); 52401.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 52411.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 52421.79Skamil } 52431.1Skamil 52441.13Schristos DPRINTF("Before resuming the child process where it left off and " 52451.1Skamil "without signal to be sent\n"); 52461.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 52471.79Skamil faked ? sigfaked : sigval) != -1); 52481.1Skamil 52491.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52501.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52511.1Skamil 52521.1Skamil validate_status_exited(status, exitval); 52531.1Skamil 52541.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52551.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 52561.1Skamil} 52571.1Skamil 52581.79Skamil#define PTRACE_SIGINFO(test, faked) \ 52591.79SkamilATF_TC(test); \ 52601.79SkamilATF_TC_HEAD(test, tc) \ 52611.79Skamil{ \ 52621.79Skamil atf_tc_set_md_var(tc, "descr", \ 52631.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 52641.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 52651.79Skamil} \ 52661.79Skamil \ 52671.79Skamilstatic int test##_caught = 0; \ 52681.79Skamil \ 52691.79Skamilstatic void \ 52701.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 52711.79Skamil{ \ 52721.79Skamil if (faked) { \ 52731.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 52741.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 52751.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 52761.79Skamil } else { \ 52771.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 52781.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 52791.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 52801.79Skamil } \ 52811.79Skamil \ 52821.79Skamil ++ test##_caught; \ 52831.79Skamil} \ 52841.79Skamil \ 52851.79SkamilATF_TC_BODY(test, tc) \ 52861.79Skamil{ \ 52871.79Skamil \ 52881.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 52891.79Skamil} 52901.79Skamil 52911.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 52921.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 52931.79Skamil 52941.79Skamil/// ---------------------------------------------------------------------------- 52951.79Skamil 52961.97Skamilstatic void 52971.97Skamiltraceme_exec(bool masked, bool ignored) 52981.1Skamil{ 52991.1Skamil const int sigval = SIGTRAP; 53001.1Skamil pid_t child, wpid; 53011.1Skamil#if defined(TWAIT_HAVE_STATUS) 53021.1Skamil int status; 53031.1Skamil#endif 53041.97Skamil struct sigaction sa; 53051.97Skamil struct ptrace_siginfo info; 53061.97Skamil sigset_t intmask; 53071.97Skamil struct kinfo_proc2 kp; 53081.97Skamil size_t len = sizeof(kp); 53091.97Skamil 53101.97Skamil int name[6]; 53111.97Skamil const size_t namelen = __arraycount(name); 53121.97Skamil ki_sigset_t kp_sigmask; 53131.97Skamil ki_sigset_t kp_sigignore; 53141.1Skamil 53151.1Skamil memset(&info, 0, sizeof(info)); 53161.1Skamil 53171.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53181.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53191.1Skamil if (child == 0) { 53201.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53211.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53221.1Skamil 53231.97Skamil if (masked) { 53241.97Skamil sigemptyset(&intmask); 53251.97Skamil sigaddset(&intmask, sigval); 53261.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53271.97Skamil } 53281.97Skamil 53291.97Skamil if (ignored) { 53301.97Skamil memset(&sa, 0, sizeof(sa)); 53311.97Skamil sa.sa_handler = SIG_IGN; 53321.97Skamil sigemptyset(&sa.sa_mask); 53331.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 53341.97Skamil } 53351.97Skamil 53361.13Schristos DPRINTF("Before calling execve(2) from child\n"); 53371.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 53381.1Skamil 53391.1Skamil FORKEE_ASSERT(0 && "Not reached"); 53401.1Skamil } 53411.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53421.1Skamil 53431.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53441.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53451.1Skamil 53461.1Skamil validate_status_stopped(status, sigval); 53471.1Skamil 53481.97Skamil name[0] = CTL_KERN, 53491.97Skamil name[1] = KERN_PROC2, 53501.97Skamil name[2] = KERN_PROC_PID; 53511.97Skamil name[3] = getpid(); 53521.97Skamil name[4] = sizeof(kp); 53531.97Skamil name[5] = 1; 53541.97Skamil 53551.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53561.97Skamil 53571.97Skamil if (masked) 53581.97Skamil kp_sigmask = kp.p_sigmask; 53591.97Skamil 53601.97Skamil if (ignored) 53611.97Skamil kp_sigignore = kp.p_sigignore; 53621.97Skamil 53631.97Skamil name[3] = getpid(); 53641.97Skamil 53651.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53661.97Skamil 53671.97Skamil if (masked) { 53681.97Skamil DPRINTF("kp_sigmask=" 53691.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53701.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53711.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53721.97Skamil 53731.97Skamil DPRINTF("kp.p_sigmask=" 53741.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53751.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53761.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53771.97Skamil 53781.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53791.97Skamil sizeof(kp_sigmask))); 53801.97Skamil } 53811.97Skamil 53821.97Skamil if (ignored) { 53831.97Skamil DPRINTF("kp_sigignore=" 53841.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53851.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53861.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53871.97Skamil 53881.97Skamil DPRINTF("kp.p_sigignore=" 53891.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53901.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53911.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53921.97Skamil 53931.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53941.97Skamil sizeof(kp_sigignore))); 53951.97Skamil } 53961.97Skamil 53971.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 53981.61Skre SYSCALL_REQUIRE( 53991.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54001.1Skamil 54011.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54021.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 54031.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54041.1Skamil info.psi_siginfo.si_errno); 54051.1Skamil 54061.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 54071.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 54081.1Skamil 54091.13Schristos DPRINTF("Before resuming the child process where it left off and " 54101.1Skamil "without signal to be sent\n"); 54111.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54121.1Skamil 54131.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54151.1Skamil 54161.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54171.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54181.1Skamil} 54191.1Skamil 54201.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 54211.97SkamilATF_TC(test); \ 54221.97SkamilATF_TC_HEAD(test, tc) \ 54231.97Skamil{ \ 54241.97Skamil atf_tc_set_md_var(tc, "descr", \ 54251.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 54261.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 54271.97Skamil masked ? " with ignored signal" : ""); \ 54281.97Skamil} \ 54291.97Skamil \ 54301.97SkamilATF_TC_BODY(test, tc) \ 54311.97Skamil{ \ 54321.97Skamil \ 54331.97Skamil traceme_exec(masked, ignored); \ 54341.97Skamil} 54351.97Skamil 54361.97SkamilTRACEME_EXEC(traceme_exec, false, false) 54371.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 54381.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 54391.97Skamil 54401.82Skamil/// ---------------------------------------------------------------------------- 54411.82Skamil 54421.135Skamil#define TRACE_THREADS_NUM 100 54431.135Skamil 54441.83Skamilstatic volatile int done; 54451.137Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER; 54461.1Skamil 54471.83Skamilstatic void * 54481.83Skamiltrace_threads_cb(void *arg __unused) 54491.1Skamil{ 54501.1Skamil 54511.137Skamil pthread_mutex_lock(&trace_threads_mtx); 54521.83Skamil done++; 54531.137Skamil pthread_mutex_unlock(&trace_threads_mtx); 54541.83Skamil 54551.135Skamil while (done < TRACE_THREADS_NUM) 54561.135Skamil sched_yield(); 54571.83Skamil 54581.83Skamil return NULL; 54591.1Skamil} 54601.1Skamil 54611.83Skamilstatic void 54621.83Skamiltrace_threads(bool trace_create, bool trace_exit) 54631.1Skamil{ 54641.1Skamil const int sigval = SIGSTOP; 54651.1Skamil pid_t child, wpid; 54661.1Skamil#if defined(TWAIT_HAVE_STATUS) 54671.1Skamil int status; 54681.1Skamil#endif 54691.1Skamil ptrace_state_t state; 54701.1Skamil const int slen = sizeof(state); 54711.1Skamil ptrace_event_t event; 54721.1Skamil const int elen = sizeof(event); 54731.83Skamil struct ptrace_siginfo info; 54741.83Skamil 54751.135Skamil pthread_t t[TRACE_THREADS_NUM]; 54761.83Skamil int rv; 54771.83Skamil size_t n; 54781.1Skamil lwpid_t lid; 54791.83Skamil 54801.83Skamil /* Track created and exited threads */ 54811.141Skamil struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}}; 54821.83Skamil 54831.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54841.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54851.1Skamil if (child == 0) { 54861.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54871.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54881.1Skamil 54891.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54901.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54911.1Skamil 54921.83Skamil for (n = 0; n < __arraycount(t); n++) { 54931.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 54941.83Skamil NULL); 54951.83Skamil FORKEE_ASSERT(rv == 0); 54961.83Skamil } 54971.1Skamil 54981.83Skamil for (n = 0; n < __arraycount(t); n++) { 54991.83Skamil rv = pthread_join(t[n], NULL); 55001.83Skamil FORKEE_ASSERT(rv == 0); 55011.83Skamil } 55021.1Skamil 55031.83Skamil /* 55041.83Skamil * There is race between _exit() and pthread_join() detaching 55051.83Skamil * a thread. For simplicity kill the process after detecting 55061.83Skamil * LWP events. 55071.83Skamil */ 55081.83Skamil while (true) 55091.83Skamil continue; 55101.1Skamil 55111.83Skamil FORKEE_ASSERT(0 && "Not reached"); 55121.1Skamil } 55131.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55141.1Skamil 55151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55171.1Skamil 55181.1Skamil validate_status_stopped(status, sigval); 55191.1Skamil 55201.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 55211.83Skamil SYSCALL_REQUIRE( 55221.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55231.1Skamil 55241.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55251.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55261.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55271.83Skamil info.psi_siginfo.si_errno); 55281.1Skamil 55291.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55301.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55311.1Skamil 55321.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 55331.83Skamil memset(&event, 0, sizeof(event)); 55341.83Skamil if (trace_create) 55351.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 55361.83Skamil if (trace_exit) 55371.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 55381.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 55391.1Skamil 55401.13Schristos DPRINTF("Before resuming the child process where it left off and " 55411.1Skamil "without signal to be sent\n"); 55421.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55431.1Skamil 55441.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 55451.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55461.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55471.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55481.83Skamil child); 55491.1Skamil 55501.83Skamil validate_status_stopped(status, SIGTRAP); 55511.1Skamil 55521.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55531.83Skamil "child\n"); 55541.83Skamil SYSCALL_REQUIRE( 55551.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55561.1Skamil 55571.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55581.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55591.83Skamil "si_errno=%#x\n", 55601.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55611.83Skamil info.psi_siginfo.si_errno); 55621.1Skamil 55631.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55641.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55651.1Skamil 55661.83Skamil SYSCALL_REQUIRE( 55671.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55681.1Skamil 55691.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 55701.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 55711.1Skamil 55721.83Skamil lid = state.pe_lwp; 55731.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 55741.1Skamil 55751.141Skamil *FIND_EVENT_COUNT(traced_lwps, lid) += 1; 55761.1Skamil 55771.83Skamil DPRINTF("Before resuming the child process where it left off " 55781.83Skamil "and without signal to be sent\n"); 55791.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55801.83Skamil } 55811.1Skamil 55821.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 55831.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55841.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55851.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55861.83Skamil child); 55871.1Skamil 55881.83Skamil validate_status_stopped(status, SIGTRAP); 55891.1Skamil 55901.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55911.83Skamil "child\n"); 55921.83Skamil SYSCALL_REQUIRE( 55931.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55941.1Skamil 55951.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55961.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55971.83Skamil "si_errno=%#x\n", 55981.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55991.83Skamil info.psi_siginfo.si_errno); 56001.1Skamil 56011.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 56021.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 56031.1Skamil 56041.83Skamil SYSCALL_REQUIRE( 56051.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 56061.1Skamil 56071.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 56081.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 56091.1Skamil 56101.83Skamil lid = state.pe_lwp; 56111.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 56121.1Skamil 56131.83Skamil if (trace_create) { 56141.141Skamil int *count = FIND_EVENT_COUNT(traced_lwps, lid); 56151.141Skamil ATF_REQUIRE_EQ(*count, 1); 56161.141Skamil *count = 0; 56171.83Skamil } 56181.1Skamil 56191.83Skamil DPRINTF("Before resuming the child process where it left off " 56201.83Skamil "and without signal to be sent\n"); 56211.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56221.83Skamil } 56231.1Skamil 56241.83Skamil kill(child, SIGKILL); 56251.1Skamil 56261.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 56271.1Skamil TWAIT_FNAME); 56281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56291.1Skamil 56301.83Skamil validate_status_signaled(status, SIGKILL, 0); 56311.1Skamil 56321.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 56331.1Skamil TWAIT_FNAME); 56341.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56351.1Skamil} 56361.1Skamil 56371.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 56381.83SkamilATF_TC(test); \ 56391.83SkamilATF_TC_HEAD(test, tc) \ 56401.83Skamil{ \ 56411.83Skamil atf_tc_set_md_var(tc, "descr", \ 56421.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 56431.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 56441.83Skamil trace_exit ? "" : "out"); \ 56451.83Skamil} \ 56461.83Skamil \ 56471.83SkamilATF_TC_BODY(test, tc) \ 56481.83Skamil{ \ 56491.83Skamil \ 56501.83Skamil trace_threads(trace_create, trace_exit); \ 56511.83Skamil} 56521.83Skamil 56531.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 56541.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 56551.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 56561.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 56571.83Skamil 56581.83Skamil/// ---------------------------------------------------------------------------- 56591.83Skamil 56601.84SkamilATF_TC(signal_mask_unrelated); 56611.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 56621.1Skamil{ 56631.1Skamil atf_tc_set_md_var(tc, "descr", 56641.1Skamil "Verify that masking single unrelated signal does not stop tracer " 56651.1Skamil "from catching other signals"); 56661.1Skamil} 56671.1Skamil 56681.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 56691.1Skamil{ 56701.1Skamil const int exitval = 5; 56711.1Skamil const int sigval = SIGSTOP; 56721.1Skamil const int sigmasked = SIGTRAP; 56731.1Skamil const int signotmasked = SIGINT; 56741.1Skamil pid_t child, wpid; 56751.1Skamil#if defined(TWAIT_HAVE_STATUS) 56761.1Skamil int status; 56771.1Skamil#endif 56781.1Skamil sigset_t intmask; 56791.1Skamil 56801.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56811.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56821.1Skamil if (child == 0) { 56831.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56841.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56851.1Skamil 56861.1Skamil sigemptyset(&intmask); 56871.1Skamil sigaddset(&intmask, sigmasked); 56881.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56891.1Skamil 56901.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56911.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56921.1Skamil 56931.13Schristos DPRINTF("Before raising %s from child\n", 56941.1Skamil strsignal(signotmasked)); 56951.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 56961.1Skamil 56971.13Schristos DPRINTF("Before exiting of the child process\n"); 56981.1Skamil _exit(exitval); 56991.1Skamil } 57001.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57011.1Skamil 57021.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57041.1Skamil 57051.1Skamil validate_status_stopped(status, sigval); 57061.1Skamil 57071.13Schristos DPRINTF("Before resuming the child process where it left off and " 57081.1Skamil "without signal to be sent\n"); 57091.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57101.1Skamil 57111.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57131.1Skamil 57141.1Skamil validate_status_stopped(status, signotmasked); 57151.1Skamil 57161.13Schristos DPRINTF("Before resuming the child process where it left off and " 57171.1Skamil "without signal to be sent\n"); 57181.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57191.1Skamil 57201.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57211.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57221.1Skamil 57231.1Skamil validate_status_exited(status, exitval); 57241.1Skamil 57251.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57261.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57271.1Skamil} 57281.1Skamil 57291.84Skamil/// ---------------------------------------------------------------------------- 57301.84Skamil 57311.1Skamil#if defined(TWAIT_HAVE_PID) 57321.99Skamilstatic void 57331.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 57341.1Skamil{ 57351.1Skamil const int exitval = 5; 57361.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 57371.1Skamil const int sigval = SIGSTOP; 57381.99Skamil pid_t child, child2 = 0, wpid; 57391.1Skamil#if defined(TWAIT_HAVE_STATUS) 57401.1Skamil int status; 57411.1Skamil#endif 57421.1Skamil ptrace_state_t state; 57431.1Skamil const int slen = sizeof(state); 57441.1Skamil ptrace_event_t event; 57451.1Skamil const int elen = sizeof(event); 57461.99Skamil struct sigaction sa; 57471.99Skamil struct ptrace_siginfo info; 57481.99Skamil sigset_t intmask; 57491.99Skamil struct kinfo_proc2 kp; 57501.99Skamil size_t len = sizeof(kp); 57511.99Skamil 57521.99Skamil int name[6]; 57531.99Skamil const size_t namelen = __arraycount(name); 57541.99Skamil ki_sigset_t kp_sigmask; 57551.99Skamil ki_sigset_t kp_sigignore; 57561.1Skamil 57571.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 57581.14Schristos 57591.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57601.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57611.1Skamil if (child == 0) { 57621.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57631.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57641.1Skamil 57651.99Skamil if (masked) { 57661.99Skamil sigemptyset(&intmask); 57671.99Skamil sigaddset(&intmask, SIGTRAP); 57681.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 57691.99Skamil } 57701.99Skamil 57711.99Skamil if (ignored) { 57721.99Skamil memset(&sa, 0, sizeof(sa)); 57731.99Skamil sa.sa_handler = SIG_IGN; 57741.99Skamil sigemptyset(&sa.sa_mask); 57751.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 57761.99Skamil } 57771.1Skamil 57781.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57791.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57801.1Skamil 57811.126Skamil if (strcmp(fn, "spawn") == 0) { 57821.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 57831.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 57841.126Skamil } else { 57851.126Skamil if (strcmp(fn, "fork") == 0) { 57861.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 57871.126Skamil } else { 57881.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 57891.126Skamil } 57901.126Skamil if (child2 == 0) 57911.126Skamil _exit(exitval2); 57921.126Skamil } 57931.1Skamil 57941.1Skamil FORKEE_REQUIRE_SUCCESS 57951.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 57961.1Skamil 57971.1Skamil forkee_status_exited(status, exitval2); 57981.1Skamil 57991.13Schristos DPRINTF("Before exiting of the child process\n"); 58001.1Skamil _exit(exitval); 58011.1Skamil } 58021.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 58031.1Skamil 58041.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 58051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58061.1Skamil 58071.1Skamil validate_status_stopped(status, sigval); 58081.1Skamil 58091.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 58101.99Skamil SYSCALL_REQUIRE( 58111.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 58121.99Skamil 58131.99Skamil DPRINTF("Before checking siginfo_t\n"); 58141.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 58151.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 58161.1Skamil 58171.99Skamil name[0] = CTL_KERN, 58181.99Skamil name[1] = KERN_PROC2, 58191.99Skamil name[2] = KERN_PROC_PID; 58201.99Skamil name[3] = child; 58211.99Skamil name[4] = sizeof(kp); 58221.99Skamil name[5] = 1; 58231.1Skamil 58241.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58251.1Skamil 58261.99Skamil if (masked) 58271.99Skamil kp_sigmask = kp.p_sigmask; 58281.1Skamil 58291.99Skamil if (ignored) 58301.99Skamil kp_sigignore = kp.p_sigignore; 58311.1Skamil 58321.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 58331.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 58341.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 58351.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 58361.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 58371.99Skamil event.pe_set_event = 0; 58381.126Skamil if (strcmp(fn, "spawn") == 0) 58391.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 58401.126Skamil if (strcmp(fn, "fork") == 0) 58411.99Skamil event.pe_set_event |= PTRACE_FORK; 58421.126Skamil if (strcmp(fn, "vfork") == 0) 58431.99Skamil event.pe_set_event |= PTRACE_VFORK; 58441.126Skamil if (strcmp(fn, "vforkdone") == 0) 58451.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 58461.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58471.1Skamil 58481.99Skamil DPRINTF("Before resuming the child process where it left off and " 58491.99Skamil "without signal to be sent\n"); 58501.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58511.1Skamil 58521.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 58531.126Skamil strcmp(fn, "vfork") == 0) { 58541.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58551.99Skamil child); 58561.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58571.99Skamil child); 58581.1Skamil 58591.99Skamil validate_status_stopped(status, SIGTRAP); 58601.1Skamil 58611.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58621.1Skamil 58631.99Skamil if (masked) { 58641.99Skamil DPRINTF("kp_sigmask=" 58651.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58661.99Skamil PRIx32 "\n", 58671.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58681.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58691.1Skamil 58701.99Skamil DPRINTF("kp.p_sigmask=" 58711.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58721.99Skamil PRIx32 "\n", 58731.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58741.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58751.1Skamil 58761.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58771.99Skamil sizeof(kp_sigmask))); 58781.99Skamil } 58791.1Skamil 58801.99Skamil if (ignored) { 58811.99Skamil DPRINTF("kp_sigignore=" 58821.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58831.99Skamil PRIx32 "\n", 58841.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58851.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58861.1Skamil 58871.99Skamil DPRINTF("kp.p_sigignore=" 58881.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58891.99Skamil PRIx32 "\n", 58901.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58911.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58921.1Skamil 58931.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58941.99Skamil sizeof(kp_sigignore))); 58951.99Skamil } 58961.1Skamil 58971.99Skamil SYSCALL_REQUIRE( 58981.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58991.126Skamil if (strcmp(fn, "spawn") == 0) { 59001.126Skamil ATF_REQUIRE_EQ( 59011.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59021.126Skamil PTRACE_POSIX_SPAWN); 59031.126Skamil } 59041.126Skamil if (strcmp(fn, "fork") == 0) { 59051.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59061.99Skamil PTRACE_FORK); 59071.99Skamil } 59081.126Skamil if (strcmp(fn, "vfork") == 0) { 59091.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59101.99Skamil PTRACE_VFORK); 59111.99Skamil } 59121.1Skamil 59131.99Skamil child2 = state.pe_other_pid; 59141.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 59151.1Skamil 59161.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 59171.99Skamil "%d\n", TWAIT_FNAME, child2, child); 59181.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 59191.99Skamil child2); 59201.1Skamil 59211.99Skamil validate_status_stopped(status, SIGTRAP); 59221.1Skamil 59231.99Skamil name[3] = child2; 59241.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59251.1Skamil 59261.99Skamil if (masked) { 59271.99Skamil DPRINTF("kp_sigmask=" 59281.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59291.99Skamil PRIx32 "\n", 59301.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59311.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59321.1Skamil 59331.99Skamil DPRINTF("kp.p_sigmask=" 59341.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59351.99Skamil PRIx32 "\n", 59361.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59371.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59381.14Schristos 59391.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59401.99Skamil sizeof(kp_sigmask))); 59411.99Skamil } 59421.1Skamil 59431.99Skamil if (ignored) { 59441.99Skamil DPRINTF("kp_sigignore=" 59451.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59461.99Skamil PRIx32 "\n", 59471.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59481.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59491.1Skamil 59501.99Skamil DPRINTF("kp.p_sigignore=" 59511.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59521.99Skamil PRIx32 "\n", 59531.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59541.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59551.1Skamil 59561.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59571.99Skamil sizeof(kp_sigignore))); 59581.99Skamil } 59591.1Skamil 59601.99Skamil SYSCALL_REQUIRE( 59611.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 59621.126Skamil if (strcmp(fn, "spawn") == 0) { 59631.126Skamil ATF_REQUIRE_EQ( 59641.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59651.126Skamil PTRACE_POSIX_SPAWN); 59661.126Skamil } 59671.126Skamil if (strcmp(fn, "fork") == 0) { 59681.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59691.99Skamil PTRACE_FORK); 59701.99Skamil } 59711.126Skamil if (strcmp(fn, "vfork") == 0) { 59721.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59731.99Skamil PTRACE_VFORK); 59741.99Skamil } 59751.1Skamil 59761.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 59771.1Skamil 59781.99Skamil DPRINTF("Before resuming the forkee process where it left off " 59791.99Skamil "and without signal to be sent\n"); 59801.99Skamil SYSCALL_REQUIRE( 59811.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 59821.1Skamil 59831.99Skamil DPRINTF("Before resuming the child process where it left off " 59841.99Skamil "and without signal to be sent\n"); 59851.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59861.1Skamil } 59871.1Skamil 59881.126Skamil if (strcmp(fn, "vforkdone") == 0) { 59891.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 59901.99Skamil child); 59911.99Skamil TWAIT_REQUIRE_SUCCESS( 59921.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 59931.1Skamil 59941.99Skamil validate_status_stopped(status, SIGTRAP); 59951.1Skamil 59961.99Skamil name[3] = child; 59971.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59981.1Skamil 59991.102Skamil /* 60001.102Skamil * SIGCHLD is now pending in the signal queue and 60011.102Skamil * the kernel presents it to userland as a masked signal. 60021.102Skamil */ 60031.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 60041.102Skamil 60051.99Skamil if (masked) { 60061.99Skamil DPRINTF("kp_sigmask=" 60071.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60081.99Skamil PRIx32 "\n", 60091.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 60101.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 60111.1Skamil 60121.99Skamil DPRINTF("kp.p_sigmask=" 60131.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60141.99Skamil PRIx32 "\n", 60151.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 60161.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 60171.1Skamil 60181.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 60191.99Skamil sizeof(kp_sigmask))); 60201.99Skamil } 60211.1Skamil 60221.99Skamil if (ignored) { 60231.99Skamil DPRINTF("kp_sigignore=" 60241.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60251.99Skamil PRIx32 "\n", 60261.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 60271.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 60281.1Skamil 60291.99Skamil DPRINTF("kp.p_sigignore=" 60301.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60311.99Skamil PRIx32 "\n", 60321.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 60331.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 60341.1Skamil 60351.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 60361.99Skamil sizeof(kp_sigignore))); 60371.99Skamil } 60381.1Skamil 60391.99Skamil SYSCALL_REQUIRE( 60401.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60411.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 60421.1Skamil 60431.99Skamil child2 = state.pe_other_pid; 60441.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 60451.99Skamil child2); 60461.1Skamil 60471.99Skamil DPRINTF("Before resuming the child process where it left off " 60481.99Skamil "and without signal to be sent\n"); 60491.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60501.99Skamil } 60511.1Skamil 60521.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 60531.126Skamil strcmp(fn, "vfork") == 0) { 60541.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 60551.99Skamil "\n", TWAIT_FNAME); 60561.99Skamil TWAIT_REQUIRE_SUCCESS( 60571.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 60581.1Skamil 60591.99Skamil validate_status_exited(status, exitval2); 60601.1Skamil 60611.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 60621.99Skamil "process\n", TWAIT_FNAME); 60631.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 60641.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 60651.99Skamil } 60661.1Skamil 60671.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60681.1Skamil "SIGCHLD\n", TWAIT_FNAME); 60691.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60701.1Skamil 60711.1Skamil validate_status_stopped(status, SIGCHLD); 60721.1Skamil 60731.57Skamil DPRINTF("Before resuming the child process where it left off and " 60741.1Skamil "without signal to be sent\n"); 60751.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60761.1Skamil 60771.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 60781.1Skamil TWAIT_FNAME); 60791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60801.1Skamil 60811.1Skamil validate_status_exited(status, exitval); 60821.1Skamil 60831.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60841.57Skamil TWAIT_FNAME); 60851.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60861.1Skamil} 60871.1Skamil 60881.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 60891.99SkamilATF_TC(name); \ 60901.99SkamilATF_TC_HEAD(name, tc) \ 60911.99Skamil{ \ 60921.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 60931.99Skamil "regardless of signal %s%s", \ 60941.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 60951.99Skamil} \ 60961.99Skamil \ 60971.99SkamilATF_TC_BODY(name, tc) \ 60981.99Skamil{ \ 60991.99Skamil \ 61001.126Skamil fork2_body(fn, masked, ignored); \ 61011.1Skamil} 61021.1Skamil 61031.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 61041.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 61051.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 61061.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 61071.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 61081.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 61091.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 61101.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 61111.1Skamil#endif 61121.1Skamil 61131.99Skamil/// ---------------------------------------------------------------------------- 61141.1Skamil 61151.83Skamilvolatile lwpid_t the_lwp_id = 0; 61161.83Skamil 61171.83Skamilstatic void 61181.83Skamillwp_main_func(void *arg) 61191.83Skamil{ 61201.83Skamil the_lwp_id = _lwp_self(); 61211.83Skamil _lwp_exit(); 61221.83Skamil} 61231.83Skamil 61241.1SkamilATF_TC(signal9); 61251.1SkamilATF_TC_HEAD(signal9, tc) 61261.1Skamil{ 61271.1Skamil atf_tc_set_md_var(tc, "descr", 61281.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61291.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 61301.1Skamil} 61311.1Skamil 61321.1SkamilATF_TC_BODY(signal9, tc) 61331.1Skamil{ 61341.1Skamil const int exitval = 5; 61351.1Skamil const int sigval = SIGSTOP; 61361.1Skamil const int sigmasked = SIGTRAP; 61371.1Skamil pid_t child, wpid; 61381.1Skamil#if defined(TWAIT_HAVE_STATUS) 61391.1Skamil int status; 61401.1Skamil#endif 61411.1Skamil sigset_t intmask; 61421.1Skamil ptrace_state_t state; 61431.1Skamil const int slen = sizeof(state); 61441.1Skamil ptrace_event_t event; 61451.1Skamil const int elen = sizeof(event); 61461.1Skamil ucontext_t uc; 61471.1Skamil lwpid_t lid; 61481.1Skamil static const size_t ssize = 16*1024; 61491.1Skamil void *stack; 61501.1Skamil 61511.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61521.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61531.1Skamil if (child == 0) { 61541.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61551.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61561.1Skamil 61571.1Skamil sigemptyset(&intmask); 61581.1Skamil sigaddset(&intmask, sigmasked); 61591.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61601.1Skamil 61611.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61621.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61631.1Skamil 61641.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61651.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61661.1Skamil 61671.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61681.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61691.1Skamil 61701.13Schristos DPRINTF("Before creating new in child\n"); 61711.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61721.1Skamil 61731.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61741.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61751.1Skamil 61761.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61771.1Skamil "are the same\n", lid, the_lwp_id); 61781.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61791.1Skamil 61801.13Schristos DPRINTF("Before exiting of the child process\n"); 61811.1Skamil _exit(exitval); 61821.1Skamil } 61831.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61841.1Skamil 61851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61871.1Skamil 61881.1Skamil validate_status_stopped(status, sigval); 61891.1Skamil 61901.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61911.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 61921.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61931.1Skamil 61941.13Schristos DPRINTF("Before resuming the child process where it left off and " 61951.1Skamil "without signal to be sent\n"); 61961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61971.1Skamil 61981.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61991.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62011.1Skamil 62021.1Skamil validate_status_stopped(status, sigmasked); 62031.1Skamil 62041.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 62051.1Skamil 62061.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 62071.1Skamil 62081.1Skamil lid = state.pe_lwp; 62091.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 62101.1Skamil 62111.13Schristos DPRINTF("Before resuming the child process where it left off and " 62121.1Skamil "without signal to be sent\n"); 62131.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62141.1Skamil 62151.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62161.1Skamil TWAIT_FNAME); 62171.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62181.1Skamil 62191.1Skamil validate_status_exited(status, exitval); 62201.1Skamil 62211.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62221.1Skamil TWAIT_FNAME); 62231.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62241.1Skamil} 62251.1Skamil 62261.1SkamilATF_TC(signal10); 62271.1SkamilATF_TC_HEAD(signal10, tc) 62281.1Skamil{ 62291.1Skamil atf_tc_set_md_var(tc, "descr", 62301.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 62311.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 62321.1Skamil} 62331.1Skamil 62341.1SkamilATF_TC_BODY(signal10, tc) 62351.1Skamil{ 62361.1Skamil const int exitval = 5; 62371.1Skamil const int sigval = SIGSTOP; 62381.1Skamil const int sigmasked = SIGTRAP; 62391.1Skamil pid_t child, wpid; 62401.1Skamil#if defined(TWAIT_HAVE_STATUS) 62411.1Skamil int status; 62421.1Skamil#endif 62431.1Skamil sigset_t intmask; 62441.1Skamil ptrace_state_t state; 62451.1Skamil const int slen = sizeof(state); 62461.1Skamil ptrace_event_t event; 62471.1Skamil const int elen = sizeof(event); 62481.1Skamil ucontext_t uc; 62491.1Skamil lwpid_t lid; 62501.1Skamil static const size_t ssize = 16*1024; 62511.1Skamil void *stack; 62521.1Skamil 62531.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62541.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62551.1Skamil if (child == 0) { 62561.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62571.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62581.1Skamil 62591.1Skamil sigemptyset(&intmask); 62601.1Skamil sigaddset(&intmask, sigmasked); 62611.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62621.1Skamil 62631.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62641.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62651.1Skamil 62661.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62671.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62681.1Skamil 62691.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62701.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 62711.1Skamil 62721.13Schristos DPRINTF("Before creating new in child\n"); 62731.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62741.1Skamil 62751.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62761.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62771.1Skamil 62781.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62791.1Skamil "are the same\n", lid, the_lwp_id); 62801.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62811.1Skamil 62821.13Schristos DPRINTF("Before exiting of the child process\n"); 62831.1Skamil _exit(exitval); 62841.1Skamil } 62851.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62861.1Skamil 62871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62891.1Skamil 62901.1Skamil validate_status_stopped(status, sigval); 62911.1Skamil 62921.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 62931.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 62941.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 62951.1Skamil 62961.13Schristos DPRINTF("Before resuming the child process where it left off and " 62971.1Skamil "without signal to be sent\n"); 62981.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62991.1Skamil 63001.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63011.1Skamil "SIGTRAP\n", TWAIT_FNAME); 63021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63031.1Skamil 63041.1Skamil validate_status_stopped(status, sigmasked); 63051.1Skamil 63061.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 63071.1Skamil 63081.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 63091.1Skamil 63101.1Skamil lid = state.pe_lwp; 63111.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 63121.1Skamil 63131.13Schristos DPRINTF("Before resuming the child process where it left off and " 63141.1Skamil "without signal to be sent\n"); 63151.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63161.1Skamil 63171.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63181.1Skamil TWAIT_FNAME); 63191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63201.1Skamil 63211.1Skamil validate_status_exited(status, exitval); 63221.1Skamil 63231.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63241.1Skamil TWAIT_FNAME); 63251.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63261.1Skamil} 63271.1Skamil 63281.1Skamilstatic void 63291.1Skamillwp_main_stop(void *arg) 63301.1Skamil{ 63311.1Skamil the_lwp_id = _lwp_self(); 63321.1Skamil 63331.1Skamil raise(SIGTRAP); 63341.1Skamil 63351.1Skamil _lwp_exit(); 63361.1Skamil} 63371.1Skamil 63381.1SkamilATF_TC(suspend2); 63391.1SkamilATF_TC_HEAD(suspend2, tc) 63401.1Skamil{ 63411.1Skamil atf_tc_set_md_var(tc, "descr", 63421.1Skamil "Verify that the while the only thread within a process is " 63431.1Skamil "suspended, the whole process cannot be unstopped"); 63441.1Skamil} 63451.1Skamil 63461.1SkamilATF_TC_BODY(suspend2, tc) 63471.1Skamil{ 63481.1Skamil const int exitval = 5; 63491.1Skamil const int sigval = SIGSTOP; 63501.1Skamil pid_t child, wpid; 63511.1Skamil#if defined(TWAIT_HAVE_STATUS) 63521.1Skamil int status; 63531.1Skamil#endif 63541.1Skamil struct ptrace_siginfo psi; 63551.1Skamil 63561.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63571.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63581.1Skamil if (child == 0) { 63591.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63601.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63611.1Skamil 63621.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63631.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63641.1Skamil 63651.13Schristos DPRINTF("Before exiting of the child process\n"); 63661.1Skamil _exit(exitval); 63671.1Skamil } 63681.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63691.1Skamil 63701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63721.1Skamil 63731.1Skamil validate_status_stopped(status, sigval); 63741.1Skamil 63751.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 63761.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 63771.1Skamil 63781.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 63791.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 63801.1Skamil 63811.13Schristos DPRINTF("Before resuming the child process where it left off and " 63821.1Skamil "without signal to be sent\n"); 63831.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 63841.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 63851.1Skamil 63861.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 63871.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 63881.1Skamil 63891.13Schristos DPRINTF("Before resuming the child process where it left off and " 63901.1Skamil "without signal to be sent\n"); 63911.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63921.1Skamil 63931.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63941.1Skamil TWAIT_FNAME); 63951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63961.1Skamil 63971.1Skamil validate_status_exited(status, exitval); 63981.1Skamil 63991.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64001.1Skamil TWAIT_FNAME); 64011.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64021.1Skamil} 64031.1Skamil 64041.1SkamilATF_TC(resume1); 64051.1SkamilATF_TC_HEAD(resume1, tc) 64061.1Skamil{ 64071.1Skamil atf_tc_set_md_var(tc, "descr", 64081.1Skamil "Verify that a thread can be suspended by a debugger and later " 64091.1Skamil "resumed by the debugger"); 64101.1Skamil} 64111.1Skamil 64121.1SkamilATF_TC_BODY(resume1, tc) 64131.1Skamil{ 64141.1Skamil struct msg_fds fds; 64151.1Skamil const int exitval = 5; 64161.1Skamil const int sigval = SIGSTOP; 64171.1Skamil pid_t child, wpid; 64181.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 64191.1Skamil#if defined(TWAIT_HAVE_STATUS) 64201.1Skamil int status; 64211.1Skamil#endif 64221.1Skamil ucontext_t uc; 64231.1Skamil lwpid_t lid; 64241.1Skamil static const size_t ssize = 16*1024; 64251.1Skamil void *stack; 64261.1Skamil struct ptrace_lwpinfo pl; 64271.1Skamil struct ptrace_siginfo psi; 64281.1Skamil 64291.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 64301.1Skamil 64311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64331.1Skamil if (child == 0) { 64341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64361.1Skamil 64371.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64381.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64391.1Skamil 64401.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 64411.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 64421.1Skamil 64431.13Schristos DPRINTF("Before making context for new lwp in child\n"); 64441.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 64451.1Skamil 64461.13Schristos DPRINTF("Before creating new in child\n"); 64471.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 64481.1Skamil 64491.1Skamil CHILD_TO_PARENT("Message", fds, msg); 64501.1Skamil 64511.1Skamil raise(SIGINT); 64521.1Skamil 64531.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 64541.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 64551.1Skamil 64561.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 64571.1Skamil "are the same\n", lid, the_lwp_id); 64581.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 64591.1Skamil 64601.13Schristos DPRINTF("Before exiting of the child process\n"); 64611.1Skamil _exit(exitval); 64621.1Skamil } 64631.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64641.1Skamil 64651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64671.1Skamil 64681.1Skamil validate_status_stopped(status, sigval); 64691.1Skamil 64701.13Schristos DPRINTF("Before resuming the child process where it left off and " 64711.1Skamil "without signal to be sent\n"); 64721.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64731.1Skamil 64741.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64751.1Skamil "SIGTRAP\n", TWAIT_FNAME); 64761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64771.1Skamil 64781.1Skamil validate_status_stopped(status, SIGTRAP); 64791.1Skamil 64801.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64811.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64821.1Skamil 64831.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64841.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64851.1Skamil 64861.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 64871.1Skamil 64881.13Schristos DPRINTF("Before resuming the child process where it left off and " 64891.1Skamil "without signal to be sent\n"); 64901.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64911.1Skamil 64921.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64931.1Skamil "SIGINT\n", TWAIT_FNAME); 64941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64951.1Skamil 64961.1Skamil validate_status_stopped(status, SIGINT); 64971.1Skamil 64981.1Skamil pl.pl_lwpid = 0; 64991.1Skamil 65001.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65011.1Skamil while (pl.pl_lwpid != 0) { 65021.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65031.1Skamil switch (pl.pl_lwpid) { 65041.1Skamil case 1: 65051.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 65061.1Skamil break; 65071.1Skamil case 2: 65081.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 65091.1Skamil break; 65101.1Skamil } 65111.1Skamil } 65121.1Skamil 65131.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65141.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65151.1Skamil 65161.13Schristos DPRINTF("Before resuming the child process where it left off and " 65171.1Skamil "without signal to be sent\n"); 65181.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65191.1Skamil 65201.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65211.1Skamil TWAIT_FNAME); 65221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65231.1Skamil 65241.1Skamil validate_status_exited(status, exitval); 65251.1Skamil 65261.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65271.1Skamil TWAIT_FNAME); 65281.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65291.1Skamil 65301.1Skamil msg_close(&fds); 65311.1Skamil} 65321.1Skamil 65331.1SkamilATF_TC(syscall1); 65341.1SkamilATF_TC_HEAD(syscall1, tc) 65351.1Skamil{ 65361.1Skamil atf_tc_set_md_var(tc, "descr", 65371.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 65381.1Skamil} 65391.1Skamil 65401.1SkamilATF_TC_BODY(syscall1, tc) 65411.1Skamil{ 65421.1Skamil const int exitval = 5; 65431.1Skamil const int sigval = SIGSTOP; 65441.1Skamil pid_t child, wpid; 65451.1Skamil#if defined(TWAIT_HAVE_STATUS) 65461.1Skamil int status; 65471.1Skamil#endif 65481.1Skamil struct ptrace_siginfo info; 65491.1Skamil memset(&info, 0, sizeof(info)); 65501.1Skamil 65511.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65521.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65531.1Skamil if (child == 0) { 65541.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65551.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65561.1Skamil 65571.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65581.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65591.1Skamil 65601.1Skamil syscall(SYS_getpid); 65611.1Skamil 65621.13Schristos DPRINTF("Before exiting of the child process\n"); 65631.1Skamil _exit(exitval); 65641.1Skamil } 65651.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65661.1Skamil 65671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65691.1Skamil 65701.1Skamil validate_status_stopped(status, sigval); 65711.1Skamil 65721.13Schristos DPRINTF("Before resuming the child process where it left off and " 65731.1Skamil "without signal to be sent\n"); 65741.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65751.1Skamil 65761.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65781.1Skamil 65791.1Skamil validate_status_stopped(status, SIGTRAP); 65801.1Skamil 65811.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 65821.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 65831.1Skamil 65841.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 65851.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 65861.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 65871.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 65881.1Skamil 65891.13Schristos DPRINTF("Before resuming the child process where it left off and " 65901.1Skamil "without signal to be sent\n"); 65911.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65921.1Skamil 65931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65951.1Skamil 65961.1Skamil validate_status_stopped(status, SIGTRAP); 65971.1Skamil 65981.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 65991.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66001.1Skamil 66011.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 66021.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66031.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 66041.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 66051.1Skamil 66061.13Schristos DPRINTF("Before resuming the child process where it left off and " 66071.1Skamil "without signal to be sent\n"); 66081.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66091.1Skamil 66101.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66121.1Skamil 66131.1Skamil validate_status_exited(status, exitval); 66141.1Skamil 66151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66161.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66171.1Skamil} 66181.1Skamil 66191.1SkamilATF_TC(syscallemu1); 66201.1SkamilATF_TC_HEAD(syscallemu1, tc) 66211.1Skamil{ 66221.1Skamil atf_tc_set_md_var(tc, "descr", 66231.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 66241.1Skamil} 66251.1Skamil 66261.1SkamilATF_TC_BODY(syscallemu1, tc) 66271.1Skamil{ 66281.1Skamil const int exitval = 5; 66291.1Skamil const int sigval = SIGSTOP; 66301.1Skamil pid_t child, wpid; 66311.1Skamil#if defined(TWAIT_HAVE_STATUS) 66321.1Skamil int status; 66331.1Skamil#endif 66341.1Skamil 66351.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 66361.6Skamil /* syscallemu does not work on sparc (32-bit) */ 66371.6Skamil atf_tc_expect_fail("PR kern/52166"); 66381.6Skamil#endif 66391.6Skamil 66401.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66411.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66421.1Skamil if (child == 0) { 66431.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66441.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66451.1Skamil 66461.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66471.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66481.1Skamil 66491.1Skamil syscall(SYS_exit, 100); 66501.1Skamil 66511.13Schristos DPRINTF("Before exiting of the child process\n"); 66521.1Skamil _exit(exitval); 66531.1Skamil } 66541.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66551.1Skamil 66561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66581.1Skamil 66591.1Skamil validate_status_stopped(status, sigval); 66601.1Skamil 66611.13Schristos DPRINTF("Before resuming the child process where it left off and " 66621.1Skamil "without signal to be sent\n"); 66631.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66641.1Skamil 66651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66671.1Skamil 66681.1Skamil validate_status_stopped(status, SIGTRAP); 66691.1Skamil 66701.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 66711.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 66721.1Skamil 66731.13Schristos DPRINTF("Before resuming the child process where it left off and " 66741.1Skamil "without signal to be sent\n"); 66751.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66761.1Skamil 66771.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66781.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66791.1Skamil 66801.1Skamil validate_status_stopped(status, SIGTRAP); 66811.1Skamil 66821.13Schristos DPRINTF("Before resuming the child process where it left off and " 66831.1Skamil "without signal to be sent\n"); 66841.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66851.1Skamil 66861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66881.1Skamil 66891.1Skamil validate_status_exited(status, exitval); 66901.1Skamil 66911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66921.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66931.1Skamil} 66941.1Skamil 66951.103Skamil/// ---------------------------------------------------------------------------- 66961.103Skamil 66971.106Skamilstatic void 66981.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 66991.106Skamil bool trackvforkdone) 67001.106Skamil{ 67011.106Skamil const int exitval = 5; 67021.106Skamil const int exitval2 = 15; 67031.106Skamil const int sigval = SIGSTOP; 67041.106Skamil pid_t child, child2 = 0, wpid; 67051.106Skamil#if defined(TWAIT_HAVE_STATUS) 67061.106Skamil int status; 67071.106Skamil#endif 67081.106Skamil ptrace_state_t state; 67091.106Skamil const int slen = sizeof(state); 67101.106Skamil ptrace_event_t event; 67111.106Skamil const int elen = sizeof(event); 67121.106Skamil 67131.106Skamil const size_t stack_size = 1024 * 1024; 67141.106Skamil void *stack, *stack_base; 67151.106Skamil 67161.106Skamil stack = malloc(stack_size); 67171.106Skamil ATF_REQUIRE(stack != NULL); 67181.106Skamil 67191.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 67201.106Skamil stack_base = stack; 67211.106Skamil#else 67221.106Skamil stack_base = (char *)stack + stack_size; 67231.106Skamil#endif 67241.106Skamil 67251.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 67261.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 67271.106Skamil if (child == 0) { 67281.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67291.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67301.106Skamil 67311.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67321.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 67331.106Skamil 67341.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 67351.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 67361.106Skamil 67371.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 67381.106Skamil child2); 67391.106Skamil 67401.106Skamil // XXX WALLSIG? 67411.106Skamil FORKEE_REQUIRE_SUCCESS 67421.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 67431.106Skamil 67441.106Skamil forkee_status_exited(status, exitval2); 67451.106Skamil 67461.106Skamil DPRINTF("Before exiting of the child process\n"); 67471.106Skamil _exit(exitval); 67481.106Skamil } 67491.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67501.106Skamil 67511.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67521.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67531.106Skamil 67541.106Skamil validate_status_stopped(status, sigval); 67551.106Skamil 67561.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 67571.106Skamil trackfork ? "|PTRACE_FORK" : "", 67581.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 67591.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 67601.106Skamil event.pe_set_event = 0; 67611.106Skamil if (trackfork) 67621.106Skamil event.pe_set_event |= PTRACE_FORK; 67631.106Skamil if (trackvfork) 67641.106Skamil event.pe_set_event |= PTRACE_VFORK; 67651.106Skamil if (trackvforkdone) 67661.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 67671.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 67681.106Skamil 67691.106Skamil DPRINTF("Before resuming the child process where it left off and " 67701.106Skamil "without signal to be sent\n"); 67711.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67721.106Skamil 67731.106Skamil#if defined(TWAIT_HAVE_PID) 67741.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 67751.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 67761.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 67771.106Skamil child); 67781.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 67791.106Skamil child); 67801.106Skamil 67811.106Skamil validate_status_stopped(status, SIGTRAP); 67821.106Skamil 67831.106Skamil SYSCALL_REQUIRE( 67841.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 67851.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 67861.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 67871.106Skamil PTRACE_FORK); 67881.106Skamil } 67891.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 67901.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 67911.106Skamil PTRACE_VFORK); 67921.106Skamil } 67931.106Skamil 67941.106Skamil child2 = state.pe_other_pid; 67951.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 67961.106Skamil 67971.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 67981.106Skamil "%d\n", TWAIT_FNAME, child2, child); 67991.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 68001.106Skamil child2); 68011.106Skamil 68021.106Skamil validate_status_stopped(status, SIGTRAP); 68031.106Skamil 68041.106Skamil SYSCALL_REQUIRE( 68051.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 68061.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68071.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68081.106Skamil PTRACE_FORK); 68091.106Skamil } 68101.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 68111.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68121.106Skamil PTRACE_VFORK); 68131.106Skamil } 68141.106Skamil 68151.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 68161.106Skamil 68171.106Skamil DPRINTF("Before resuming the forkee process where it left off " 68181.106Skamil "and without signal to be sent\n"); 68191.106Skamil SYSCALL_REQUIRE( 68201.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 68211.106Skamil 68221.106Skamil DPRINTF("Before resuming the child process where it left off " 68231.106Skamil "and without signal to be sent\n"); 68241.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68251.106Skamil } 68261.106Skamil#endif 68271.106Skamil 68281.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 68291.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68301.106Skamil child); 68311.106Skamil TWAIT_REQUIRE_SUCCESS( 68321.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 68331.106Skamil 68341.106Skamil validate_status_stopped(status, SIGTRAP); 68351.106Skamil 68361.106Skamil SYSCALL_REQUIRE( 68371.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68381.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 68391.106Skamil 68401.106Skamil child2 = state.pe_other_pid; 68411.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 68421.106Skamil child2); 68431.106Skamil 68441.106Skamil DPRINTF("Before resuming the child process where it left off " 68451.106Skamil "and without signal to be sent\n"); 68461.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68471.106Skamil } 68481.106Skamil 68491.103Skamil#if defined(TWAIT_HAVE_PID) 68501.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68511.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68521.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 68531.106Skamil "\n", TWAIT_FNAME); 68541.106Skamil TWAIT_REQUIRE_SUCCESS( 68551.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 68561.106Skamil 68571.106Skamil validate_status_exited(status, exitval2); 68581.106Skamil 68591.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 68601.106Skamil "process\n", TWAIT_FNAME); 68611.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 68621.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 68631.106Skamil } 68641.106Skamil#endif 68651.106Skamil 68661.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 68671.106Skamil "SIGCHLD\n", TWAIT_FNAME); 68681.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68691.106Skamil 68701.106Skamil validate_status_stopped(status, SIGCHLD); 68711.106Skamil 68721.106Skamil DPRINTF("Before resuming the child process where it left off and " 68731.106Skamil "without signal to be sent\n"); 68741.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68751.106Skamil 68761.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 68771.106Skamil TWAIT_FNAME); 68781.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68791.106Skamil 68801.106Skamil validate_status_exited(status, exitval); 68811.103Skamil 68821.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 68831.106Skamil TWAIT_FNAME); 68841.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68851.106Skamil} 68861.103Skamil 68871.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 68881.106SkamilATF_TC(name); \ 68891.106SkamilATF_TC_HEAD(name, tc) \ 68901.106Skamil{ \ 68911.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 68921.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 68931.106Skamil #flags, \ 68941.106Skamil tfork ? "|PTRACE_FORK" : "", \ 68951.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 68961.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 68971.106Skamil} \ 68981.106Skamil \ 68991.106SkamilATF_TC_BODY(name, tc) \ 69001.106Skamil{ \ 69011.106Skamil \ 69021.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 69031.103Skamil} 69041.103Skamil 69051.106SkamilCLONE_TEST(clone1, 0, false, false, false) 69061.106Skamil#if defined(TWAIT_HAVE_PID) 69071.106SkamilCLONE_TEST(clone2, 0, true, false, false) 69081.106SkamilCLONE_TEST(clone3, 0, false, true, false) 69091.106SkamilCLONE_TEST(clone4, 0, true, true, false) 69101.106Skamil#endif 69111.106SkamilCLONE_TEST(clone5, 0, false, false, true) 69121.106Skamil#if defined(TWAIT_HAVE_PID) 69131.106SkamilCLONE_TEST(clone6, 0, true, false, true) 69141.106SkamilCLONE_TEST(clone7, 0, false, true, true) 69151.106SkamilCLONE_TEST(clone8, 0, true, true, true) 69161.106Skamil#endif 69171.106Skamil 69181.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 69191.106Skamil#if defined(TWAIT_HAVE_PID) 69201.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 69211.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 69221.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 69231.106Skamil#endif 69241.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 69251.106Skamil#if defined(TWAIT_HAVE_PID) 69261.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 69271.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 69281.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 69291.106Skamil#endif 69301.106Skamil 69311.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 69321.106Skamil#if defined(TWAIT_HAVE_PID) 69331.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 69341.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 69351.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 69361.106Skamil#endif 69371.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 69381.106Skamil#if defined(TWAIT_HAVE_PID) 69391.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 69401.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 69411.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 69421.106Skamil#endif 69431.106Skamil 69441.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 69451.106Skamil#if defined(TWAIT_HAVE_PID) 69461.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 69471.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 69481.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 69491.106Skamil#endif 69501.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 69511.106Skamil#if defined(TWAIT_HAVE_PID) 69521.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 69531.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 69541.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 69551.106Skamil#endif 69561.106Skamil 69571.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 69581.106Skamil#if defined(TWAIT_HAVE_PID) 69591.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 69601.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 69611.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 69621.106Skamil#endif 69631.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 69641.106Skamil#if defined(TWAIT_HAVE_PID) 69651.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 69661.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 69671.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 69681.106Skamil#endif 69691.106Skamil 69701.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 69711.106Skamil#if defined(TWAIT_HAVE_PID) 69721.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 69731.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 69741.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 69751.106Skamil#endif 69761.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 69771.106Skamil#if defined(TWAIT_HAVE_PID) 69781.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 69791.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 69801.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 69811.106Skamil#endif 69821.106Skamil 69831.106Skamil/// ---------------------------------------------------------------------------- 69841.106Skamil 69851.106Skamil#if defined(TWAIT_HAVE_PID) 69861.103Skamilstatic void 69871.106Skamilclone_body2(int flags, bool masked, bool ignored) 69881.103Skamil{ 69891.103Skamil const int exitval = 5; 69901.103Skamil const int exitval2 = 15; 69911.103Skamil const int sigval = SIGSTOP; 69921.103Skamil pid_t child, child2 = 0, wpid; 69931.103Skamil#if defined(TWAIT_HAVE_STATUS) 69941.103Skamil int status; 69951.103Skamil#endif 69961.103Skamil ptrace_state_t state; 69971.103Skamil const int slen = sizeof(state); 69981.103Skamil ptrace_event_t event; 69991.103Skamil const int elen = sizeof(event); 70001.103Skamil struct sigaction sa; 70011.103Skamil struct ptrace_siginfo info; 70021.103Skamil sigset_t intmask; 70031.103Skamil struct kinfo_proc2 kp; 70041.103Skamil size_t len = sizeof(kp); 70051.103Skamil 70061.103Skamil int name[6]; 70071.103Skamil const size_t namelen = __arraycount(name); 70081.103Skamil ki_sigset_t kp_sigmask; 70091.103Skamil ki_sigset_t kp_sigignore; 70101.103Skamil 70111.103Skamil const size_t stack_size = 1024 * 1024; 70121.103Skamil void *stack, *stack_base; 70131.103Skamil 70141.103Skamil stack = malloc(stack_size); 70151.103Skamil ATF_REQUIRE(stack != NULL); 70161.103Skamil 70171.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 70181.103Skamil stack_base = stack; 70191.103Skamil#else 70201.103Skamil stack_base = (char *)stack + stack_size; 70211.103Skamil#endif 70221.103Skamil 70231.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70241.103Skamil if (child == 0) { 70251.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70261.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70271.103Skamil 70281.103Skamil if (masked) { 70291.103Skamil sigemptyset(&intmask); 70301.103Skamil sigaddset(&intmask, SIGTRAP); 70311.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 70321.103Skamil } 70331.103Skamil 70341.103Skamil if (ignored) { 70351.103Skamil memset(&sa, 0, sizeof(sa)); 70361.103Skamil sa.sa_handler = SIG_IGN; 70371.103Skamil sigemptyset(&sa.sa_mask); 70381.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 70391.103Skamil } 70401.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70411.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 70421.103Skamil 70431.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 70441.103Skamil flags); 70451.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 70461.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 70471.103Skamil 70481.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 70491.103Skamil child2); 70501.103Skamil 70511.103Skamil // XXX WALLSIG? 70521.103Skamil FORKEE_REQUIRE_SUCCESS 70531.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 70541.103Skamil 70551.103Skamil forkee_status_exited(status, exitval2); 70561.103Skamil 70571.103Skamil DPRINTF("Before exiting of the child process\n"); 70581.103Skamil _exit(exitval); 70591.103Skamil } 70601.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 70611.103Skamil 70621.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 70631.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70641.103Skamil 70651.103Skamil validate_status_stopped(status, sigval); 70661.103Skamil 70671.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 70681.103Skamil SYSCALL_REQUIRE( 70691.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 70701.103Skamil 70711.103Skamil DPRINTF("Before checking siginfo_t\n"); 70721.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 70731.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 70741.103Skamil 70751.103Skamil name[0] = CTL_KERN, 70761.103Skamil name[1] = KERN_PROC2, 70771.103Skamil name[2] = KERN_PROC_PID; 70781.103Skamil name[3] = child; 70791.103Skamil name[4] = sizeof(kp); 70801.103Skamil name[5] = 1; 70811.103Skamil 70821.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 70831.103Skamil 70841.103Skamil if (masked) 70851.103Skamil kp_sigmask = kp.p_sigmask; 70861.103Skamil 70871.103Skamil if (ignored) 70881.103Skamil kp_sigignore = kp.p_sigignore; 70891.103Skamil 70901.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 70911.103Skamil "EVENT_MASK for the child %d\n", child); 70921.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 70931.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 70941.103Skamil 70951.103Skamil DPRINTF("Before resuming the child process where it left off and " 70961.103Skamil "without signal to be sent\n"); 70971.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70981.103Skamil 70991.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 71001.103Skamil child); 71011.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71021.103Skamil child); 71031.103Skamil 71041.103Skamil validate_status_stopped(status, SIGTRAP); 71051.103Skamil 71061.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71071.103Skamil 71081.103Skamil if (masked) { 71091.103Skamil DPRINTF("kp_sigmask=" 71101.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71111.103Skamil PRIx32 "\n", 71121.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71131.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71141.103Skamil 71151.103Skamil DPRINTF("kp.p_sigmask=" 71161.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71171.103Skamil PRIx32 "\n", 71181.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 71191.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 71201.103Skamil 71211.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 71221.103Skamil sizeof(kp_sigmask))); 71231.103Skamil } 71241.103Skamil 71251.103Skamil if (ignored) { 71261.103Skamil DPRINTF("kp_sigignore=" 71271.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71281.103Skamil PRIx32 "\n", 71291.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71301.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71311.103Skamil 71321.103Skamil DPRINTF("kp.p_sigignore=" 71331.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71341.103Skamil PRIx32 "\n", 71351.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 71361.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 71371.103Skamil 71381.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 71391.103Skamil sizeof(kp_sigignore))); 71401.103Skamil } 71411.103Skamil 71421.103Skamil SYSCALL_REQUIRE( 71431.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71441.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 71451.103Skamil child2); 71461.103Skamil if (!(flags & CLONE_VFORK)) { 71471.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 71481.103Skamil PTRACE_FORK); 71491.103Skamil } else { 71501.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 71511.103Skamil PTRACE_VFORK); 71521.103Skamil } 71531.103Skamil 71541.103Skamil child2 = state.pe_other_pid; 71551.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 71561.103Skamil 71571.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 71581.103Skamil "%d\n", TWAIT_FNAME, child2, child); 71591.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 71601.103Skamil child2); 71611.103Skamil 71621.103Skamil validate_status_stopped(status, SIGTRAP); 71631.103Skamil 71641.103Skamil name[3] = child2; 71651.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71661.103Skamil 71671.103Skamil if (masked) { 71681.103Skamil DPRINTF("kp_sigmask=" 71691.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71701.103Skamil PRIx32 "\n", 71711.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71721.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71731.103Skamil 71741.103Skamil DPRINTF("kp.p_sigmask=" 71751.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71761.103Skamil PRIx32 "\n", 71771.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 71781.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 71791.103Skamil 71801.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 71811.103Skamil sizeof(kp_sigmask))); 71821.103Skamil } 71831.103Skamil 71841.103Skamil if (ignored) { 71851.103Skamil DPRINTF("kp_sigignore=" 71861.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71871.103Skamil PRIx32 "\n", 71881.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71891.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71901.103Skamil 71911.103Skamil DPRINTF("kp.p_sigignore=" 71921.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71931.103Skamil PRIx32 "\n", 71941.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 71951.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 71961.103Skamil 71971.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 71981.103Skamil sizeof(kp_sigignore))); 71991.103Skamil } 72001.103Skamil 72011.103Skamil SYSCALL_REQUIRE( 72021.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 72031.103Skamil if (!(flags & CLONE_VFORK)) { 72041.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72051.103Skamil PTRACE_FORK); 72061.103Skamil } else { 72071.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72081.103Skamil PTRACE_VFORK); 72091.103Skamil } 72101.103Skamil 72111.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 72121.103Skamil 72131.103Skamil DPRINTF("Before resuming the forkee process where it left off " 72141.103Skamil "and without signal to be sent\n"); 72151.103Skamil SYSCALL_REQUIRE( 72161.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 72171.103Skamil 72181.103Skamil DPRINTF("Before resuming the child process where it left off " 72191.103Skamil "and without signal to be sent\n"); 72201.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72211.103Skamil 72221.103Skamil if (flags & CLONE_VFORK) { 72231.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72241.103Skamil child); 72251.103Skamil TWAIT_REQUIRE_SUCCESS( 72261.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 72271.103Skamil 72281.103Skamil validate_status_stopped(status, SIGTRAP); 72291.103Skamil 72301.103Skamil name[3] = child; 72311.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72321.103Skamil 72331.103Skamil /* 72341.103Skamil * SIGCHLD is now pending in the signal queue and 72351.103Skamil * the kernel presents it to userland as a masked signal. 72361.103Skamil */ 72371.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 72381.103Skamil 72391.103Skamil if (masked) { 72401.103Skamil DPRINTF("kp_sigmask=" 72411.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72421.103Skamil PRIx32 "\n", 72431.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72441.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72451.103Skamil 72461.103Skamil DPRINTF("kp.p_sigmask=" 72471.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72481.103Skamil PRIx32 "\n", 72491.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72501.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72511.103Skamil 72521.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72531.103Skamil sizeof(kp_sigmask))); 72541.103Skamil } 72551.103Skamil 72561.103Skamil if (ignored) { 72571.103Skamil DPRINTF("kp_sigignore=" 72581.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72591.103Skamil PRIx32 "\n", 72601.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72611.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72621.103Skamil 72631.103Skamil DPRINTF("kp.p_sigignore=" 72641.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72651.103Skamil PRIx32 "\n", 72661.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72671.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72681.103Skamil 72691.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72701.103Skamil sizeof(kp_sigignore))); 72711.103Skamil } 72721.103Skamil 72731.103Skamil SYSCALL_REQUIRE( 72741.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 72751.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 72761.103Skamil 72771.103Skamil child2 = state.pe_other_pid; 72781.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 72791.103Skamil child2); 72801.103Skamil 72811.103Skamil DPRINTF("Before resuming the child process where it left off " 72821.103Skamil "and without signal to be sent\n"); 72831.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72841.103Skamil } 72851.103Skamil 72861.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 72871.103Skamil "\n", TWAIT_FNAME); 72881.103Skamil TWAIT_REQUIRE_SUCCESS( 72891.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 72901.103Skamil 72911.103Skamil validate_status_exited(status, exitval2); 72921.103Skamil 72931.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 72941.103Skamil "process\n", TWAIT_FNAME); 72951.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 72961.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 72971.103Skamil 72981.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 72991.103Skamil "SIGCHLD\n", TWAIT_FNAME); 73001.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73011.103Skamil 73021.103Skamil validate_status_stopped(status, SIGCHLD); 73031.103Skamil 73041.103Skamil DPRINTF("Before resuming the child process where it left off and " 73051.103Skamil "without signal to be sent\n"); 73061.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73071.103Skamil 73081.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 73091.103Skamil TWAIT_FNAME); 73101.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73111.103Skamil 73121.103Skamil validate_status_exited(status, exitval); 73131.103Skamil 73141.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 73151.103Skamil TWAIT_FNAME); 73161.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 73171.103Skamil} 73181.103Skamil 73191.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 73201.103SkamilATF_TC(name); \ 73211.103SkamilATF_TC_HEAD(name, tc) \ 73221.103Skamil{ \ 73231.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 73241.103Skamil " regardless of signal %s%s", \ 73251.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 73261.103Skamil} \ 73271.103Skamil \ 73281.103SkamilATF_TC_BODY(name, tc) \ 73291.103Skamil{ \ 73301.103Skamil \ 73311.106Skamil clone_body2(flags, masked, ignored); \ 73321.103Skamil} 73331.103Skamil 73341.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 73351.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 73361.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 73371.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 73381.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 73391.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 73401.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 73411.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 73421.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 73431.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 73441.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 73451.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 73461.103Skamil#endif 73471.103Skamil 73481.103Skamil/// ---------------------------------------------------------------------------- 73491.103Skamil 73501.107Skamil#if defined(TWAIT_HAVE_PID) 73511.107Skamilstatic void 73521.107Skamiltraceme_vfork_clone_body(int flags) 73531.107Skamil{ 73541.107Skamil const int exitval = 5; 73551.107Skamil const int exitval2 = 15; 73561.107Skamil pid_t child, child2 = 0, wpid; 73571.107Skamil#if defined(TWAIT_HAVE_STATUS) 73581.107Skamil int status; 73591.107Skamil#endif 73601.107Skamil 73611.107Skamil const size_t stack_size = 1024 * 1024; 73621.107Skamil void *stack, *stack_base; 73631.107Skamil 73641.107Skamil stack = malloc(stack_size); 73651.107Skamil ATF_REQUIRE(stack != NULL); 73661.107Skamil 73671.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 73681.107Skamil stack_base = stack; 73691.107Skamil#else 73701.107Skamil stack_base = (char *)stack + stack_size; 73711.107Skamil#endif 73721.107Skamil 73731.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 73741.107Skamil if (child == 0) { 73751.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 73761.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 73771.107Skamil 73781.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 73791.107Skamil flags); 73801.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 73811.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 73821.107Skamil 73831.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 73841.107Skamil child2); 73851.107Skamil 73861.107Skamil // XXX WALLSIG? 73871.107Skamil FORKEE_REQUIRE_SUCCESS 73881.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 73891.107Skamil 73901.107Skamil forkee_status_exited(status, exitval2); 73911.107Skamil 73921.107Skamil DPRINTF("Before exiting of the child process\n"); 73931.107Skamil _exit(exitval); 73941.107Skamil } 73951.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 73961.107Skamil 73971.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 73981.107Skamil TWAIT_FNAME); 73991.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74001.107Skamil 74011.107Skamil validate_status_exited(status, exitval); 74021.107Skamil 74031.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74041.107Skamil TWAIT_FNAME); 74051.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74061.107Skamil} 74071.107Skamil 74081.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 74091.107SkamilATF_TC(name); \ 74101.107SkamilATF_TC_HEAD(name, tc) \ 74111.107Skamil{ \ 74121.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 74131.107Skamil "handled correctly with vfork(2)ed tracer", \ 74141.107Skamil #flags); \ 74151.107Skamil} \ 74161.107Skamil \ 74171.107SkamilATF_TC_BODY(name, tc) \ 74181.107Skamil{ \ 74191.107Skamil \ 74201.107Skamil traceme_vfork_clone_body(flags); \ 74211.107Skamil} 74221.107Skamil 74231.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 74241.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 74251.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 74261.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 74271.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 74281.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 74291.107Skamil#endif 74301.107Skamil 74311.107Skamil/// ---------------------------------------------------------------------------- 74321.107Skamil 74331.122Skamilstatic void 74341.122Skamiluser_va0_disable(int operation) 74351.122Skamil{ 74361.122Skamil pid_t child, wpid; 74371.122Skamil#if defined(TWAIT_HAVE_STATUS) 74381.122Skamil int status; 74391.122Skamil#endif 74401.122Skamil const int sigval = SIGSTOP; 74411.122Skamil int rv; 74421.122Skamil 74431.122Skamil struct ptrace_siginfo info; 74441.122Skamil 74451.122Skamil if (get_user_va0_disable() == 0) 74461.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 74471.122Skamil 74481.122Skamil memset(&info, 0, sizeof(info)); 74491.122Skamil 74501.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 74511.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 74521.122Skamil if (child == 0) { 74531.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74541.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74551.122Skamil 74561.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 74571.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 74581.122Skamil 74591.122Skamil /* NOTREACHED */ 74601.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 74611.122Skamil __unreachable(); 74621.122Skamil } 74631.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74641.122Skamil 74651.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74661.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74671.122Skamil 74681.122Skamil validate_status_stopped(status, sigval); 74691.122Skamil 74701.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 74711.122Skamil "child\n"); 74721.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 74731.122Skamil sizeof(info)) != -1); 74741.122Skamil 74751.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 74761.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 74771.122Skamil "si_errno=%#x\n", 74781.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 74791.122Skamil info.psi_siginfo.si_errno); 74801.122Skamil 74811.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 74821.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 74831.122Skamil 74841.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 74851.122Skamil "and without signal to be sent\n"); 74861.122Skamil errno = 0; 74871.122Skamil rv = ptrace(operation, child, (void *)0, 0); 74881.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 74891.122Skamil ATF_REQUIRE_EQ(rv, -1); 74901.122Skamil 74911.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 74921.122Skamil 74931.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74941.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74951.122Skamil validate_status_signaled(status, SIGKILL, 0); 74961.122Skamil 74971.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74981.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74991.122Skamil} 75001.122Skamil 75011.122Skamil#define USER_VA0_DISABLE(test, operation) \ 75021.122SkamilATF_TC(test); \ 75031.122SkamilATF_TC_HEAD(test, tc) \ 75041.122Skamil{ \ 75051.122Skamil atf_tc_set_md_var(tc, "descr", \ 75061.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 75071.122Skamil} \ 75081.122Skamil \ 75091.122SkamilATF_TC_BODY(test, tc) \ 75101.122Skamil{ \ 75111.122Skamil \ 75121.122Skamil user_va0_disable(operation); \ 75131.122Skamil} 75141.122Skamil 75151.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 75161.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 75171.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 75181.122Skamil 75191.122Skamil/// ---------------------------------------------------------------------------- 75201.122Skamil 75211.130Smgorny/* 75221.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 75231.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 75241.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 75251.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 75261.130Smgorny * found, -1 is returned. 75271.130Smgorny */ 75281.130Smgornystatic ssize_t core_find_note(const char *core_path, 75291.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 75301.130Smgorny{ 75311.130Smgorny int core_fd; 75321.130Smgorny Elf *core_elf; 75331.130Smgorny size_t core_numhdr, i; 75341.130Smgorny ssize_t ret = -1; 75351.130Smgorny /* note: we assume note name will be null-terminated */ 75361.130Smgorny size_t name_len = strlen(note_name) + 1; 75371.130Smgorny 75381.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 75391.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 75401.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 75411.130Smgorny 75421.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 75431.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 75441.130Smgorny GElf_Phdr core_hdr; 75451.130Smgorny size_t offset; 75461.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 75471.130Smgorny if (core_hdr.p_type != PT_NOTE) 75481.130Smgorny continue; 75491.130Smgorny 75501.130Smgorny for (offset = core_hdr.p_offset; 75511.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 75521.130Smgorny Elf64_Nhdr note_hdr; 75531.130Smgorny char name_buf[64]; 75541.130Smgorny 75551.130Smgorny switch (gelf_getclass(core_elf)) { 75561.130Smgorny case ELFCLASS64: 75571.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 75581.130Smgorny sizeof(note_hdr), offset) 75591.130Smgorny == sizeof(note_hdr)); 75601.130Smgorny offset += sizeof(note_hdr); 75611.130Smgorny break; 75621.130Smgorny case ELFCLASS32: 75631.130Smgorny { 75641.130Smgorny Elf32_Nhdr tmp_hdr; 75651.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 75661.130Smgorny sizeof(tmp_hdr), offset) 75671.130Smgorny == sizeof(tmp_hdr)); 75681.130Smgorny offset += sizeof(tmp_hdr); 75691.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 75701.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 75711.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 75721.130Smgorny } 75731.130Smgorny break; 75741.130Smgorny } 75751.130Smgorny 75761.130Smgorny /* indicates end of notes */ 75771.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 75781.130Smgorny break; 75791.130Smgorny if (note_hdr.n_namesz == name_len && 75801.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 75811.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 75821.130Smgorny note_hdr.n_namesz, offset) 75831.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 75841.130Smgorny 75851.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 75861.130Smgorny note_hdr.n_type == note_type) 75871.130Smgorny ret = note_hdr.n_descsz; 75881.130Smgorny } 75891.130Smgorny 75901.130Smgorny offset += note_hdr.n_namesz; 75911.130Smgorny /* fix to alignment */ 75921.130Smgorny offset = ((offset + core_hdr.p_align - 1) 75931.130Smgorny / core_hdr.p_align) * core_hdr.p_align; 75941.130Smgorny 75951.130Smgorny /* if name & type matched above */ 75961.130Smgorny if (ret != -1) { 75971.130Smgorny ssize_t read_len = MIN(buf_len, 75981.130Smgorny note_hdr.n_descsz); 75991.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 76001.130Smgorny read_len, offset) == read_len); 76011.130Smgorny break; 76021.130Smgorny } 76031.130Smgorny 76041.130Smgorny offset += note_hdr.n_descsz; 76051.130Smgorny } 76061.130Smgorny } 76071.130Smgorny 76081.130Smgorny elf_end(core_elf); 76091.130Smgorny close(core_fd); 76101.130Smgorny 76111.130Smgorny return ret; 76121.130Smgorny} 76131.130Smgorny 76141.130SmgornyATF_TC(core_dump_procinfo); 76151.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 76161.130Smgorny{ 76171.130Smgorny atf_tc_set_md_var(tc, "descr", 76181.130Smgorny "Trigger a core dump and verify its contents."); 76191.130Smgorny} 76201.130Smgorny 76211.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 76221.130Smgorny{ 76231.130Smgorny const int exitval = 5; 76241.130Smgorny pid_t child, wpid; 76251.130Smgorny#if defined(TWAIT_HAVE_STATUS) 76261.130Smgorny const int sigval = SIGTRAP; 76271.130Smgorny int status; 76281.130Smgorny#endif 76291.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 76301.130Smgorny int core_fd; 76311.130Smgorny struct netbsd_elfcore_procinfo procinfo; 76321.130Smgorny 76331.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 76341.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 76351.130Smgorny if (child == 0) { 76361.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 76371.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 76381.130Smgorny 76391.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 76401.130Smgorny trigger_trap(); 76411.130Smgorny 76421.130Smgorny DPRINTF("Before exiting of the child process\n"); 76431.130Smgorny _exit(exitval); 76441.130Smgorny } 76451.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 76461.130Smgorny 76471.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76481.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76491.130Smgorny 76501.130Smgorny validate_status_stopped(status, sigval); 76511.130Smgorny 76521.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 76531.130Smgorny close(core_fd); 76541.130Smgorny 76551.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 76561.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 76571.130Smgorny != -1); 76581.130Smgorny 76591.130Smgorny DPRINTF("Read core file\n"); 76601.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 76611.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 76621.130Smgorny sizeof(procinfo)); 76631.130Smgorny 76641.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 76651.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 76661.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 76671.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 76681.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 76691.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 76701.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 76711.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 76721.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 76731.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 76741.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 76751.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 76761.130Smgorny ATF_CHECK_EQ(procinfo.cpi_siglwp, 1); 76771.130Smgorny 76781.130Smgorny unlink(core_path); 76791.130Smgorny 76801.130Smgorny DPRINTF("Before resuming the child process where it left off and " 76811.130Smgorny "without signal to be sent\n"); 76821.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 76831.130Smgorny 76841.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76851.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76861.130Smgorny 76871.130Smgorny validate_status_exited(status, exitval); 76881.130Smgorny 76891.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76901.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76911.130Smgorny} 76921.130Smgorny 76931.130Smgorny/// ---------------------------------------------------------------------------- 76941.130Smgorny 76951.138Smgorny#if defined(TWAIT_HAVE_STATUS) 76961.138Smgorny 76971.138SmgornyATF_TC(thread_concurrent_signals); 76981.138SmgornyATF_TC_HEAD(thread_concurrent_signals, tc) 76991.138Smgorny{ 77001.138Smgorny atf_tc_set_md_var(tc, "descr", 77011.138Smgorny "Verify that concurrent signals issued to a single thread " 77021.138Smgorny "are reported correctly"); 77031.138Smgorny} 77041.138Smgorny 77051.138Smgorny/* List of signals to use for the test */ 77061.138Smgornyconst int thread_concurrent_signals_list[] = { 77071.138Smgorny SIGIO, 77081.138Smgorny SIGXCPU, 77091.138Smgorny SIGXFSZ, 77101.138Smgorny SIGVTALRM, 77111.138Smgorny SIGPROF, 77121.138Smgorny SIGWINCH, 77131.138Smgorny SIGINFO, 77141.138Smgorny SIGUSR1, 77151.138Smgorny SIGUSR2 77161.138Smgorny}; 77171.138Smgorny 77181.138Smgornypthread_barrier_t thread_concurrent_signals_barrier; 77191.138Smgorny 77201.138Smgornystatic void * 77211.138Smgornythread_concurrent_signals_thread(void *arg) 77221.138Smgorny{ 77231.138Smgorny int sigval = thread_concurrent_signals_list[ 77241.138Smgorny _lwp_self() % __arraycount(thread_concurrent_signals_list)]; 77251.138Smgorny pthread_barrier_wait(&thread_concurrent_signals_barrier); 77261.138Smgorny DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval), 77271.138Smgorny _lwp_self()); 77281.138Smgorny pthread_kill(pthread_self(), sigval); 77291.138Smgorny return NULL; 77301.138Smgorny} 77311.138Smgorny 77321.138Smgorny#define THREAD_CONCURRENT_SIGNALS_NUM 50 77331.138Smgorny 77341.138SmgornyATF_TC_BODY(thread_concurrent_signals, tc) 77351.138Smgorny{ 77361.138Smgorny const int exitval = 5; 77371.138Smgorny const int sigval = SIGSTOP; 77381.138Smgorny pid_t child, wpid; 77391.138Smgorny int status; 77401.141Skamil struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM] 77411.141Skamil = {{0, 0}}; 77421.138Smgorny unsigned int i; 77431.138Smgorny 77441.138Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 77451.138Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 77461.138Smgorny if (child == 0) { 77471.138Smgorny pthread_t threads[THREAD_CONCURRENT_SIGNALS_NUM]; 77481.138Smgorny 77491.138Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 77501.138Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 77511.138Smgorny 77521.138Smgorny DPRINTF("Before raising %s from child\n", strsignal(sigval)); 77531.138Smgorny FORKEE_ASSERT(raise(sigval) == 0); 77541.138Smgorny 77551.138Smgorny DPRINTF("Before starting threads from the child\n"); 77561.138Smgorny FORKEE_ASSERT(pthread_barrier_init( 77571.138Smgorny &thread_concurrent_signals_barrier, NULL, 77581.138Smgorny __arraycount(threads)) == 0); 77591.138Smgorny 77601.138Smgorny for (i = 0; i < __arraycount(threads); i++) { 77611.138Smgorny FORKEE_ASSERT(pthread_create(&threads[i], NULL, 77621.138Smgorny thread_concurrent_signals_thread, NULL) == 0); 77631.138Smgorny } 77641.138Smgorny 77651.138Smgorny DPRINTF("Before joining threads from the child\n"); 77661.138Smgorny for (i = 0; i < __arraycount(threads); i++) { 77671.138Smgorny FORKEE_ASSERT(pthread_join(threads[i], NULL) == 0); 77681.138Smgorny } 77691.138Smgorny 77701.138Smgorny FORKEE_ASSERT(pthread_barrier_destroy( 77711.138Smgorny &thread_concurrent_signals_barrier) == 0); 77721.138Smgorny 77731.138Smgorny DPRINTF("Before exiting of the child process\n"); 77741.138Smgorny _exit(exitval); 77751.138Smgorny } 77761.138Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 77771.138Smgorny 77781.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77791.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77801.138Smgorny 77811.138Smgorny validate_status_stopped(status, sigval); 77821.138Smgorny 77831.138Smgorny DPRINTF("Before resuming the child process where it left off\n"); 77841.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 77851.138Smgorny 77861.138Smgorny DPRINTF("Before entering signal collection loop\n"); 77871.138Smgorny while (1) { 77881.138Smgorny ptrace_siginfo_t info; 77891.138Smgorny int expected_sig; 77901.138Smgorny 77911.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77921.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 77931.138Smgorny child); 77941.138Smgorny if (WIFEXITED(status)) 77951.138Smgorny break; 77961.138Smgorny /* Note: we use validate_status_stopped() to get nice error 77971.138Smgorny * message. Signal is irrelevant since it won't be reached. 77981.138Smgorny */ 77991.138Smgorny else if (!WIFSTOPPED(status)) 78001.138Smgorny validate_status_stopped(status, 0); 78011.138Smgorny 78021.138Smgorny DPRINTF("Before calling PT_GET_SIGINFO\n"); 78031.138Smgorny SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 78041.138Smgorny sizeof(info)) != -1); 78051.138Smgorny 78061.138Smgorny DPRINTF("Received signal %d from LWP %d (wait: %d)\n", 78071.138Smgorny info.psi_siginfo.si_signo, info.psi_lwpid, 78081.138Smgorny WSTOPSIG(status)); 78091.138Smgorny 78101.138Smgorny expected_sig = thread_concurrent_signals_list[info.psi_lwpid % 78111.138Smgorny __arraycount(thread_concurrent_signals_list)]; 78121.138Smgorny ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, expected_sig, 78131.138Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 78141.138Smgorny expected_sig, info.psi_siginfo.si_signo); 78151.138Smgorny ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig, 78161.138Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 78171.138Smgorny expected_sig, WSTOPSIG(status)); 78181.138Smgorny 78191.141Skamil *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1; 78201.138Smgorny 78211.138Smgorny DPRINTF("Before resuming the child process\n"); 78221.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78231.138Smgorny } 78241.138Smgorny 78251.138Smgorny for (i = 0; i < __arraycount(signal_counts); i++) 78261.141Skamil ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1, 78271.141Skamil "signal_counts[%d].lec_count=%d; lec_lwp=%d", 78281.141Skamil i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 78291.138Smgorny 78301.138Smgorny validate_status_exited(status, exitval); 78311.138Smgorny} 78321.138Smgorny 78331.138Smgorny#endif /*defined(TWAIT_HAVE_STATUS)*/ 78341.138Smgorny 78351.138Smgorny/// ---------------------------------------------------------------------------- 78361.138Smgorny 78371.1Skamil#include "t_ptrace_amd64_wait.h" 78381.1Skamil#include "t_ptrace_i386_wait.h" 78391.1Skamil#include "t_ptrace_x86_wait.h" 78401.1Skamil 78411.1SkamilATF_TP_ADD_TCS(tp) 78421.1Skamil{ 78431.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 78441.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 78451.33Skamil 78461.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 78471.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 78481.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 78491.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 78501.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 78511.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 78521.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 78531.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 78541.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 78551.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 78561.33Skamil 78571.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 78581.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 78591.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 78601.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 78611.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 78621.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 78631.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 78641.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 78651.87Skamil 78661.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 78671.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 78681.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 78691.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 78701.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 78711.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 78721.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 78731.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 78741.86Skamil 78751.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 78761.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 78771.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 78781.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 78791.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 78801.59Skamil 78811.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 78821.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 78831.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 78841.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 78851.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 78861.88Skamil 78871.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 78881.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 78891.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 78901.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 78911.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 78921.88Skamil 78931.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 78941.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 78951.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 78961.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 78971.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 78981.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 78991.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 79001.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 79011.50Skamil 79021.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 79031.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 79041.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 79051.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 79061.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 79071.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 79081.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 79091.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 79101.50Skamil 79111.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 79121.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 79131.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 79141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 79151.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 79161.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 79171.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 79181.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 79191.50Skamil 79201.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 79211.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 79221.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 79231.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 79241.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 79251.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 79261.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 79271.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 79281.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 79291.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 79301.1Skamil 79311.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 79321.37Skamil 79331.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 79341.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 79351.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 79361.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 79371.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 79381.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 79391.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 79401.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 79411.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 79421.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 79431.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 79441.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 79451.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 79461.40Skamil 79471.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 79481.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 79491.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 79501.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 79511.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 79521.41Skamil 79531.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 79541.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 79551.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 79561.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 79571.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 79581.92Skamil 79591.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 79601.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 79611.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 79621.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 79631.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 79641.92Skamil 79651.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 79661.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 79671.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 79681.43Skamil 79691.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 79701.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 79711.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 79721.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 79731.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 79741.59Skamil 79751.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79761.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 79771.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79781.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 79791.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79801.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 79811.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79821.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 79831.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79841.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 79851.94Skamil 79861.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79871.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 79881.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79891.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 79901.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79911.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 79921.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79931.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 79941.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79951.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 79961.94Skamil 79971.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 79981.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 79991.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 80001.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 80011.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 80021.51Skamil 80031.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 80041.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 80051.51Skamil 80061.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 80071.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 80081.51Skamil 80091.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 80101.51Skamil tracee_sees_its_original_parent_getppid); 80111.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 80121.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 80131.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 80141.51Skamil tracee_sees_its_original_parent_procfs_status); 80151.1Skamil 80161.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 80171.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 80181.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 80191.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 80201.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 80211.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 80221.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 80231.1Skamil 80241.31Skamil ATF_TP_ADD_TC(tp, fork1); 80251.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 80261.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 80271.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 80281.31Skamil ATF_TP_ADD_TC(tp, fork5); 80291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 80301.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 80311.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 80321.125Skamil ATF_TP_ADD_TC(tp, fork9); 80331.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 80341.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 80351.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 80361.125Skamil ATF_TP_ADD_TC(tp, fork13); 80371.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 80381.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 80391.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 80401.31Skamil 80411.31Skamil ATF_TP_ADD_TC(tp, vfork1); 80421.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 80431.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 80441.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 80451.31Skamil ATF_TP_ADD_TC(tp, vfork5); 80461.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 80471.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 80481.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 80491.125Skamil ATF_TP_ADD_TC(tp, vfork9); 80501.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 80511.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 80521.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 80531.125Skamil ATF_TP_ADD_TC(tp, vfork13); 80541.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 80551.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 80561.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 80571.1Skamil 80581.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 80591.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 80601.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 80611.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 80621.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 80631.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 80641.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 80651.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 80661.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 80671.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 80681.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 80691.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 80701.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 80711.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 80721.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 80731.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 80741.124Skamil 80751.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 80761.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 80771.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 80781.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 80791.126Skamil 80801.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 80811.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 80821.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 80831.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 80841.116Skamil 80851.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 80861.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 80871.108Skamil 80881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 80891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 80901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 80911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 80921.54Skamil 80931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 80941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 80951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 80961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 80971.54Skamil 80981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 80991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 81001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 81011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 81021.54Skamil 81031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 81041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 81051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 81061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 81071.54Skamil 81081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 81091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 81101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 81111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 81121.54Skamil 81131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 81141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 81151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 81161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 81171.54Skamil 81181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 81191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 81201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 81211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 81221.54Skamil 81231.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 81241.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 81251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 81261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 81271.54Skamil 81281.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 81291.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 81301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 81311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 81321.54Skamil 81331.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 81341.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 81351.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 81361.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 81371.1Skamil 81381.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 81391.1Skamil 81401.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 81411.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 81421.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 81431.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 81441.101Skamil 81451.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 81461.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 81471.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 81481.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 81491.101Skamil 81501.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 81511.101Skamil 81521.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 81531.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 81541.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 81551.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 81561.115Skamil 81571.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 81581.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 81591.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 81601.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 81611.115Skamil 81621.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 81631.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 81641.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 81651.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 81661.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 81671.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 81681.1Skamil 81691.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 81701.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 81711.1Skamil 81721.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 81731.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 81741.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 81751.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 81761.1Skamil 81771.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 81781.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 81791.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 81801.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 81811.2Skamil 81821.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 81831.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 81841.95Skamil 81851.1Skamil ATF_TP_ADD_TC(tp, kill1); 81861.1Skamil ATF_TP_ADD_TC(tp, kill2); 81871.75Skamil ATF_TP_ADD_TC(tp, kill3); 81881.1Skamil 81891.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 81901.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 81911.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 81921.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 81931.77Skamil 81941.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 81951.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 81961.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 81971.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 81981.1Skamil 81991.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 82001.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 82011.79Skamil 82021.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 82031.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 82041.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 82051.1Skamil 82061.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 82071.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 82081.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 82091.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 82101.1Skamil 82111.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 82121.84Skamil 82131.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 82141.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 82151.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 82161.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 82171.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 82181.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 82191.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 82201.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 82211.99Skamil 82221.1Skamil ATF_TP_ADD_TC(tp, signal9); 82231.1Skamil ATF_TP_ADD_TC(tp, signal10); 82241.1Skamil 82251.1Skamil ATF_TP_ADD_TC(tp, suspend2); 82261.1Skamil 82271.1Skamil ATF_TP_ADD_TC(tp, resume1); 82281.1Skamil 82291.1Skamil ATF_TP_ADD_TC(tp, syscall1); 82301.1Skamil 82311.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 82321.1Skamil 82331.106Skamil ATF_TP_ADD_TC(tp, clone1); 82341.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 82351.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 82361.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 82371.106Skamil ATF_TP_ADD_TC(tp, clone5); 82381.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 82391.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 82401.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 82411.106Skamil 82421.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 82431.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 82441.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 82451.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 82461.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 82471.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 82481.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 82491.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 82501.106Skamil 82511.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 82521.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 82531.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 82541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 82551.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 82561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 82571.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 82581.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 82591.106Skamil 82601.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 82611.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 82621.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 82631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 82641.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 82651.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 82661.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 82671.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 82681.106Skamil 82691.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 82701.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 82711.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 82721.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 82731.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 82741.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 82751.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 82761.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 82771.106Skamil 82781.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 82791.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 82801.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 82811.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 82821.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 82831.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 82841.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 82851.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 82861.106Skamil 82871.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 82881.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 82891.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 82901.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 82911.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 82921.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 82931.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 82941.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 82951.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 82961.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 82971.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 82981.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 82991.103Skamil 83001.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 83011.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 83021.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 83031.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 83041.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 83051.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 83061.107Skamil 83071.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 83081.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 83091.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 83101.122Skamil 83111.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 83121.130Smgorny 83131.138Smgorny#if defined(TWAIT_HAVE_STATUS) 83141.138Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals); 83151.138Smgorny#endif 83161.138Smgorny 83171.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 83181.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 83191.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 83201.1Skamil 83211.1Skamil return atf_no_error(); 83221.1Skamil} 8323