t_ptrace_wait.c revision 1.137
11.137Skamil/* $NetBSD: t_ptrace_wait.c,v 1.137 2019/10/13 09:42:15 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.137Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.137 2019/10/13 09:42:15 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.110Skamil#ifndef TEST_VFORK_ENABLED 1251.127Skamil#define TEST_VFORK_ENABLED 1 1261.110Skamil#endif 1271.109Skamil 1281.128Skamil#ifndef TEST_LWP_ENABLED 1291.136Skamil#define TEST_LWP_ENABLED 1 1301.128Skamil#endif 1311.128Skamil 1321.34Skamil/// ---------------------------------------------------------------------------- 1331.34Skamil 1341.33Skamilstatic void 1351.33Skamiltraceme_raise(int sigval) 1361.1Skamil{ 1371.1Skamil const int exitval = 5; 1381.1Skamil pid_t child, wpid; 1391.1Skamil#if defined(TWAIT_HAVE_STATUS) 1401.1Skamil int status; 1411.1Skamil#endif 1421.1Skamil 1431.133Skamil ptrace_state_t state, zero_state; 1441.133Skamil const int slen = sizeof(state); 1451.45Skamil struct ptrace_siginfo info; 1461.133Skamil memset(&zero_state, 0, sizeof(zero_state)); 1471.45Skamil memset(&info, 0, sizeof(info)); 1481.45Skamil 1491.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1501.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1511.1Skamil if (child == 0) { 1521.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1531.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1541.1Skamil 1551.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1561.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1571.1Skamil 1581.36Skamil switch (sigval) { 1591.36Skamil case SIGKILL: 1601.36Skamil /* NOTREACHED */ 1611.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1621.70Smrg __unreachable(); 1631.36Skamil default: 1641.36Skamil DPRINTF("Before exiting of the child process\n"); 1651.36Skamil _exit(exitval); 1661.36Skamil } 1671.1Skamil } 1681.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1691.1Skamil 1701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1721.1Skamil 1731.36Skamil switch (sigval) { 1741.36Skamil case SIGKILL: 1751.36Skamil validate_status_signaled(status, sigval, 0); 1761.133Skamil SYSCALL_REQUIRE( 1771.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) == -1); 1781.133Skamil 1791.36Skamil break; 1801.36Skamil default: 1811.36Skamil validate_status_stopped(status, sigval); 1821.1Skamil 1831.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1841.61Skre "child\n"); 1851.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1861.61Skre sizeof(info)) != -1); 1871.45Skamil 1881.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1891.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1901.61Skre "si_errno=%#x\n", 1911.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1921.61Skre info.psi_siginfo.si_errno); 1931.45Skamil 1941.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1951.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1961.45Skamil 1971.133Skamil DPRINTF("Assert that PT_GET_PROCESS_STATE returns non-error"); 1981.133Skamil SYSCALL_REQUIRE( 1991.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 2001.133Skamil ATF_REQUIRE(memcmp(&state, &zero_state, slen) == 0); 2011.133Skamil 2021.36Skamil DPRINTF("Before resuming the child process where it left off " 2031.36Skamil "and without signal to be sent\n"); 2041.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2051.1Skamil 2061.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2071.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 2081.61Skre child); 2091.36Skamil break; 2101.36Skamil } 2111.1Skamil 2121.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2131.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2141.1Skamil} 2151.1Skamil 2161.61Skre#define TRACEME_RAISE(test, sig) \ 2171.61SkreATF_TC(test); \ 2181.61SkreATF_TC_HEAD(test, tc) \ 2191.61Skre{ \ 2201.61Skre atf_tc_set_md_var(tc, "descr", \ 2211.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 2221.61Skre} \ 2231.61Skre \ 2241.61SkreATF_TC_BODY(test, tc) \ 2251.61Skre{ \ 2261.61Skre \ 2271.61Skre traceme_raise(sig); \ 2281.33Skamil} 2291.33Skamil 2301.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2311.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2321.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2331.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2341.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2351.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2361.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2371.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2381.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2391.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2401.33Skamil 2411.34Skamil/// ---------------------------------------------------------------------------- 2421.1Skamil 2431.1Skamilstatic void 2441.87Skamiltraceme_raisesignal_ignored(int sigignored) 2451.87Skamil{ 2461.87Skamil const int exitval = 5; 2471.87Skamil const int sigval = SIGSTOP; 2481.87Skamil pid_t child, wpid; 2491.87Skamil struct sigaction sa; 2501.87Skamil#if defined(TWAIT_HAVE_STATUS) 2511.87Skamil int status; 2521.87Skamil#endif 2531.87Skamil struct ptrace_siginfo info; 2541.87Skamil 2551.87Skamil memset(&info, 0, sizeof(info)); 2561.87Skamil 2571.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2581.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2591.87Skamil if (child == 0) { 2601.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2611.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2621.87Skamil 2631.87Skamil memset(&sa, 0, sizeof(sa)); 2641.87Skamil sa.sa_handler = SIG_IGN; 2651.87Skamil sigemptyset(&sa.sa_mask); 2661.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2671.87Skamil 2681.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2691.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2701.87Skamil 2711.87Skamil DPRINTF("Before raising %s from child\n", 2721.87Skamil strsignal(sigignored)); 2731.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2741.87Skamil 2751.87Skamil DPRINTF("Before exiting of the child process\n"); 2761.87Skamil _exit(exitval); 2771.87Skamil } 2781.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2791.87Skamil 2801.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2811.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2821.87Skamil 2831.87Skamil validate_status_stopped(status, sigval); 2841.87Skamil 2851.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2861.87Skamil SYSCALL_REQUIRE( 2871.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2881.87Skamil 2891.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2901.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2911.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2921.87Skamil info.psi_siginfo.si_errno); 2931.87Skamil 2941.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2951.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2961.87Skamil 2971.87Skamil DPRINTF("Before resuming the child process where it left off and " 2981.87Skamil "without signal to be sent\n"); 2991.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3001.87Skamil 3011.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3021.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3031.87Skamil 3041.87Skamil validate_status_stopped(status, sigignored); 3051.87Skamil 3061.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3071.87Skamil SYSCALL_REQUIRE( 3081.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3091.87Skamil 3101.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3111.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3121.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3131.87Skamil info.psi_siginfo.si_errno); 3141.87Skamil 3151.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 3161.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3171.87Skamil 3181.87Skamil DPRINTF("Before resuming the child process where it left off and " 3191.87Skamil "without signal to be sent\n"); 3201.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3211.87Skamil 3221.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3231.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3241.87Skamil 3251.87Skamil validate_status_exited(status, exitval); 3261.87Skamil 3271.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3281.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3291.87Skamil} 3301.87Skamil 3311.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3321.87SkamilATF_TC(test); \ 3331.87SkamilATF_TC_HEAD(test, tc) \ 3341.87Skamil{ \ 3351.87Skamil atf_tc_set_md_var(tc, "descr", \ 3361.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3371.87Skamil "does not stop tracer from catching this raised signal"); \ 3381.87Skamil} \ 3391.87Skamil \ 3401.87SkamilATF_TC_BODY(test, tc) \ 3411.87Skamil{ \ 3421.87Skamil \ 3431.87Skamil traceme_raisesignal_ignored(sig); \ 3441.87Skamil} 3451.87Skamil 3461.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3471.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3481.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3491.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3501.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3511.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3521.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3531.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3541.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3551.87Skamil 3561.87Skamil/// ---------------------------------------------------------------------------- 3571.87Skamil 3581.87Skamilstatic void 3591.86Skamiltraceme_raisesignal_masked(int sigmasked) 3601.86Skamil{ 3611.86Skamil const int exitval = 5; 3621.86Skamil const int sigval = SIGSTOP; 3631.86Skamil pid_t child, wpid; 3641.86Skamil#if defined(TWAIT_HAVE_STATUS) 3651.86Skamil int status; 3661.86Skamil#endif 3671.86Skamil sigset_t intmask; 3681.86Skamil struct ptrace_siginfo info; 3691.86Skamil 3701.86Skamil memset(&info, 0, sizeof(info)); 3711.86Skamil 3721.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3731.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3741.86Skamil if (child == 0) { 3751.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3761.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3771.86Skamil 3781.86Skamil sigemptyset(&intmask); 3791.86Skamil sigaddset(&intmask, sigmasked); 3801.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3811.86Skamil 3821.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3831.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3841.86Skamil 3851.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3861.86Skamil strsignal(sigmasked)); 3871.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3881.86Skamil 3891.86Skamil DPRINTF("Before exiting of the child process\n"); 3901.86Skamil _exit(exitval); 3911.86Skamil } 3921.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3931.86Skamil 3941.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3951.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3961.86Skamil 3971.86Skamil validate_status_stopped(status, sigval); 3981.86Skamil 3991.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 4001.86Skamil SYSCALL_REQUIRE( 4011.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4021.86Skamil 4031.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4041.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4051.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4061.86Skamil info.psi_siginfo.si_errno); 4071.86Skamil 4081.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 4091.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 4101.86Skamil 4111.86Skamil DPRINTF("Before resuming the child process where it left off and " 4121.86Skamil "without signal to be sent\n"); 4131.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 4141.86Skamil 4151.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4161.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4171.86Skamil 4181.86Skamil validate_status_exited(status, exitval); 4191.86Skamil 4201.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4211.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 4221.86Skamil} 4231.86Skamil 4241.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 4251.86SkamilATF_TC(test); \ 4261.86SkamilATF_TC_HEAD(test, tc) \ 4271.86Skamil{ \ 4281.86Skamil atf_tc_set_md_var(tc, "descr", \ 4291.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4301.86Skamil "stops tracer from catching this raised signal"); \ 4311.86Skamil} \ 4321.86Skamil \ 4331.86SkamilATF_TC_BODY(test, tc) \ 4341.86Skamil{ \ 4351.86Skamil \ 4361.86Skamil traceme_raisesignal_masked(sig); \ 4371.86Skamil} 4381.86Skamil 4391.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4401.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4411.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4421.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4431.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4441.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4451.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4461.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4471.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4481.86Skamil 4491.86Skamil/// ---------------------------------------------------------------------------- 4501.86Skamil 4511.86Skamilstatic void 4521.59Skamiltraceme_crash(int sig) 4531.59Skamil{ 4541.59Skamil pid_t child, wpid; 4551.59Skamil#if defined(TWAIT_HAVE_STATUS) 4561.59Skamil int status; 4571.59Skamil#endif 4581.59Skamil struct ptrace_siginfo info; 4591.61Skre 4601.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4611.71Skamil if (sig == SIGILL) 4621.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4631.71Skamil#endif 4641.71Skamil 4651.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4661.114Skamil atf_tc_skip("FP exceptions are not supported"); 4671.114Skamil 4681.59Skamil memset(&info, 0, sizeof(info)); 4691.59Skamil 4701.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4711.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4721.59Skamil if (child == 0) { 4731.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4741.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4751.59Skamil 4761.59Skamil DPRINTF("Before executing a trap\n"); 4771.59Skamil switch (sig) { 4781.59Skamil case SIGTRAP: 4791.59Skamil trigger_trap(); 4801.59Skamil break; 4811.59Skamil case SIGSEGV: 4821.59Skamil trigger_segv(); 4831.59Skamil break; 4841.59Skamil case SIGILL: 4851.59Skamil trigger_ill(); 4861.59Skamil break; 4871.59Skamil case SIGFPE: 4881.59Skamil trigger_fpe(); 4891.59Skamil break; 4901.59Skamil case SIGBUS: 4911.59Skamil trigger_bus(); 4921.59Skamil break; 4931.59Skamil default: 4941.59Skamil /* NOTREACHED */ 4951.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4961.59Skamil } 4971.59Skamil 4981.59Skamil /* NOTREACHED */ 4991.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5001.59Skamil } 5011.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 5021.59Skamil 5031.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5041.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5051.59Skamil 5061.59Skamil validate_status_stopped(status, sig); 5071.59Skamil 5081.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 5091.61Skre SYSCALL_REQUIRE( 5101.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 5111.59Skamil 5121.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 5131.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 5141.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 5151.61Skre info.psi_siginfo.si_errno); 5161.59Skamil 5171.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 5181.59Skamil switch (sig) { 5191.59Skamil case SIGTRAP: 5201.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 5211.59Skamil break; 5221.59Skamil case SIGSEGV: 5231.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 5241.59Skamil break; 5251.71Skamil case SIGILL: 5261.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 5271.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5281.71Skamil break; 5291.59Skamil case SIGFPE: 5301.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5311.59Skamil break; 5321.59Skamil case SIGBUS: 5331.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5341.59Skamil break; 5351.59Skamil } 5361.59Skamil 5371.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5381.59Skamil 5391.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5401.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5411.59Skamil 5421.59Skamil validate_status_signaled(status, SIGKILL, 0); 5431.59Skamil 5441.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5451.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5461.59Skamil} 5471.59Skamil 5481.61Skre#define TRACEME_CRASH(test, sig) \ 5491.61SkreATF_TC(test); \ 5501.61SkreATF_TC_HEAD(test, tc) \ 5511.61Skre{ \ 5521.61Skre atf_tc_set_md_var(tc, "descr", \ 5531.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5541.61Skre} \ 5551.61Skre \ 5561.61SkreATF_TC_BODY(test, tc) \ 5571.61Skre{ \ 5581.61Skre \ 5591.61Skre traceme_crash(sig); \ 5601.59Skamil} 5611.59Skamil 5621.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5631.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5641.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5651.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5661.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5671.59Skamil 5681.59Skamil/// ---------------------------------------------------------------------------- 5691.59Skamil 5701.59Skamilstatic void 5711.88Skamiltraceme_signalmasked_crash(int sig) 5721.88Skamil{ 5731.89Skamil const int sigval = SIGSTOP; 5741.88Skamil pid_t child, wpid; 5751.88Skamil#if defined(TWAIT_HAVE_STATUS) 5761.88Skamil int status; 5771.88Skamil#endif 5781.88Skamil struct ptrace_siginfo info; 5791.88Skamil sigset_t intmask; 5801.89Skamil struct kinfo_proc2 kp; 5811.89Skamil size_t len = sizeof(kp); 5821.89Skamil 5831.89Skamil int name[6]; 5841.89Skamil const size_t namelen = __arraycount(name); 5851.89Skamil ki_sigset_t kp_sigmask; 5861.88Skamil 5871.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5881.88Skamil if (sig == SIGILL) 5891.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5901.88Skamil#endif 5911.88Skamil 5921.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5931.114Skamil atf_tc_skip("FP exceptions are not supported"); 5941.114Skamil 5951.88Skamil memset(&info, 0, sizeof(info)); 5961.88Skamil 5971.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5981.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5991.88Skamil if (child == 0) { 6001.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 6011.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 6021.88Skamil 6031.88Skamil sigemptyset(&intmask); 6041.88Skamil sigaddset(&intmask, sig); 6051.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 6061.88Skamil 6071.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 6081.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 6091.89Skamil 6101.88Skamil DPRINTF("Before executing a trap\n"); 6111.88Skamil switch (sig) { 6121.88Skamil case SIGTRAP: 6131.88Skamil trigger_trap(); 6141.88Skamil break; 6151.88Skamil case SIGSEGV: 6161.88Skamil trigger_segv(); 6171.88Skamil break; 6181.88Skamil case SIGILL: 6191.88Skamil trigger_ill(); 6201.88Skamil break; 6211.88Skamil case SIGFPE: 6221.88Skamil trigger_fpe(); 6231.88Skamil break; 6241.88Skamil case SIGBUS: 6251.88Skamil trigger_bus(); 6261.88Skamil break; 6271.88Skamil default: 6281.88Skamil /* NOTREACHED */ 6291.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6301.88Skamil } 6311.88Skamil 6321.88Skamil /* NOTREACHED */ 6331.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6341.88Skamil } 6351.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6361.88Skamil 6371.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6381.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6391.88Skamil 6401.89Skamil validate_status_stopped(status, sigval); 6411.89Skamil 6421.89Skamil name[0] = CTL_KERN, 6431.89Skamil name[1] = KERN_PROC2, 6441.89Skamil name[2] = KERN_PROC_PID; 6451.89Skamil name[3] = child; 6461.89Skamil name[4] = sizeof(kp); 6471.89Skamil name[5] = 1; 6481.89Skamil 6491.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6501.89Skamil 6511.89Skamil kp_sigmask = kp.p_sigmask; 6521.89Skamil 6531.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6541.89Skamil SYSCALL_REQUIRE( 6551.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6561.89Skamil 6571.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6581.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6591.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6601.89Skamil info.psi_siginfo.si_errno); 6611.89Skamil 6621.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6631.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6641.89Skamil 6651.89Skamil DPRINTF("Before resuming the child process where it left off and " 6661.89Skamil "without signal to be sent\n"); 6671.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6681.89Skamil 6691.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6701.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6711.89Skamil 6721.88Skamil validate_status_stopped(status, sig); 6731.88Skamil 6741.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6751.88Skamil SYSCALL_REQUIRE( 6761.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6771.88Skamil 6781.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6791.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6801.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6811.88Skamil info.psi_siginfo.si_errno); 6821.88Skamil 6831.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6841.89Skamil 6851.89Skamil DPRINTF("kp_sigmask=" 6861.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6871.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6881.89Skamil kp_sigmask.__bits[3]); 6891.89Skamil 6901.89Skamil DPRINTF("kp.p_sigmask=" 6911.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6921.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6931.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6941.89Skamil 6951.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6961.89Skamil 6971.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6981.88Skamil switch (sig) { 6991.88Skamil case SIGTRAP: 7001.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 7011.88Skamil break; 7021.88Skamil case SIGSEGV: 7031.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 7041.88Skamil break; 7051.88Skamil case SIGILL: 7061.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 7071.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 7081.88Skamil break; 7091.88Skamil case SIGFPE: 7101.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 7111.88Skamil break; 7121.88Skamil case SIGBUS: 7131.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 7141.88Skamil break; 7151.88Skamil } 7161.88Skamil 7171.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 7181.88Skamil 7191.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7201.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7211.88Skamil 7221.88Skamil validate_status_signaled(status, SIGKILL, 0); 7231.88Skamil 7241.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7251.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 7261.88Skamil} 7271.88Skamil 7281.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7291.88SkamilATF_TC(test); \ 7301.88SkamilATF_TC_HEAD(test, tc) \ 7311.88Skamil{ \ 7321.88Skamil atf_tc_set_md_var(tc, "descr", \ 7331.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7341.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7351.88Skamil} \ 7361.88Skamil \ 7371.88SkamilATF_TC_BODY(test, tc) \ 7381.88Skamil{ \ 7391.88Skamil \ 7401.88Skamil traceme_signalmasked_crash(sig); \ 7411.88Skamil} 7421.88Skamil 7431.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7441.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7451.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7461.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7471.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7481.88Skamil 7491.88Skamil/// ---------------------------------------------------------------------------- 7501.88Skamil 7511.88Skamilstatic void 7521.88Skamiltraceme_signalignored_crash(int sig) 7531.88Skamil{ 7541.90Skamil const int sigval = SIGSTOP; 7551.88Skamil pid_t child, wpid; 7561.88Skamil#if defined(TWAIT_HAVE_STATUS) 7571.88Skamil int status; 7581.88Skamil#endif 7591.88Skamil struct sigaction sa; 7601.88Skamil struct ptrace_siginfo info; 7611.90Skamil struct kinfo_proc2 kp; 7621.90Skamil size_t len = sizeof(kp); 7631.90Skamil 7641.90Skamil int name[6]; 7651.90Skamil const size_t namelen = __arraycount(name); 7661.90Skamil ki_sigset_t kp_sigignore; 7671.88Skamil 7681.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7691.88Skamil if (sig == SIGILL) 7701.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7711.88Skamil#endif 7721.88Skamil 7731.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7741.114Skamil atf_tc_skip("FP exceptions are not supported"); 7751.114Skamil 7761.88Skamil memset(&info, 0, sizeof(info)); 7771.88Skamil 7781.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7791.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7801.88Skamil if (child == 0) { 7811.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7821.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7831.88Skamil 7841.88Skamil memset(&sa, 0, sizeof(sa)); 7851.88Skamil sa.sa_handler = SIG_IGN; 7861.88Skamil sigemptyset(&sa.sa_mask); 7871.88Skamil 7881.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7891.88Skamil 7901.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7911.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7921.90Skamil 7931.88Skamil DPRINTF("Before executing a trap\n"); 7941.88Skamil switch (sig) { 7951.88Skamil case SIGTRAP: 7961.88Skamil trigger_trap(); 7971.88Skamil break; 7981.88Skamil case SIGSEGV: 7991.88Skamil trigger_segv(); 8001.88Skamil break; 8011.88Skamil case SIGILL: 8021.88Skamil trigger_ill(); 8031.88Skamil break; 8041.88Skamil case SIGFPE: 8051.88Skamil trigger_fpe(); 8061.88Skamil break; 8071.88Skamil case SIGBUS: 8081.88Skamil trigger_bus(); 8091.88Skamil break; 8101.88Skamil default: 8111.88Skamil /* NOTREACHED */ 8121.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8131.88Skamil } 8141.88Skamil 8151.88Skamil /* NOTREACHED */ 8161.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8171.88Skamil } 8181.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 8191.88Skamil 8201.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8211.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8221.88Skamil 8231.90Skamil validate_status_stopped(status, sigval); 8241.90Skamil 8251.90Skamil name[0] = CTL_KERN, 8261.90Skamil name[1] = KERN_PROC2, 8271.90Skamil name[2] = KERN_PROC_PID; 8281.90Skamil name[3] = child; 8291.90Skamil name[4] = sizeof(kp); 8301.90Skamil name[5] = 1; 8311.90Skamil 8321.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8331.90Skamil 8341.90Skamil kp_sigignore = kp.p_sigignore; 8351.90Skamil 8361.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8371.90Skamil SYSCALL_REQUIRE( 8381.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8391.90Skamil 8401.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8411.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8421.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8431.90Skamil info.psi_siginfo.si_errno); 8441.90Skamil 8451.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8461.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8471.90Skamil 8481.90Skamil DPRINTF("Before resuming the child process where it left off and " 8491.90Skamil "without signal to be sent\n"); 8501.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8511.90Skamil 8521.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8531.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8541.90Skamil 8551.88Skamil validate_status_stopped(status, sig); 8561.88Skamil 8571.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8581.88Skamil SYSCALL_REQUIRE( 8591.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8601.88Skamil 8611.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8621.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8631.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8641.88Skamil info.psi_siginfo.si_errno); 8651.88Skamil 8661.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8671.90Skamil 8681.90Skamil DPRINTF("kp_sigignore=" 8691.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8701.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8711.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8721.90Skamil 8731.90Skamil DPRINTF("kp.p_sigignore=" 8741.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8751.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8761.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8771.90Skamil 8781.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8791.90Skamil 8801.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8811.88Skamil switch (sig) { 8821.88Skamil case SIGTRAP: 8831.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8841.88Skamil break; 8851.88Skamil case SIGSEGV: 8861.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8871.88Skamil break; 8881.88Skamil case SIGILL: 8891.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8901.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8911.88Skamil break; 8921.88Skamil case SIGFPE: 8931.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8941.88Skamil break; 8951.88Skamil case SIGBUS: 8961.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8971.88Skamil break; 8981.88Skamil } 8991.88Skamil 9001.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 9011.88Skamil 9021.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9031.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9041.88Skamil 9051.88Skamil validate_status_signaled(status, SIGKILL, 0); 9061.88Skamil 9071.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9081.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9091.88Skamil} 9101.88Skamil 9111.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 9121.88SkamilATF_TC(test); \ 9131.88SkamilATF_TC_HEAD(test, tc) \ 9141.88Skamil{ \ 9151.88Skamil atf_tc_set_md_var(tc, "descr", \ 9161.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 9171.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 9181.88Skamil} \ 9191.88Skamil \ 9201.88SkamilATF_TC_BODY(test, tc) \ 9211.88Skamil{ \ 9221.88Skamil \ 9231.88Skamil traceme_signalignored_crash(sig); \ 9241.88Skamil} 9251.88Skamil 9261.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 9271.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9281.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9291.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9301.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9311.88Skamil 9321.88Skamil/// ---------------------------------------------------------------------------- 9331.88Skamil 9341.88Skamilstatic void 9351.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9361.1Skamil{ 9371.1Skamil const int exitval = 5; 9381.34Skamil const int sigval = SIGSTOP; 9391.1Skamil pid_t child, wpid; 9401.1Skamil struct sigaction sa; 9411.1Skamil#if defined(TWAIT_HAVE_STATUS) 9421.1Skamil int status; 9431.1Skamil#endif 9441.61Skre struct ptrace_siginfo info; 9451.1Skamil 9461.45Skamil memset(&info, 0, sizeof(info)); 9471.45Skamil 9481.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9491.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9501.1Skamil if (child == 0) { 9511.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9521.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9531.1Skamil 9541.34Skamil sa.sa_handler = sah; 9551.1Skamil sa.sa_flags = SA_SIGINFO; 9561.1Skamil sigemptyset(&sa.sa_mask); 9571.1Skamil 9581.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9591.1Skamil 9601.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9611.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9621.1Skamil 9631.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9641.1Skamil 9651.13Schristos DPRINTF("Before exiting of the child process\n"); 9661.1Skamil _exit(exitval); 9671.1Skamil } 9681.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9691.1Skamil 9701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9721.1Skamil 9731.1Skamil validate_status_stopped(status, sigval); 9741.1Skamil 9751.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9761.61Skre SYSCALL_REQUIRE( 9771.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9781.45Skamil 9791.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9801.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9811.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9821.45Skamil info.psi_siginfo.si_errno); 9831.45Skamil 9841.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9851.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9861.45Skamil 9871.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9881.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9901.1Skamil 9911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9931.1Skamil 9941.1Skamil validate_status_exited(status, exitval); 9951.1Skamil 9961.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9971.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9981.1Skamil} 9991.1Skamil 10001.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 10011.61SkreATF_TC(test); \ 10021.61SkreATF_TC_HEAD(test, tc) \ 10031.61Skre{ \ 10041.61Skre atf_tc_set_md_var(tc, "descr", \ 10051.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10061.61Skre "handled correctly and caught by a signal handler"); \ 10071.61Skre} \ 10081.61Skre \ 10091.61Skrestatic int test##_caught = 0; \ 10101.61Skre \ 10111.61Skrestatic void \ 10121.61Skretest##_sighandler(int arg) \ 10131.61Skre{ \ 10141.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 10151.61Skre \ 10161.61Skre ++ test##_caught; \ 10171.61Skre} \ 10181.61Skre \ 10191.61SkreATF_TC_BODY(test, tc) \ 10201.61Skre{ \ 10211.61Skre \ 10221.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 10231.34Skamil} 10241.34Skamil 10251.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 10261.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 10271.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10281.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10291.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10301.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10311.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10321.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10331.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10341.34Skamil 10351.34Skamil/// ---------------------------------------------------------------------------- 10361.34Skamil 10371.35Skamilstatic void 10381.50Skamiltraceme_sendsignal_masked(int sigsent) 10391.50Skamil{ 10401.50Skamil const int exitval = 5; 10411.50Skamil const int sigval = SIGSTOP; 10421.50Skamil pid_t child, wpid; 10431.50Skamil sigset_t set; 10441.50Skamil#if defined(TWAIT_HAVE_STATUS) 10451.50Skamil int status; 10461.50Skamil#endif 10471.61Skre struct ptrace_siginfo info; 10481.50Skamil 10491.50Skamil memset(&info, 0, sizeof(info)); 10501.50Skamil 10511.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10521.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10531.50Skamil if (child == 0) { 10541.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10551.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10561.50Skamil 10571.50Skamil sigemptyset(&set); 10581.50Skamil sigaddset(&set, sigsent); 10591.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10601.50Skamil 10611.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10621.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10631.50Skamil 10641.50Skamil _exit(exitval); 10651.50Skamil } 10661.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10671.50Skamil 10681.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10691.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10701.50Skamil 10711.50Skamil validate_status_stopped(status, sigval); 10721.50Skamil 10731.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10741.61Skre SYSCALL_REQUIRE( 10751.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10761.50Skamil 10771.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10781.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10791.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10801.50Skamil info.psi_siginfo.si_errno); 10811.50Skamil 10821.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10831.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10841.50Skamil 10851.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10861.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10871.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10881.50Skamil 10891.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10901.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10911.50Skamil 10921.50Skamil validate_status_exited(status, exitval); 10931.50Skamil 10941.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10951.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10961.50Skamil} 10971.50Skamil 10981.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10991.61SkreATF_TC(test); \ 11001.61SkreATF_TC_HEAD(test, tc) \ 11011.61Skre{ \ 11021.61Skre atf_tc_set_md_var(tc, "descr", \ 11031.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11041.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 11051.61Skre} \ 11061.61Skre \ 11071.61SkreATF_TC_BODY(test, tc) \ 11081.61Skre{ \ 11091.61Skre \ 11101.61Skre traceme_sendsignal_masked(sig); \ 11111.50Skamil} 11121.50Skamil 11131.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 11141.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 11151.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 11161.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 11171.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 11181.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 11191.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 11201.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 11211.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 11221.50Skamil 11231.50Skamil/// ---------------------------------------------------------------------------- 11241.50Skamil 11251.50Skamilstatic void 11261.50Skamiltraceme_sendsignal_ignored(int sigsent) 11271.50Skamil{ 11281.50Skamil const int exitval = 5; 11291.50Skamil const int sigval = SIGSTOP; 11301.50Skamil pid_t child, wpid; 11311.50Skamil struct sigaction sa; 11321.50Skamil#if defined(TWAIT_HAVE_STATUS) 11331.50Skamil int status; 11341.50Skamil#endif 11351.61Skre struct ptrace_siginfo info; 11361.50Skamil 11371.50Skamil memset(&info, 0, sizeof(info)); 11381.50Skamil 11391.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11401.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11411.50Skamil if (child == 0) { 11421.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11431.61Skre 11441.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11451.50Skamil 11461.50Skamil memset(&sa, 0, sizeof(sa)); 11471.50Skamil sa.sa_handler = SIG_IGN; 11481.50Skamil sigemptyset(&sa.sa_mask); 11491.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11501.50Skamil 11511.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11521.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11531.50Skamil 11541.50Skamil _exit(exitval); 11551.50Skamil } 11561.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11571.50Skamil 11581.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11591.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11601.50Skamil 11611.50Skamil validate_status_stopped(status, sigval); 11621.50Skamil 11631.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11641.61Skre SYSCALL_REQUIRE( 11651.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11661.50Skamil 11671.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11681.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11691.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11701.50Skamil info.psi_siginfo.si_errno); 11711.50Skamil 11721.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11731.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11741.50Skamil 11751.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11761.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11771.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11781.50Skamil 11791.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11801.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11811.50Skamil 11821.50Skamil validate_status_exited(status, exitval); 11831.50Skamil 11841.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11851.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11861.50Skamil} 11871.50Skamil 11881.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11891.61SkreATF_TC(test); \ 11901.61SkreATF_TC_HEAD(test, tc) \ 11911.61Skre{ \ 11921.61Skre atf_tc_set_md_var(tc, "descr", \ 11931.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11941.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11951.61Skre} \ 11961.61Skre \ 11971.61SkreATF_TC_BODY(test, tc) \ 11981.61Skre{ \ 11991.61Skre \ 12001.61Skre traceme_sendsignal_ignored(sig); \ 12011.50Skamil} 12021.50Skamil 12031.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 12041.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 12051.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 12061.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 12071.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 12081.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 12091.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 12101.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 12111.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 12121.50Skamil 12131.50Skamil/// ---------------------------------------------------------------------------- 12141.50Skamil 12151.50Skamilstatic void 12161.50Skamiltraceme_sendsignal_simple(int sigsent) 12171.1Skamil{ 12181.35Skamil const int sigval = SIGSTOP; 12191.35Skamil int exitval = 0; 12201.1Skamil pid_t child, wpid; 12211.1Skamil#if defined(TWAIT_HAVE_STATUS) 12221.1Skamil int status; 12231.85Skamil int expect_core; 12241.85Skamil 12251.85Skamil switch (sigsent) { 12261.85Skamil case SIGABRT: 12271.85Skamil case SIGTRAP: 12281.85Skamil case SIGBUS: 12291.85Skamil case SIGILL: 12301.85Skamil case SIGFPE: 12311.85Skamil case SIGSEGV: 12321.85Skamil expect_core = 1; 12331.85Skamil break; 12341.85Skamil default: 12351.85Skamil expect_core = 0; 12361.85Skamil break; 12371.85Skamil } 12381.1Skamil#endif 12391.61Skre struct ptrace_siginfo info; 12401.1Skamil 12411.45Skamil memset(&info, 0, sizeof(info)); 12421.45Skamil 12431.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12441.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12451.1Skamil if (child == 0) { 12461.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12471.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12481.1Skamil 12491.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12501.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12511.1Skamil 12521.35Skamil switch (sigsent) { 12531.35Skamil case SIGCONT: 12541.48Skamil case SIGSTOP: 12551.35Skamil _exit(exitval); 12561.35Skamil default: 12571.35Skamil /* NOTREACHED */ 12581.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12591.35Skamil } 12601.1Skamil } 12611.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12621.1Skamil 12631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12651.1Skamil 12661.1Skamil validate_status_stopped(status, sigval); 12671.1Skamil 12681.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12691.61Skre SYSCALL_REQUIRE( 12701.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12711.45Skamil 12721.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12731.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12741.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12751.45Skamil info.psi_siginfo.si_errno); 12761.45Skamil 12771.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12781.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12791.45Skamil 12801.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12811.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12821.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12831.1Skamil 12841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12861.1Skamil 12871.35Skamil switch (sigsent) { 12881.48Skamil case SIGSTOP: 12891.48Skamil validate_status_stopped(status, sigsent); 12901.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12911.61Skre "child\n"); 12921.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12931.61Skre sizeof(info)) != -1); 12941.48Skamil 12951.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12961.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12971.61Skre "si_errno=%#x\n", 12981.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12991.61Skre info.psi_siginfo.si_errno); 13001.48Skamil 13011.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 13021.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 13031.48Skamil 13041.48Skamil DPRINTF("Before resuming the child process where it left off " 13051.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 13061.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 13071.48Skamil 13081.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13091.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 13101.61Skre child); 13111.48Skamil /* FALLTHROUGH */ 13121.35Skamil case SIGCONT: 13131.35Skamil validate_status_exited(status, exitval); 13141.35Skamil break; 13151.35Skamil default: 13161.35Skamil validate_status_signaled(status, sigsent, expect_core); 13171.35Skamil break; 13181.35Skamil } 13191.1Skamil 13201.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 13211.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 13221.1Skamil} 13231.1Skamil 13241.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 13251.61SkreATF_TC(test); \ 13261.61SkreATF_TC_HEAD(test, tc) \ 13271.61Skre{ \ 13281.61Skre atf_tc_set_md_var(tc, "descr", \ 13291.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13301.61Skre "handled correctly in a child without a signal handler"); \ 13311.61Skre} \ 13321.61Skre \ 13331.61SkreATF_TC_BODY(test, tc) \ 13341.61Skre{ \ 13351.61Skre \ 13361.61Skre traceme_sendsignal_simple(sig); \ 13371.35Skamil} 13381.35Skamil 13391.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13401.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13411.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13421.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13431.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13441.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13451.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13461.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13471.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13481.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13491.35Skamil 13501.35Skamil/// ---------------------------------------------------------------------------- 13511.35Skamil 13521.37SkamilATF_TC(traceme_pid1_parent); 13531.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13541.37Skamil{ 13551.37Skamil atf_tc_set_md_var(tc, "descr", 13561.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13571.37Skamil} 13581.37Skamil 13591.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13601.37Skamil{ 13611.37Skamil struct msg_fds parent_child; 13621.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13631.37Skamil pid_t child1, child2, wpid; 13641.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13651.37Skamil#if defined(TWAIT_HAVE_STATUS) 13661.37Skamil int status; 13671.37Skamil#endif 13681.37Skamil 13691.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13701.37Skamil 13711.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13721.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13731.37Skamil if (child1 == 0) { 13741.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13751.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13761.37Skamil if (child2 != 0) { 13771.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13781.61Skre getpid(), child2); 13791.37Skamil _exit(exitval_child1); 13801.37Skamil } 13811.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13821.37Skamil 13831.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13841.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13851.37Skamil 13861.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13871.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13881.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13891.37Skamil 13901.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13911.37Skamil 13921.37Skamil _exit(exitval_child2); 13931.37Skamil } 13941.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13951.37Skamil 13961.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13971.61Skre TWAIT_REQUIRE_SUCCESS( 13981.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13991.37Skamil 14001.37Skamil validate_status_exited(status, exitval_child1); 14011.37Skamil 14021.37Skamil DPRINTF("Notify that child1 is dead\n"); 14031.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 14041.37Skamil 14051.37Skamil DPRINTF("Wait for exiting of child2\n"); 14061.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 14071.37Skamil} 14081.37Skamil 14091.37Skamil/// ---------------------------------------------------------------------------- 14101.37Skamil 14111.40Skamilstatic void 14121.40Skamiltraceme_vfork_raise(int sigval) 14131.40Skamil{ 14141.46Skamil const int exitval = 5, exitval_watcher = 10; 14151.46Skamil pid_t child, parent, watcher, wpid; 14161.46Skamil int rv; 14171.40Skamil#if defined(TWAIT_HAVE_STATUS) 14181.40Skamil int status; 14191.85Skamil 14201.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 14211.85Skamil volatile int expect_core; 14221.85Skamil 14231.85Skamil switch (sigval) { 14241.85Skamil case SIGABRT: 14251.85Skamil case SIGTRAP: 14261.85Skamil case SIGBUS: 14271.85Skamil case SIGILL: 14281.85Skamil case SIGFPE: 14291.85Skamil case SIGSEGV: 14301.85Skamil expect_core = 1; 14311.85Skamil break; 14321.85Skamil default: 14331.85Skamil expect_core = 0; 14341.85Skamil break; 14351.85Skamil } 14361.40Skamil#endif 14371.40Skamil 14381.46Skamil /* 14391.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14401.46Skamil * the SIGKILL signal to it. 14411.46Skamil * 14421.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14431.46Skamil * simpler to reparent this process to initproc and forget about it. 14441.46Skamil */ 14451.46Skamil if (sigval == SIGSTOP) { 14461.46Skamil parent = getpid(); 14471.46Skamil 14481.46Skamil watcher = fork(); 14491.46Skamil ATF_REQUIRE(watcher != 1); 14501.46Skamil if (watcher == 0) { 14511.46Skamil /* Double fork(2) trick to reparent to initproc */ 14521.46Skamil watcher = fork(); 14531.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14541.46Skamil if (watcher != 0) 14551.46Skamil _exit(exitval_watcher); 14561.46Skamil 14571.46Skamil child = await_stopped_child(parent); 14581.46Skamil 14591.46Skamil errno = 0; 14601.46Skamil rv = kill(child, SIGKILL); 14611.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14621.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14631.46Skamil 14641.46Skamil /* This exit value will be collected by initproc */ 14651.46Skamil _exit(0); 14661.46Skamil } 14671.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14681.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14691.61Skre watcher); 14701.46Skamil 14711.46Skamil validate_status_exited(status, exitval_watcher); 14721.46Skamil 14731.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14741.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14751.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14761.46Skamil } 14771.46Skamil 14781.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14791.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14801.40Skamil if (child == 0) { 14811.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14821.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14831.40Skamil 14841.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14851.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14861.40Skamil 14871.40Skamil switch (sigval) { 14881.46Skamil case SIGSTOP: 14891.40Skamil case SIGKILL: 14901.40Skamil case SIGABRT: 14911.40Skamil case SIGHUP: 14921.85Skamil case SIGTRAP: 14931.85Skamil case SIGBUS: 14941.85Skamil case SIGILL: 14951.85Skamil case SIGFPE: 14961.85Skamil case SIGSEGV: 14971.40Skamil /* NOTREACHED */ 14981.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14991.70Smrg __unreachable(); 15001.40Skamil default: 15011.40Skamil DPRINTF("Before exiting of the child process\n"); 15021.40Skamil _exit(exitval); 15031.40Skamil } 15041.40Skamil } 15051.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15061.40Skamil 15071.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15081.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15091.40Skamil 15101.40Skamil switch (sigval) { 15111.40Skamil case SIGKILL: 15121.40Skamil case SIGABRT: 15131.40Skamil case SIGHUP: 15141.85Skamil case SIGTRAP: 15151.85Skamil case SIGBUS: 15161.85Skamil case SIGILL: 15171.85Skamil case SIGFPE: 15181.85Skamil case SIGSEGV: 15191.40Skamil validate_status_signaled(status, sigval, expect_core); 15201.40Skamil break; 15211.40Skamil case SIGSTOP: 15221.46Skamil validate_status_signaled(status, SIGKILL, 0); 15231.46Skamil break; 15241.40Skamil case SIGCONT: 15251.47Skamil case SIGTSTP: 15261.47Skamil case SIGTTIN: 15271.47Skamil case SIGTTOU: 15281.40Skamil validate_status_exited(status, exitval); 15291.40Skamil break; 15301.40Skamil default: 15311.40Skamil /* NOTREACHED */ 15321.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15331.40Skamil break; 15341.40Skamil } 15351.40Skamil 15361.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15371.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15381.40Skamil} 15391.40Skamil 15401.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15411.61SkreATF_TC(test); \ 15421.61SkreATF_TC_HEAD(test, tc) \ 15431.61Skre{ \ 15441.61Skre atf_tc_set_md_var(tc, "descr", \ 15451.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15461.61Skre "vfork(2)ed child"); \ 15471.61Skre} \ 15481.61Skre \ 15491.61SkreATF_TC_BODY(test, tc) \ 15501.61Skre{ \ 15511.61Skre \ 15521.61Skre traceme_vfork_raise(sig); \ 15531.40Skamil} 15541.40Skamil 15551.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15561.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15571.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15581.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15591.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15601.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15611.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15621.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15631.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15641.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15651.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15661.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15671.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15681.40Skamil 15691.40Skamil/// ---------------------------------------------------------------------------- 15701.40Skamil 15711.52Skamilstatic void 15721.52Skamiltraceme_vfork_crash(int sig) 15731.41Skamil{ 15741.41Skamil pid_t child, wpid; 15751.41Skamil#if defined(TWAIT_HAVE_STATUS) 15761.41Skamil int status; 15771.41Skamil#endif 15781.41Skamil 15791.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15801.71Skamil if (sig == SIGILL) 15811.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15821.71Skamil#endif 15831.71Skamil 15841.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15851.114Skamil atf_tc_skip("FP exceptions are not supported"); 15861.114Skamil 15871.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15881.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15891.41Skamil if (child == 0) { 15901.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15911.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15921.41Skamil 15931.52Skamil DPRINTF("Before executing a trap\n"); 15941.52Skamil switch (sig) { 15951.52Skamil case SIGTRAP: 15961.52Skamil trigger_trap(); 15971.52Skamil break; 15981.52Skamil case SIGSEGV: 15991.52Skamil trigger_segv(); 16001.52Skamil break; 16011.52Skamil case SIGILL: 16021.52Skamil trigger_ill(); 16031.52Skamil break; 16041.52Skamil case SIGFPE: 16051.52Skamil trigger_fpe(); 16061.52Skamil break; 16071.52Skamil case SIGBUS: 16081.52Skamil trigger_bus(); 16091.52Skamil break; 16101.52Skamil default: 16111.52Skamil /* NOTREACHED */ 16121.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16131.52Skamil } 16141.41Skamil 16151.41Skamil /* NOTREACHED */ 16161.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16171.41Skamil } 16181.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16191.41Skamil 16201.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16211.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16221.41Skamil 16231.52Skamil validate_status_signaled(status, sig, 1); 16241.41Skamil 16251.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16261.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16271.41Skamil} 16281.41Skamil 16291.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16301.61SkreATF_TC(test); \ 16311.61SkreATF_TC_HEAD(test, tc) \ 16321.61Skre{ \ 16331.61Skre atf_tc_set_md_var(tc, "descr", \ 16341.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16351.61Skre "vfork(2)ed child"); \ 16361.61Skre} \ 16371.61Skre \ 16381.61SkreATF_TC_BODY(test, tc) \ 16391.61Skre{ \ 16401.61Skre \ 16411.61Skre traceme_vfork_crash(sig); \ 16421.52Skamil} 16431.52Skamil 16441.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16451.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16461.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16471.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16481.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16491.52Skamil 16501.41Skamil/// ---------------------------------------------------------------------------- 16511.41Skamil 16521.92Skamilstatic void 16531.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16541.92Skamil{ 16551.92Skamil pid_t child, wpid; 16561.92Skamil#if defined(TWAIT_HAVE_STATUS) 16571.92Skamil int status; 16581.92Skamil#endif 16591.92Skamil sigset_t intmask; 16601.92Skamil 16611.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16621.92Skamil if (sig == SIGILL) 16631.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16641.92Skamil#endif 16651.92Skamil 16661.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16671.114Skamil atf_tc_skip("FP exceptions are not supported"); 16681.114Skamil 16691.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16701.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16711.92Skamil if (child == 0) { 16721.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16731.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16741.92Skamil 16751.92Skamil sigemptyset(&intmask); 16761.92Skamil sigaddset(&intmask, sig); 16771.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16781.92Skamil 16791.92Skamil DPRINTF("Before executing a trap\n"); 16801.92Skamil switch (sig) { 16811.92Skamil case SIGTRAP: 16821.92Skamil trigger_trap(); 16831.92Skamil break; 16841.92Skamil case SIGSEGV: 16851.92Skamil trigger_segv(); 16861.92Skamil break; 16871.92Skamil case SIGILL: 16881.92Skamil trigger_ill(); 16891.92Skamil break; 16901.92Skamil case SIGFPE: 16911.92Skamil trigger_fpe(); 16921.92Skamil break; 16931.92Skamil case SIGBUS: 16941.92Skamil trigger_bus(); 16951.92Skamil break; 16961.92Skamil default: 16971.92Skamil /* NOTREACHED */ 16981.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16991.92Skamil } 17001.92Skamil 17011.92Skamil /* NOTREACHED */ 17021.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17031.92Skamil } 17041.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17051.92Skamil 17061.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17071.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17081.92Skamil 17091.92Skamil validate_status_signaled(status, sig, 1); 17101.92Skamil 17111.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17121.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17131.92Skamil} 17141.92Skamil 17151.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 17161.92SkamilATF_TC(test); \ 17171.92SkamilATF_TC_HEAD(test, tc) \ 17181.92Skamil{ \ 17191.92Skamil atf_tc_set_md_var(tc, "descr", \ 17201.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17211.92Skamil "vfork(2)ed child with a masked signal"); \ 17221.92Skamil} \ 17231.92Skamil \ 17241.92SkamilATF_TC_BODY(test, tc) \ 17251.92Skamil{ \ 17261.92Skamil \ 17271.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17281.92Skamil} 17291.92Skamil 17301.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17311.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17321.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17331.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17341.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17351.92Skamil 17361.92Skamil/// ---------------------------------------------------------------------------- 17371.92Skamil 17381.92Skamilstatic void 17391.92Skamiltraceme_vfork_signalignored_crash(int sig) 17401.92Skamil{ 17411.92Skamil pid_t child, wpid; 17421.92Skamil#if defined(TWAIT_HAVE_STATUS) 17431.92Skamil int status; 17441.92Skamil#endif 17451.92Skamil struct sigaction sa; 17461.92Skamil 17471.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17481.92Skamil if (sig == SIGILL) 17491.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17501.92Skamil#endif 17511.92Skamil 17521.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17531.114Skamil atf_tc_skip("FP exceptions are not supported"); 17541.114Skamil 17551.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17561.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17571.92Skamil if (child == 0) { 17581.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17591.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17601.92Skamil 17611.92Skamil memset(&sa, 0, sizeof(sa)); 17621.92Skamil sa.sa_handler = SIG_IGN; 17631.92Skamil sigemptyset(&sa.sa_mask); 17641.92Skamil 17651.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17661.92Skamil 17671.92Skamil DPRINTF("Before executing a trap\n"); 17681.92Skamil switch (sig) { 17691.92Skamil case SIGTRAP: 17701.92Skamil trigger_trap(); 17711.92Skamil break; 17721.92Skamil case SIGSEGV: 17731.92Skamil trigger_segv(); 17741.92Skamil break; 17751.92Skamil case SIGILL: 17761.92Skamil trigger_ill(); 17771.92Skamil break; 17781.92Skamil case SIGFPE: 17791.92Skamil trigger_fpe(); 17801.92Skamil break; 17811.92Skamil case SIGBUS: 17821.92Skamil trigger_bus(); 17831.92Skamil break; 17841.92Skamil default: 17851.92Skamil /* NOTREACHED */ 17861.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17871.92Skamil } 17881.92Skamil 17891.92Skamil /* NOTREACHED */ 17901.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17911.92Skamil } 17921.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17931.92Skamil 17941.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17951.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17961.92Skamil 17971.92Skamil validate_status_signaled(status, sig, 1); 17981.92Skamil 17991.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18001.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 18011.92Skamil} 18021.92Skamil 18031.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 18041.92SkamilATF_TC(test); \ 18051.92SkamilATF_TC_HEAD(test, tc) \ 18061.92Skamil{ \ 18071.92Skamil atf_tc_set_md_var(tc, "descr", \ 18081.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 18091.92Skamil "vfork(2)ed child with ignored signal"); \ 18101.92Skamil} \ 18111.92Skamil \ 18121.92SkamilATF_TC_BODY(test, tc) \ 18131.92Skamil{ \ 18141.92Skamil \ 18151.92Skamil traceme_vfork_signalignored_crash(sig); \ 18161.92Skamil} 18171.92Skamil 18181.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 18191.92Skamil SIGTRAP) 18201.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 18211.92Skamil SIGSEGV) 18221.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 18231.92Skamil SIGILL) 18241.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 18251.92Skamil SIGFPE) 18261.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 18271.92Skamil SIGBUS) 18281.92Skamil 18291.92Skamil/// ---------------------------------------------------------------------------- 18301.92Skamil 18311.96Skamilstatic void 18321.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18331.43Skamil{ 18341.43Skamil const int sigval = SIGTRAP; 18351.43Skamil pid_t child, wpid; 18361.43Skamil#if defined(TWAIT_HAVE_STATUS) 18371.43Skamil int status; 18381.43Skamil#endif 18391.96Skamil struct sigaction sa; 18401.61Skre struct ptrace_siginfo info; 18411.96Skamil sigset_t intmask; 18421.96Skamil struct kinfo_proc2 kp; 18431.96Skamil size_t len = sizeof(kp); 18441.96Skamil 18451.96Skamil int name[6]; 18461.96Skamil const size_t namelen = __arraycount(name); 18471.96Skamil ki_sigset_t kp_sigmask; 18481.96Skamil ki_sigset_t kp_sigignore; 18491.43Skamil 18501.43Skamil memset(&info, 0, sizeof(info)); 18511.43Skamil 18521.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18531.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18541.43Skamil if (child == 0) { 18551.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18561.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18571.43Skamil 18581.96Skamil if (masked) { 18591.96Skamil sigemptyset(&intmask); 18601.96Skamil sigaddset(&intmask, sigval); 18611.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18621.96Skamil } 18631.96Skamil 18641.96Skamil if (ignored) { 18651.96Skamil memset(&sa, 0, sizeof(sa)); 18661.96Skamil sa.sa_handler = SIG_IGN; 18671.96Skamil sigemptyset(&sa.sa_mask); 18681.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18691.96Skamil } 18701.96Skamil 18711.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18721.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18731.43Skamil 18741.43Skamil /* NOTREACHED */ 18751.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18761.43Skamil } 18771.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18781.43Skamil 18791.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18801.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18811.43Skamil 18821.43Skamil validate_status_stopped(status, sigval); 18831.43Skamil 18841.96Skamil name[0] = CTL_KERN, 18851.96Skamil name[1] = KERN_PROC2, 18861.96Skamil name[2] = KERN_PROC_PID; 18871.96Skamil name[3] = getpid(); 18881.96Skamil name[4] = sizeof(kp); 18891.96Skamil name[5] = 1; 18901.96Skamil 18911.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18921.96Skamil 18931.96Skamil if (masked) 18941.96Skamil kp_sigmask = kp.p_sigmask; 18951.96Skamil 18961.96Skamil if (ignored) 18971.96Skamil kp_sigignore = kp.p_sigignore; 18981.96Skamil 18991.96Skamil name[3] = getpid(); 19001.96Skamil 19011.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 19021.96Skamil 19031.96Skamil if (masked) { 19041.96Skamil DPRINTF("kp_sigmask=" 19051.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19061.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 19071.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 19081.96Skamil 19091.96Skamil DPRINTF("kp.p_sigmask=" 19101.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19111.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 19121.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 19131.96Skamil 19141.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 19151.96Skamil sizeof(kp_sigmask))); 19161.96Skamil } 19171.96Skamil 19181.96Skamil if (ignored) { 19191.96Skamil DPRINTF("kp_sigignore=" 19201.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19211.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 19221.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 19231.96Skamil 19241.96Skamil DPRINTF("kp.p_sigignore=" 19251.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19261.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 19271.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19281.96Skamil 19291.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19301.96Skamil sizeof(kp_sigignore))); 19311.96Skamil } 19321.96Skamil 19331.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19341.61Skre SYSCALL_REQUIRE( 19351.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19361.43Skamil 19371.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19381.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19391.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19401.43Skamil info.psi_siginfo.si_errno); 19411.43Skamil 19421.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19431.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19441.43Skamil 19451.43Skamil DPRINTF("Before resuming the child process where it left off and " 19461.43Skamil "without signal to be sent\n"); 19471.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19481.43Skamil 19491.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19501.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19511.43Skamil 19521.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19531.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19541.43Skamil} 19551.43Skamil 19561.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19571.96SkamilATF_TC(test); \ 19581.96SkamilATF_TC_HEAD(test, tc) \ 19591.96Skamil{ \ 19601.96Skamil atf_tc_set_md_var(tc, "descr", \ 19611.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19621.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19631.96Skamil masked ? " with ignored signal" : ""); \ 19641.96Skamil} \ 19651.96Skamil \ 19661.96SkamilATF_TC_BODY(test, tc) \ 19671.96Skamil{ \ 19681.96Skamil \ 19691.96Skamil traceme_vfork_exec(masked, ignored); \ 19701.96Skamil} 19711.96Skamil 19721.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19731.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19741.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19751.96Skamil 19761.43Skamil/// ---------------------------------------------------------------------------- 19771.43Skamil 19781.1Skamil#if defined(TWAIT_HAVE_PID) 19791.51Skamilstatic void 19801.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19811.59Skamil{ 19821.94Skamil const int sigval = SIGSTOP; 19831.59Skamil struct msg_fds parent_tracee, parent_tracer; 19841.59Skamil const int exitval = 10; 19851.59Skamil pid_t tracee, tracer, wpid; 19861.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19871.59Skamil#if defined(TWAIT_HAVE_STATUS) 19881.59Skamil int status; 19891.59Skamil#endif 19901.94Skamil struct sigaction sa; 19911.59Skamil struct ptrace_siginfo info; 19921.94Skamil sigset_t intmask; 19931.94Skamil struct kinfo_proc2 kp; 19941.94Skamil size_t len = sizeof(kp); 19951.94Skamil 19961.94Skamil int name[6]; 19971.94Skamil const size_t namelen = __arraycount(name); 19981.94Skamil ki_sigset_t kp_sigmask; 19991.94Skamil ki_sigset_t kp_sigignore; 20001.61Skre 20011.71Skamil#ifndef PTRACE_ILLEGAL_ASM 20021.71Skamil if (sig == SIGILL) 20031.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 20041.71Skamil#endif 20051.71Skamil 20061.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 20071.114Skamil atf_tc_skip("FP exceptions are not supported"); 20081.114Skamil 20091.59Skamil memset(&info, 0, sizeof(info)); 20101.59Skamil 20111.59Skamil DPRINTF("Spawn tracee\n"); 20121.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 20131.59Skamil tracee = atf_utils_fork(); 20141.59Skamil if (tracee == 0) { 20151.59Skamil // Wait for parent to let us crash 20161.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 20171.61Skre 20181.94Skamil if (masked) { 20191.94Skamil sigemptyset(&intmask); 20201.94Skamil sigaddset(&intmask, sig); 20211.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 20221.94Skamil } 20231.94Skamil 20241.94Skamil if (ignored) { 20251.94Skamil memset(&sa, 0, sizeof(sa)); 20261.94Skamil sa.sa_handler = SIG_IGN; 20271.94Skamil sigemptyset(&sa.sa_mask); 20281.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20291.94Skamil } 20301.94Skamil 20311.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20321.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20331.94Skamil 20341.59Skamil DPRINTF("Before executing a trap\n"); 20351.59Skamil switch (sig) { 20361.59Skamil case SIGTRAP: 20371.59Skamil trigger_trap(); 20381.59Skamil break; 20391.59Skamil case SIGSEGV: 20401.59Skamil trigger_segv(); 20411.59Skamil break; 20421.59Skamil case SIGILL: 20431.59Skamil trigger_ill(); 20441.59Skamil break; 20451.59Skamil case SIGFPE: 20461.59Skamil trigger_fpe(); 20471.59Skamil break; 20481.59Skamil case SIGBUS: 20491.59Skamil trigger_bus(); 20501.59Skamil break; 20511.59Skamil default: 20521.59Skamil /* NOTREACHED */ 20531.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20541.59Skamil } 20551.59Skamil 20561.59Skamil /* NOTREACHED */ 20571.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20581.59Skamil } 20591.59Skamil 20601.59Skamil DPRINTF("Spawn debugger\n"); 20611.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20621.59Skamil tracer = atf_utils_fork(); 20631.59Skamil if (tracer == 0) { 20641.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20651.59Skamil tracer = atf_utils_fork(); 20661.59Skamil if (tracer != 0) 20671.61Skre _exit(exitval); 20681.59Skamil 20691.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20701.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20711.59Skamil 20721.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20731.59Skamil FORKEE_REQUIRE_SUCCESS( 20741.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20751.59Skamil 20761.59Skamil forkee_status_stopped(status, SIGSTOP); 20771.59Skamil 20781.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20791.94Skamil "traced process\n"); 20801.94Skamil SYSCALL_REQUIRE( 20811.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20821.94Skamil 20831.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20841.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20851.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20861.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20871.94Skamil 20881.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20891.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20901.94Skamil 20911.59Skamil /* Resume tracee with PT_CONTINUE */ 20921.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20931.59Skamil 20941.59Skamil /* Inform parent that tracer has attached to tracee */ 20951.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20961.59Skamil 20971.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20981.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20991.59Skamil 21001.59Skamil /* Wait for tracee and assert that it exited */ 21011.59Skamil FORKEE_REQUIRE_SUCCESS( 21021.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21031.59Skamil 21041.94Skamil forkee_status_stopped(status, sigval); 21051.94Skamil 21061.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21071.94Skamil "traced process\n"); 21081.94Skamil SYSCALL_REQUIRE( 21091.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21101.94Skamil 21111.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21121.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21131.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 21141.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21151.94Skamil 21161.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 21171.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 21181.94Skamil 21191.94Skamil name[0] = CTL_KERN, 21201.94Skamil name[1] = KERN_PROC2, 21211.94Skamil name[2] = KERN_PROC_PID; 21221.94Skamil name[3] = tracee; 21231.94Skamil name[4] = sizeof(kp); 21241.94Skamil name[5] = 1; 21251.94Skamil 21261.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21271.94Skamil 21281.94Skamil if (masked) 21291.94Skamil kp_sigmask = kp.p_sigmask; 21301.94Skamil 21311.94Skamil if (ignored) 21321.94Skamil kp_sigignore = kp.p_sigignore; 21331.94Skamil 21341.94Skamil /* Resume tracee with PT_CONTINUE */ 21351.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21361.94Skamil 21371.94Skamil /* Wait for tracee and assert that it exited */ 21381.94Skamil FORKEE_REQUIRE_SUCCESS( 21391.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21401.94Skamil 21411.93Skamil forkee_status_stopped(status, sig); 21421.59Skamil 21431.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21441.61Skre "traced process\n"); 21451.61Skre SYSCALL_REQUIRE( 21461.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21471.59Skamil 21481.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21491.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21501.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21511.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21521.59Skamil 21531.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21541.94Skamil 21551.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21561.94Skamil 21571.94Skamil if (masked) { 21581.94Skamil DPRINTF("kp_sigmask=" 21591.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21601.94Skamil PRIx32 "\n", 21611.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21621.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21631.94Skamil 21641.94Skamil DPRINTF("kp.p_sigmask=" 21651.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21661.94Skamil PRIx32 "\n", 21671.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21681.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21691.94Skamil 21701.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21711.94Skamil sizeof(kp_sigmask))); 21721.94Skamil } 21731.94Skamil 21741.94Skamil if (ignored) { 21751.94Skamil DPRINTF("kp_sigignore=" 21761.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21771.94Skamil PRIx32 "\n", 21781.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21791.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21801.94Skamil 21811.94Skamil DPRINTF("kp.p_sigignore=" 21821.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21831.94Skamil PRIx32 "\n", 21841.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21851.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21861.94Skamil 21871.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21881.94Skamil sizeof(kp_sigignore))); 21891.94Skamil } 21901.94Skamil 21911.59Skamil switch (sig) { 21921.59Skamil case SIGTRAP: 21931.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21941.59Skamil break; 21951.59Skamil case SIGSEGV: 21961.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21971.59Skamil break; 21981.71Skamil case SIGILL: 21991.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 22001.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 22011.71Skamil break; 22021.59Skamil case SIGFPE: 22031.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 22041.59Skamil break; 22051.59Skamil case SIGBUS: 22061.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 22071.59Skamil break; 22081.59Skamil } 22091.59Skamil 22101.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 22111.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 22121.93Skamil FORKEE_REQUIRE_SUCCESS( 22131.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22141.59Skamil 22151.93Skamil forkee_status_signaled(status, SIGKILL, 0); 22161.59Skamil 22171.71Skamil /* Inform parent that tracer is exiting normally */ 22181.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 22191.71Skamil 22201.59Skamil DPRINTF("Before exiting of the tracer process\n"); 22211.59Skamil _exit(0 /* collect by initproc */); 22221.59Skamil } 22231.59Skamil 22241.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 22251.59Skamil "calling %s()\n", TWAIT_FNAME); 22261.59Skamil TWAIT_REQUIRE_SUCCESS( 22271.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22281.59Skamil 22291.59Skamil validate_status_exited(status, exitval); 22301.59Skamil 22311.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22321.59Skamil TWAIT_FNAME); 22331.59Skamil TWAIT_REQUIRE_SUCCESS( 22341.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22351.59Skamil 22361.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22371.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22381.59Skamil 22391.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22401.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22411.59Skamil 22421.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22431.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22441.59Skamil 22451.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22461.59Skamil TWAIT_FNAME); 22471.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22481.59Skamil 22491.59Skamil validate_status_signaled(status, SIGKILL, 0); 22501.59Skamil 22511.71Skamil DPRINTF("Await normal exit of tracer\n"); 22521.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22531.71Skamil 22541.59Skamil msg_close(&parent_tracer); 22551.59Skamil msg_close(&parent_tracee); 22561.59Skamil} 22571.59Skamil 22581.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22591.61SkreATF_TC(test); \ 22601.61SkreATF_TC_HEAD(test, tc) \ 22611.61Skre{ \ 22621.61Skre atf_tc_set_md_var(tc, "descr", \ 22631.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22641.94Skamil "the debuggee"); \ 22651.61Skre} \ 22661.61Skre \ 22671.61SkreATF_TC_BODY(test, tc) \ 22681.61Skre{ \ 22691.61Skre \ 22701.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22711.59Skamil} 22721.59Skamil 22731.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22741.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22751.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22761.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22771.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22781.94Skamil 22791.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22801.94SkamilATF_TC(test); \ 22811.94SkamilATF_TC_HEAD(test, tc) \ 22821.94Skamil{ \ 22831.94Skamil atf_tc_set_md_var(tc, "descr", \ 22841.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22851.94Skamil "the debuggee with masked signal"); \ 22861.94Skamil} \ 22871.94Skamil \ 22881.94SkamilATF_TC_BODY(test, tc) \ 22891.94Skamil{ \ 22901.94Skamil \ 22911.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22921.94Skamil} 22931.94Skamil 22941.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22951.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22961.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22971.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22981.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22991.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 23001.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 23011.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 23021.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 23031.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 23041.94Skamil 23051.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 23061.94SkamilATF_TC(test); \ 23071.94SkamilATF_TC_HEAD(test, tc) \ 23081.94Skamil{ \ 23091.94Skamil atf_tc_set_md_var(tc, "descr", \ 23101.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 23111.94Skamil "the debuggee with signal ignored"); \ 23121.94Skamil} \ 23131.94Skamil \ 23141.94SkamilATF_TC_BODY(test, tc) \ 23151.94Skamil{ \ 23161.94Skamil \ 23171.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 23181.94Skamil} 23191.94Skamil 23201.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23211.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 23221.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23231.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 23241.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23251.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 23261.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23271.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23281.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23291.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23301.59Skamil#endif 23311.59Skamil 23321.59Skamil/// ---------------------------------------------------------------------------- 23331.59Skamil 23341.59Skamil#if defined(TWAIT_HAVE_PID) 23351.59Skamilstatic void 23361.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23371.67Skamil bool stopped) 23381.1Skamil{ 23391.51Skamil /* 23401.51Skamil * notimeout - disable timeout in await zombie function 23411.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23421.67Skamil * stopped - attach to a stopped process 23431.51Skamil */ 23441.1Skamil 23451.1Skamil struct msg_fds parent_tracee, parent_tracer; 23461.1Skamil const int exitval_tracee = 5; 23471.1Skamil const int exitval_tracer = 10; 23481.1Skamil pid_t tracee, tracer, wpid; 23491.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23501.1Skamil#if defined(TWAIT_HAVE_STATUS) 23511.1Skamil int status; 23521.1Skamil#endif 23531.1Skamil 23541.67Skamil /* 23551.67Skamil * Only a subset of options are supported. 23561.67Skamil */ 23571.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23581.67Skamil (!notimeout && unrelated && !stopped) || 23591.67Skamil (notimeout && !unrelated && !stopped) || 23601.67Skamil (!notimeout && unrelated && stopped)); 23611.67Skamil 23621.13Schristos DPRINTF("Spawn tracee\n"); 23631.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23641.1Skamil tracee = atf_utils_fork(); 23651.1Skamil if (tracee == 0) { 23661.67Skamil if (stopped) { 23671.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23681.67Skamil raise(SIGSTOP); 23691.67Skamil } 23701.67Skamil 23711.1Skamil // Wait for parent to let us exit 23721.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23731.1Skamil _exit(exitval_tracee); 23741.1Skamil } 23751.1Skamil 23761.13Schristos DPRINTF("Spawn debugger\n"); 23771.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23781.1Skamil tracer = atf_utils_fork(); 23791.1Skamil if (tracer == 0) { 23801.51Skamil if(unrelated) { 23811.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23821.51Skamil tracer = atf_utils_fork(); 23831.51Skamil if (tracer != 0) 23841.51Skamil _exit(exitval_tracer); 23851.51Skamil } 23861.51Skamil 23871.67Skamil if (stopped) { 23881.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23891.67Skamil await_stopped(tracee); 23901.67Skamil } 23911.67Skamil 23921.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23931.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23941.1Skamil 23951.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23961.1Skamil FORKEE_REQUIRE_SUCCESS( 23971.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23981.1Skamil 23991.1Skamil forkee_status_stopped(status, SIGSTOP); 24001.1Skamil 24011.1Skamil /* Resume tracee with PT_CONTINUE */ 24021.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 24031.1Skamil 24041.1Skamil /* Inform parent that tracer has attached to tracee */ 24051.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 24061.1Skamil 24071.1Skamil /* Wait for parent to tell use that tracee should have exited */ 24081.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 24091.1Skamil 24101.1Skamil /* Wait for tracee and assert that it exited */ 24111.1Skamil FORKEE_REQUIRE_SUCCESS( 24121.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24131.1Skamil 24141.1Skamil forkee_status_exited(status, exitval_tracee); 24151.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 24161.1Skamil 24171.13Schristos DPRINTF("Before exiting of the tracer process\n"); 24181.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 24191.51Skamil } 24201.51Skamil 24211.51Skamil if (unrelated) { 24221.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 24231.51Skamil "calling %s()\n", TWAIT_FNAME); 24241.51Skamil TWAIT_REQUIRE_SUCCESS( 24251.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 24261.51Skamil 24271.51Skamil validate_status_exited(status, exitval_tracer); 24281.51Skamil 24291.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24301.51Skamil TWAIT_FNAME); 24311.51Skamil TWAIT_REQUIRE_SUCCESS( 24321.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24331.1Skamil } 24341.1Skamil 24351.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24361.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24371.1Skamil 24381.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24391.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24401.1Skamil 24411.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24421.51Skamil if (notimeout) 24431.26Skamil await_zombie_raw(tracee, 0); 24441.26Skamil else 24451.26Skamil await_zombie(tracee); 24461.1Skamil 24471.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24481.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24491.1Skamil TWAIT_FNAME); 24501.1Skamil TWAIT_REQUIRE_SUCCESS( 24511.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24521.1Skamil 24531.51Skamil if (unrelated) { 24541.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24551.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24561.51Skamil } else { 24571.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24581.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24591.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24601.59Skamil "%s()\n", TWAIT_FNAME); 24611.51Skamil 24621.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24631.59Skamil "tracee\n"); 24641.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24651.51Skamil tracer); 24661.1Skamil 24671.51Skamil validate_status_exited(status, exitval_tracer); 24681.51Skamil } 24691.1Skamil 24701.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24711.1Skamil TWAIT_FNAME); 24721.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24731.1Skamil 24741.1Skamil validate_status_exited(status, exitval_tracee); 24751.1Skamil 24761.1Skamil msg_close(&parent_tracer); 24771.1Skamil msg_close(&parent_tracee); 24781.1Skamil} 24791.26Skamil 24801.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24811.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24821.51Skamil{ 24831.51Skamil atf_tc_set_md_var(tc, "descr", 24841.51Skamil "Assert that tracer sees process termination before the parent"); 24851.51Skamil} 24861.51Skamil 24871.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24881.26Skamil{ 24891.26Skamil 24901.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24911.26Skamil} 24921.26Skamil 24931.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24941.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24951.1Skamil{ 24961.1Skamil atf_tc_set_md_var(tc, "descr", 24971.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24981.51Skamil "process and no other error is reported"); 24991.1Skamil} 25001.1Skamil 25011.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 25021.1Skamil{ 25031.51Skamil time_t start, end; 25041.51Skamil double diff; 25051.51Skamil unsigned long N = 0; 25061.1Skamil 25071.51Skamil /* 25081.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 25091.51Skamil * This test body isn't specific to this race, however it's just good 25101.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 25111.51Skamil */ 25121.1Skamil 25131.51Skamil start = time(NULL); 25141.51Skamil while (true) { 25151.51Skamil DPRINTF("Step: %lu\n", N); 25161.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 25171.67Skamil false); 25181.51Skamil end = time(NULL); 25191.51Skamil diff = difftime(end, start); 25201.51Skamil if (diff >= 5.0) 25211.51Skamil break; 25221.51Skamil ++N; 25231.1Skamil } 25241.51Skamil DPRINTF("Iterations: %lu\n", N); 25251.51Skamil} 25261.1Skamil 25271.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25281.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25291.51Skamil{ 25301.51Skamil atf_tc_set_md_var(tc, "descr", 25311.51Skamil "Assert that tracer sees process termination before the parent"); 25321.51Skamil} 25331.1Skamil 25341.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25351.51Skamil{ 25361.1Skamil 25371.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25381.67Skamil} 25391.67Skamil 25401.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25411.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25421.67Skamil{ 25431.67Skamil atf_tc_set_md_var(tc, "descr", 25441.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25451.67Skamil} 25461.67Skamil 25471.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25481.67Skamil{ 25491.67Skamil 25501.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25511.1Skamil} 25521.1Skamil#endif 25531.1Skamil 25541.51Skamil/// ---------------------------------------------------------------------------- 25551.51Skamil 25561.66Skamilstatic void 25571.66Skamilparent_attach_to_its_child(bool stopped) 25581.1Skamil{ 25591.1Skamil struct msg_fds parent_tracee; 25601.1Skamil const int exitval_tracee = 5; 25611.1Skamil pid_t tracee, wpid; 25621.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25631.1Skamil#if defined(TWAIT_HAVE_STATUS) 25641.1Skamil int status; 25651.1Skamil#endif 25661.1Skamil 25671.13Schristos DPRINTF("Spawn tracee\n"); 25681.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25691.1Skamil tracee = atf_utils_fork(); 25701.1Skamil if (tracee == 0) { 25711.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25721.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25731.1Skamil 25741.66Skamil if (stopped) { 25751.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25761.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25771.66Skamil } 25781.66Skamil 25791.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25801.1Skamil /* Wait for message from the parent */ 25811.1Skamil _exit(exitval_tracee); 25821.1Skamil } 25831.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25841.57Skamil 25851.66Skamil if (stopped) { 25861.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25871.66Skamil await_stopped(tracee); 25881.66Skamil } 25891.66Skamil 25901.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25911.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25921.1Skamil 25931.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25941.1Skamil TWAIT_FNAME); 25951.1Skamil TWAIT_REQUIRE_SUCCESS( 25961.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25971.1Skamil 25981.1Skamil validate_status_stopped(status, SIGSTOP); 25991.1Skamil 26001.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 26011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 26021.1Skamil 26031.13Schristos DPRINTF("Let the tracee exit now\n"); 26041.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 26051.1Skamil 26061.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 26071.1Skamil TWAIT_REQUIRE_SUCCESS( 26081.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 26091.1Skamil 26101.1Skamil validate_status_exited(status, exitval_tracee); 26111.1Skamil 26121.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 26131.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26141.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 26151.1Skamil 26161.1Skamil msg_close(&parent_tracee); 26171.1Skamil} 26181.1Skamil 26191.66SkamilATF_TC(parent_attach_to_its_child); 26201.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 26211.66Skamil{ 26221.66Skamil atf_tc_set_md_var(tc, "descr", 26231.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 26241.66Skamil} 26251.66Skamil 26261.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26271.66Skamil{ 26281.66Skamil 26291.66Skamil parent_attach_to_its_child(false); 26301.66Skamil} 26311.66Skamil 26321.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26331.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26341.66Skamil{ 26351.66Skamil atf_tc_set_md_var(tc, "descr", 26361.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26371.66Skamil} 26381.66Skamil 26391.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26401.66Skamil{ 26411.66Skamil 26421.66Skamil parent_attach_to_its_child(true); 26431.66Skamil} 26441.66Skamil 26451.51Skamil/// ---------------------------------------------------------------------------- 26461.51Skamil 26471.65Skamilstatic void 26481.65Skamilchild_attach_to_its_parent(bool stopped) 26491.1Skamil{ 26501.1Skamil struct msg_fds parent_tracee; 26511.1Skamil const int exitval_tracer = 5; 26521.1Skamil pid_t tracer, wpid; 26531.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26541.1Skamil#if defined(TWAIT_HAVE_STATUS) 26551.1Skamil int status; 26561.1Skamil#endif 26571.1Skamil 26581.13Schristos DPRINTF("Spawn tracer\n"); 26591.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26601.1Skamil tracer = atf_utils_fork(); 26611.1Skamil if (tracer == 0) { 26621.1Skamil /* Wait for message from the parent */ 26631.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26641.1Skamil 26651.65Skamil if (stopped) { 26661.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26671.65Skamil getppid()); 26681.65Skamil await_stopped(getppid()); 26691.65Skamil } 26701.65Skamil 26711.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26721.1Skamil getppid()); 26731.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26741.1Skamil 26751.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26761.1Skamil TWAIT_FNAME); 26771.1Skamil FORKEE_REQUIRE_SUCCESS( 26781.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26791.1Skamil 26801.1Skamil forkee_status_stopped(status, SIGSTOP); 26811.1Skamil 26821.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26831.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26841.1Skamil != -1); 26851.1Skamil 26861.1Skamil /* Tell parent we are ready */ 26871.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26881.1Skamil 26891.1Skamil _exit(exitval_tracer); 26901.1Skamil } 26911.1Skamil 26921.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26931.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26941.65Skamil 26951.65Skamil if (stopped) { 26961.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26971.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26981.65Skamil } 26991.65Skamil 27001.13Schristos DPRINTF("Allow the tracer to exit now\n"); 27011.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 27021.1Skamil 27031.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 27041.1Skamil TWAIT_REQUIRE_SUCCESS( 27051.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 27061.1Skamil 27071.1Skamil validate_status_exited(status, exitval_tracer); 27081.1Skamil 27091.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 27101.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 27111.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 27121.1Skamil 27131.1Skamil msg_close(&parent_tracee); 27141.1Skamil} 27151.1Skamil 27161.65SkamilATF_TC(child_attach_to_its_parent); 27171.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 27181.65Skamil{ 27191.65Skamil atf_tc_set_md_var(tc, "descr", 27201.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 27211.65Skamil} 27221.65Skamil 27231.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 27241.65Skamil{ 27251.65Skamil 27261.65Skamil child_attach_to_its_parent(false); 27271.65Skamil} 27281.65Skamil 27291.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27301.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27311.65Skamil{ 27321.65Skamil atf_tc_set_md_var(tc, "descr", 27331.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27341.65Skamil} 27351.65Skamil 27361.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27371.65Skamil{ 27381.65Skamil /* 27391.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27401.65Skamil * this causes a pipe (established from atf-run) to be broken. 27411.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27421.65Skamil * 27431.65Skamil * As a workaround spawn this test as a subprocess. 27441.65Skamil */ 27451.65Skamil 27461.65Skamil const int exitval = 15; 27471.65Skamil pid_t child, wpid; 27481.65Skamil#if defined(TWAIT_HAVE_STATUS) 27491.65Skamil int status; 27501.65Skamil#endif 27511.65Skamil 27521.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27531.65Skamil if (child == 0) { 27541.65Skamil child_attach_to_its_parent(true); 27551.65Skamil _exit(exitval); 27561.65Skamil } else { 27571.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27581.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27591.65Skamil 27601.65Skamil validate_status_exited(status, exitval); 27611.65Skamil 27621.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27631.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27641.65Skamil } 27651.65Skamil} 27661.65Skamil 27671.51Skamil/// ---------------------------------------------------------------------------- 27681.51Skamil 27691.1Skamil#if defined(TWAIT_HAVE_PID) 27701.1Skamil 27711.51Skamilenum tracee_sees_its_original_parent_type { 27721.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27731.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27741.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27751.51Skamil}; 27761.51Skamil 27771.51Skamilstatic void 27781.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27791.1Skamil{ 27801.1Skamil struct msg_fds parent_tracer, parent_tracee; 27811.1Skamil const int exitval_tracee = 5; 27821.1Skamil const int exitval_tracer = 10; 27831.1Skamil pid_t parent, tracee, tracer, wpid; 27841.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27851.1Skamil#if defined(TWAIT_HAVE_STATUS) 27861.1Skamil int status; 27871.1Skamil#endif 27881.51Skamil /* sysctl(3) - kinfo_proc2 */ 27891.51Skamil int name[CTL_MAXNAME]; 27901.51Skamil struct kinfo_proc2 kp; 27911.51Skamil size_t len = sizeof(kp); 27921.51Skamil unsigned int namelen; 27931.51Skamil 27941.51Skamil /* procfs - status */ 27951.51Skamil FILE *fp; 27961.51Skamil struct stat st; 27971.51Skamil const char *fname = "/proc/curproc/status"; 27981.51Skamil char s_executable[MAXPATHLEN]; 27991.51Skamil int s_pid, s_ppid; 28001.51Skamil int rv; 28011.51Skamil 28021.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 28031.61Skre SYSCALL_REQUIRE( 28041.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 28051.61Skre if (rv != 0) 28061.51Skamil atf_tc_skip("/proc/curproc/status not found"); 28071.51Skamil } 28081.1Skamil 28091.13Schristos DPRINTF("Spawn tracee\n"); 28101.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 28111.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 28121.1Skamil tracee = atf_utils_fork(); 28131.1Skamil if (tracee == 0) { 28141.1Skamil parent = getppid(); 28151.1Skamil 28161.1Skamil /* Emit message to the parent */ 28171.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 28181.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 28191.1Skamil 28201.51Skamil switch (type) { 28211.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 28221.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 28231.51Skamil break; 28241.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 28251.51Skamil namelen = 0; 28261.51Skamil name[namelen++] = CTL_KERN; 28271.51Skamil name[namelen++] = KERN_PROC2; 28281.51Skamil name[namelen++] = KERN_PROC_PID; 28291.51Skamil name[namelen++] = getpid(); 28301.51Skamil name[namelen++] = len; 28311.51Skamil name[namelen++] = 1; 28321.51Skamil 28331.61Skre FORKEE_ASSERT_EQ( 28341.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28351.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28361.51Skamil break; 28371.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28381.51Skamil /* 28391.51Skamil * Format: 28401.51Skamil * EXECUTABLE PID PPID ... 28411.51Skamil */ 28421.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28431.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28441.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28451.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28461.51Skamil break; 28471.51Skamil } 28481.1Skamil 28491.1Skamil _exit(exitval_tracee); 28501.1Skamil } 28511.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28521.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28531.1Skamil 28541.13Schristos DPRINTF("Spawn debugger\n"); 28551.1Skamil tracer = atf_utils_fork(); 28561.1Skamil if (tracer == 0) { 28571.1Skamil /* No IPC to communicate with the child */ 28581.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28591.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28601.1Skamil 28611.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28621.1Skamil FORKEE_REQUIRE_SUCCESS( 28631.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28641.1Skamil 28651.1Skamil forkee_status_stopped(status, SIGSTOP); 28661.1Skamil 28671.1Skamil /* Resume tracee with PT_CONTINUE */ 28681.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28691.1Skamil 28701.1Skamil /* Inform parent that tracer has attached to tracee */ 28711.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28721.1Skamil 28731.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28741.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28751.1Skamil 28761.1Skamil /* Wait for tracee and assert that it exited */ 28771.1Skamil FORKEE_REQUIRE_SUCCESS( 28781.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28791.1Skamil 28801.1Skamil forkee_status_exited(status, exitval_tracee); 28811.1Skamil 28821.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28831.1Skamil _exit(exitval_tracer); 28841.1Skamil } 28851.1Skamil 28861.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28871.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28881.1Skamil 28891.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28901.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28911.1Skamil 28921.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28931.1Skamil await_zombie(tracee); 28941.1Skamil 28951.13Schristos DPRINTF("Assert that there is no status about tracee - " 28961.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28971.1Skamil TWAIT_REQUIRE_SUCCESS( 28981.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28991.1Skamil 29001.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 29011.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 29021.1Skamil 29031.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 29041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 29051.1Skamil tracer); 29061.1Skamil 29071.1Skamil validate_status_exited(status, exitval_tracer); 29081.1Skamil 29091.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 29101.1Skamil TWAIT_FNAME); 29111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 29121.1Skamil tracee); 29131.1Skamil 29141.1Skamil validate_status_exited(status, exitval_tracee); 29151.1Skamil 29161.1Skamil msg_close(&parent_tracer); 29171.1Skamil msg_close(&parent_tracee); 29181.1Skamil} 29191.1Skamil 29201.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 29211.61SkreATF_TC(test); \ 29221.61SkreATF_TC_HEAD(test, tc) \ 29231.61Skre{ \ 29241.61Skre atf_tc_set_md_var(tc, "descr", \ 29251.61Skre "Assert that tracee sees its original parent when being traced " \ 29261.61Skre "(check " descr ")"); \ 29271.61Skre} \ 29281.61Skre \ 29291.61SkreATF_TC_BODY(test, tc) \ 29301.61Skre{ \ 29311.61Skre \ 29321.61Skre tracee_sees_its_original_parent(type); \ 29331.1Skamil} 29341.1Skamil 29351.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29361.51Skamil tracee_sees_its_original_parent_getppid, 29371.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29381.51Skamil "getppid(2)"); 29391.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29401.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29411.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29421.51Skamil "sysctl(3) and kinfo_proc2"); 29431.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29441.51Skamil tracee_sees_its_original_parent_procfs_status, 29451.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29461.51Skamil "the status file in procfs"); 29471.1Skamil#endif 29481.1Skamil 29491.51Skamil/// ---------------------------------------------------------------------------- 29501.1Skamil 29511.53Skamilstatic void 29521.53Skamileventmask_preserved(int event) 29531.1Skamil{ 29541.1Skamil const int exitval = 5; 29551.1Skamil const int sigval = SIGSTOP; 29561.1Skamil pid_t child, wpid; 29571.1Skamil#if defined(TWAIT_HAVE_STATUS) 29581.1Skamil int status; 29591.1Skamil#endif 29601.1Skamil ptrace_event_t set_event, get_event; 29611.1Skamil const int len = sizeof(ptrace_event_t); 29621.1Skamil 29631.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29641.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29651.1Skamil if (child == 0) { 29661.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29671.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29681.1Skamil 29691.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29701.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29711.1Skamil 29721.13Schristos DPRINTF("Before exiting of the child process\n"); 29731.1Skamil _exit(exitval); 29741.1Skamil } 29751.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29761.1Skamil 29771.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29781.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29791.1Skamil 29801.1Skamil validate_status_stopped(status, sigval); 29811.1Skamil 29821.53Skamil set_event.pe_set_event = event; 29831.61Skre SYSCALL_REQUIRE( 29841.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29851.61Skre SYSCALL_REQUIRE( 29861.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29871.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29881.125Skamil get_event.pe_set_event); 29891.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29901.1Skamil 29911.13Schristos DPRINTF("Before resuming the child process where it left off and " 29921.1Skamil "without signal to be sent\n"); 29931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29941.1Skamil 29951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29971.1Skamil 29981.1Skamil validate_status_exited(status, exitval); 29991.1Skamil 30001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30011.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 30021.1Skamil} 30031.1Skamil 30041.61Skre#define EVENTMASK_PRESERVED(test, event) \ 30051.61SkreATF_TC(test); \ 30061.61SkreATF_TC_HEAD(test, tc) \ 30071.61Skre{ \ 30081.61Skre atf_tc_set_md_var(tc, "descr", \ 30091.61Skre "Verify that eventmask " #event " is preserved"); \ 30101.61Skre} \ 30111.61Skre \ 30121.61SkreATF_TC_BODY(test, tc) \ 30131.61Skre{ \ 30141.61Skre \ 30151.61Skre eventmask_preserved(event); \ 30161.1Skamil} 30171.1Skamil 30181.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 30191.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 30201.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 30211.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 30221.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 30231.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 30241.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 30251.1Skamil 30261.53Skamil/// ---------------------------------------------------------------------------- 30271.1Skamil 30281.28Skamilstatic void 30291.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 30301.105Skamil bool trackvforkdone) 30311.1Skamil{ 30321.1Skamil const int exitval = 5; 30331.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30341.1Skamil const int sigval = SIGSTOP; 30351.31Skamil pid_t child, child2 = 0, wpid; 30361.1Skamil#if defined(TWAIT_HAVE_STATUS) 30371.1Skamil int status; 30381.1Skamil#endif 30391.1Skamil ptrace_state_t state; 30401.1Skamil const int slen = sizeof(state); 30411.1Skamil ptrace_event_t event; 30421.1Skamil const int elen = sizeof(event); 30431.1Skamil 30441.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30451.124Skamil 30461.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30471.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30481.1Skamil if (child == 0) { 30491.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30501.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30511.1Skamil 30521.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30531.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30541.1Skamil 30551.125Skamil if (strcmp(fn, "spawn") == 0) { 30561.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30571.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30581.125Skamil } else { 30591.125Skamil if (strcmp(fn, "fork") == 0) { 30601.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30611.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30621.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30631.125Skamil } 30641.1Skamil 30651.124Skamil if (child2 == 0) 30661.124Skamil _exit(exitval2); 30671.124Skamil } 30681.1Skamil FORKEE_REQUIRE_SUCCESS 30691.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30701.1Skamil 30711.1Skamil forkee_status_exited(status, exitval2); 30721.1Skamil 30731.13Schristos DPRINTF("Before exiting of the child process\n"); 30741.1Skamil _exit(exitval); 30751.1Skamil } 30761.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30771.1Skamil 30781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30801.1Skamil 30811.1Skamil validate_status_stopped(status, sigval); 30821.1Skamil 30831.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30841.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30851.61Skre trackfork ? "|PTRACE_FORK" : "", 30861.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30871.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30881.30Skamil event.pe_set_event = 0; 30891.125Skamil if (trackspawn) 30901.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30911.30Skamil if (trackfork) 30921.30Skamil event.pe_set_event |= PTRACE_FORK; 30931.30Skamil if (trackvfork) 30941.30Skamil event.pe_set_event |= PTRACE_VFORK; 30951.30Skamil if (trackvforkdone) 30961.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30971.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30981.1Skamil 30991.13Schristos DPRINTF("Before resuming the child process where it left off and " 31001.1Skamil "without signal to be sent\n"); 31011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31021.1Skamil 31031.29Skamil#if defined(TWAIT_HAVE_PID) 31041.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31051.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31061.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31071.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31081.61Skre child); 31091.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 31101.61Skre child); 31111.1Skamil 31121.29Skamil validate_status_stopped(status, SIGTRAP); 31131.1Skamil 31141.61Skre SYSCALL_REQUIRE( 31151.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31161.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31171.125Skamil ATF_REQUIRE_EQ( 31181.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31191.125Skamil PTRACE_POSIX_SPAWN); 31201.125Skamil } 31211.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31221.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31231.30Skamil PTRACE_FORK); 31241.30Skamil } 31251.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31261.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31271.30Skamil PTRACE_VFORK); 31281.30Skamil } 31291.29Skamil 31301.29Skamil child2 = state.pe_other_pid; 31311.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31321.29Skamil 31331.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31341.61Skre "%d\n", TWAIT_FNAME, child2, child); 31351.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31361.29Skamil child2); 31371.1Skamil 31381.29Skamil validate_status_stopped(status, SIGTRAP); 31391.1Skamil 31401.61Skre SYSCALL_REQUIRE( 31411.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31421.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31431.125Skamil ATF_REQUIRE_EQ( 31441.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31451.125Skamil PTRACE_POSIX_SPAWN); 31461.125Skamil } 31471.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31481.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31491.30Skamil PTRACE_FORK); 31501.30Skamil } 31511.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31521.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31531.30Skamil PTRACE_VFORK); 31541.30Skamil } 31551.30Skamil 31561.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31571.29Skamil 31581.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31591.29Skamil "and without signal to be sent\n"); 31601.61Skre SYSCALL_REQUIRE( 31611.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31621.29Skamil 31631.29Skamil DPRINTF("Before resuming the child process where it left off " 31641.61Skre "and without signal to be sent\n"); 31651.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31661.30Skamil } 31671.30Skamil#endif 31681.30Skamil 31691.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31701.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31711.61Skre child); 31721.61Skre TWAIT_REQUIRE_SUCCESS( 31731.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31741.30Skamil 31751.30Skamil validate_status_stopped(status, SIGTRAP); 31761.30Skamil 31771.61Skre SYSCALL_REQUIRE( 31781.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31791.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31801.30Skamil 31811.30Skamil child2 = state.pe_other_pid; 31821.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31831.61Skre child2); 31841.30Skamil 31851.30Skamil DPRINTF("Before resuming the child process where it left off " 31861.61Skre "and without signal to be sent\n"); 31871.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31881.30Skamil } 31891.29Skamil 31901.30Skamil#if defined(TWAIT_HAVE_PID) 31911.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31921.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31931.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31941.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31951.61Skre "\n", TWAIT_FNAME); 31961.61Skre TWAIT_REQUIRE_SUCCESS( 31971.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31981.29Skamil 31991.29Skamil validate_status_exited(status, exitval2); 32001.29Skamil 32011.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 32021.61Skre "process\n", TWAIT_FNAME); 32031.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 32041.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 32051.29Skamil } 32061.29Skamil#endif 32071.1Skamil 32081.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 32091.1Skamil "SIGCHLD\n", TWAIT_FNAME); 32101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32111.1Skamil 32121.1Skamil validate_status_stopped(status, SIGCHLD); 32131.1Skamil 32141.13Schristos DPRINTF("Before resuming the child process where it left off and " 32151.1Skamil "without signal to be sent\n"); 32161.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 32171.1Skamil 32181.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 32191.1Skamil TWAIT_FNAME); 32201.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32211.1Skamil 32221.1Skamil validate_status_exited(status, exitval); 32231.1Skamil 32241.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 32251.1Skamil TWAIT_FNAME); 32261.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32271.1Skamil} 32281.28Skamil 32291.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 32301.61SkreATF_TC(name); \ 32311.61SkreATF_TC_HEAD(name, tc) \ 32321.61Skre{ \ 32331.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32341.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32351.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32361.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32371.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32381.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32391.61Skre} \ 32401.61Skre \ 32411.61SkreATF_TC_BODY(name, tc) \ 32421.61Skre{ \ 32431.61Skre \ 32441.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32451.32Skamil} 32461.32Skamil 32471.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32481.31Skamil#if defined(TWAIT_HAVE_PID) 32491.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32501.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32511.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32521.31Skamil#endif 32531.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32541.31Skamil#if defined(TWAIT_HAVE_PID) 32551.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32561.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32571.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32581.125Skamil#endif 32591.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32601.125Skamil#if defined(TWAIT_HAVE_PID) 32611.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32621.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32631.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32641.125Skamil#endif 32651.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32661.125Skamil#if defined(TWAIT_HAVE_PID) 32671.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32681.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32691.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32701.31Skamil#endif 32711.1Skamil 32721.110Skamil#if TEST_VFORK_ENABLED 32731.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32741.31Skamil#if defined(TWAIT_HAVE_PID) 32751.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32761.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32771.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32781.31Skamil#endif 32791.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32801.31Skamil#if defined(TWAIT_HAVE_PID) 32811.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32821.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32831.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32841.31Skamil#endif 32851.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32861.125Skamil#if defined(TWAIT_HAVE_PID) 32871.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32881.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32891.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32901.110Skamil#endif 32911.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32921.124Skamil#if defined(TWAIT_HAVE_PID) 32931.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32941.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32951.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32961.124Skamil#endif 32971.125Skamil#endif 32981.125Skamil 32991.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 33001.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 33011.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 33021.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 33031.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 33041.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 33051.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 33061.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 33071.124Skamil#if defined(TWAIT_HAVE_PID) 33081.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 33091.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 33101.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 33111.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 33121.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 33131.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 33141.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 33151.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 33161.124Skamil#endif 33171.124Skamil 33181.54Skamil/// ---------------------------------------------------------------------------- 33191.31Skamil 33201.116Skamil#if defined(TWAIT_HAVE_PID) 33211.116Skamilstatic void 33221.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 33231.116Skamil{ 33241.116Skamil const int exitval = 5; 33251.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 33261.116Skamil const int sigval = SIGSTOP; 33271.116Skamil pid_t child, child2 = 0, wpid; 33281.116Skamil#if defined(TWAIT_HAVE_STATUS) 33291.116Skamil int status; 33301.116Skamil#endif 33311.116Skamil ptrace_state_t state; 33321.116Skamil const int slen = sizeof(state); 33331.116Skamil ptrace_event_t event; 33341.116Skamil const int elen = sizeof(event); 33351.116Skamil 33361.116Skamil int op; 33371.116Skamil 33381.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33391.116Skamil 33401.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33411.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 33421.116Skamil if (child == 0) { 33431.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33441.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33451.116Skamil 33461.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33471.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 33481.116Skamil 33491.126Skamil if (strcmp(fn, "spawn") == 0) { 33501.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 33511.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 33521.126Skamil } else { 33531.126Skamil if (strcmp(fn, "fork") == 0) { 33541.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 33551.126Skamil } else { 33561.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 33571.126Skamil } 33581.116Skamil 33591.126Skamil if (child2 == 0) 33601.126Skamil _exit(exitval2); 33611.126Skamil } 33621.116Skamil 33631.116Skamil FORKEE_REQUIRE_SUCCESS 33641.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33651.116Skamil 33661.116Skamil forkee_status_exited(status, exitval2); 33671.116Skamil 33681.116Skamil DPRINTF("Before exiting of the child process\n"); 33691.116Skamil _exit(exitval); 33701.116Skamil } 33711.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33721.116Skamil 33731.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33741.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33751.116Skamil 33761.116Skamil validate_status_stopped(status, sigval); 33771.116Skamil 33781.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 33791.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 33801.126Skamil | PTRACE_VFORK_DONE; 33811.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 33821.116Skamil 33831.116Skamil DPRINTF("Before resuming the child process where it left off and " 33841.116Skamil "without signal to be sent\n"); 33851.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 33861.116Skamil 33871.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 33881.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33891.116Skamil 33901.116Skamil validate_status_stopped(status, SIGTRAP); 33911.116Skamil 33921.116Skamil SYSCALL_REQUIRE( 33931.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33941.126Skamil 33951.126Skamil if (strcmp(fn, "spawn") == 0) 33961.126Skamil op = PTRACE_POSIX_SPAWN; 33971.126Skamil else if (strcmp(fn, "fork") == 0) 33981.126Skamil op = PTRACE_FORK; 33991.126Skamil else 34001.126Skamil op = PTRACE_VFORK; 34011.126Skamil 34021.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 34031.116Skamil 34041.116Skamil child2 = state.pe_other_pid; 34051.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 34061.116Skamil 34071.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 34081.126Skamil strcmp(fn, "vfork") == 0) 34091.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34101.116Skamil else 34111.116Skamil op = PT_CONTINUE; 34121.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34131.116Skamil 34141.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 34151.116Skamil TWAIT_FNAME, child2, child); 34161.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34171.116Skamil 34181.116Skamil validate_status_stopped(status, SIGTRAP); 34191.116Skamil 34201.116Skamil SYSCALL_REQUIRE( 34211.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 34221.126Skamil if (strcmp(fn, "spawn") == 0) 34231.126Skamil op = PTRACE_POSIX_SPAWN; 34241.126Skamil else if (strcmp(fn, "fork") == 0) 34251.126Skamil op = PTRACE_FORK; 34261.126Skamil else 34271.126Skamil op = PTRACE_VFORK; 34281.126Skamil 34291.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 34301.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 34311.116Skamil 34321.116Skamil DPRINTF("Before resuming the forkee process where it left off " 34331.116Skamil "and without signal to be sent\n"); 34341.116Skamil SYSCALL_REQUIRE( 34351.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 34361.116Skamil 34371.126Skamil if (strcmp(fn, "vforkdone") == 0) { 34381.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 34391.116Skamil child); 34401.116Skamil TWAIT_REQUIRE_SUCCESS( 34411.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 34421.116Skamil 34431.116Skamil validate_status_stopped(status, SIGTRAP); 34441.116Skamil 34451.116Skamil SYSCALL_REQUIRE( 34461.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 34471.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 34481.116Skamil 34491.116Skamil child2 = state.pe_other_pid; 34501.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 34511.116Skamil child2); 34521.116Skamil 34531.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34541.116Skamil DPRINTF("Before resuming the child process where it left off " 34551.116Skamil "and without signal to be sent\n"); 34561.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34571.116Skamil } 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(child2, &status, 0), child2); 34621.116Skamil 34631.116Skamil validate_status_exited(status, exitval2); 34641.116Skamil 34651.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 34661.116Skamil TWAIT_FNAME); 34671.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 34681.116Skamil 34691.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34701.116Skamil TWAIT_FNAME); 34711.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34721.116Skamil 34731.116Skamil if (kill_process) { 34741.116Skamil validate_status_signaled(status, SIGKILL, 0); 34751.116Skamil } else { 34761.116Skamil validate_status_exited(status, exitval); 34771.116Skamil } 34781.116Skamil 34791.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34801.116Skamil TWAIT_FNAME); 34811.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34821.116Skamil} 34831.116Skamil 34841.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 34851.116SkamilATF_TC(name); \ 34861.116SkamilATF_TC_HEAD(name, tc) \ 34871.116Skamil{ \ 34881.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 34891.126Skamil kprocess ? "killed" : "detached"); \ 34901.116Skamil} \ 34911.116Skamil \ 34921.116SkamilATF_TC_BODY(name, tc) \ 34931.116Skamil{ \ 34941.116Skamil \ 34951.126Skamil fork_detach_forker_body(event, kprocess); \ 34961.116Skamil} 34971.116Skamil 34981.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 34991.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 35001.116Skamil#if TEST_VFORK_ENABLED 35011.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 35021.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 35031.116Skamil#endif 35041.126Skamil 35051.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 35061.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 35071.116Skamil#if TEST_VFORK_ENABLED 35081.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 35091.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 35101.116Skamil#endif 35111.116Skamil#endif 35121.116Skamil 35131.116Skamil/// ---------------------------------------------------------------------------- 35141.116Skamil 35151.110Skamil#if TEST_VFORK_ENABLED 35161.108Skamilstatic void 35171.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 35181.108Skamil{ 35191.108Skamil const int exitval = 5; 35201.108Skamil const int exitval2 = 15; 35211.108Skamil pid_t child, child2 = 0, wpid; 35221.108Skamil#if defined(TWAIT_HAVE_STATUS) 35231.108Skamil int status; 35241.108Skamil#endif 35251.108Skamil 35261.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 35271.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 35281.108Skamil if (child == 0) { 35291.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 35301.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 35311.108Skamil 35321.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 35331.108Skamil 35341.108Skamil if (child2 == 0) 35351.108Skamil _exit(exitval2); 35361.108Skamil 35371.108Skamil FORKEE_REQUIRE_SUCCESS 35381.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 35391.108Skamil 35401.108Skamil forkee_status_exited(status, exitval2); 35411.108Skamil 35421.108Skamil DPRINTF("Before exiting of the child process\n"); 35431.108Skamil _exit(exitval); 35441.108Skamil } 35451.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35461.108Skamil 35471.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 35481.108Skamil TWAIT_FNAME); 35491.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35501.108Skamil 35511.108Skamil validate_status_exited(status, exitval); 35521.108Skamil 35531.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 35541.108Skamil TWAIT_FNAME); 35551.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35561.108Skamil} 35571.108Skamil 35581.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 35591.108SkamilATF_TC(name); \ 35601.108SkamilATF_TC_HEAD(name, tc) \ 35611.108Skamil{ \ 35621.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 35631.108Skamil "called from vfork(2)ed child"); \ 35641.108Skamil} \ 35651.108Skamil \ 35661.108SkamilATF_TC_BODY(name, tc) \ 35671.108Skamil{ \ 35681.108Skamil \ 35691.108Skamil traceme_vfork_fork_body(fun); \ 35701.108Skamil} 35711.108Skamil 35721.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 35731.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 35741.110Skamil#endif 35751.108Skamil 35761.108Skamil/// ---------------------------------------------------------------------------- 35771.108Skamil 35781.54Skamilenum bytes_transfer_type { 35791.54Skamil BYTES_TRANSFER_DATA, 35801.54Skamil BYTES_TRANSFER_DATAIO, 35811.54Skamil BYTES_TRANSFER_TEXT, 35821.54Skamil BYTES_TRANSFER_TEXTIO, 35831.54Skamil BYTES_TRANSFER_AUXV 35841.54Skamil}; 35851.31Skamil 35861.54Skamilstatic int __used 35871.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 35881.54Skamil{ 35891.54Skamil int e, f, g, h; 35901.1Skamil 35911.54Skamil a *= 4; 35921.54Skamil b += 3; 35931.54Skamil c -= 2; 35941.54Skamil d /= 1; 35951.1Skamil 35961.54Skamil e = strtol("10", NULL, 10); 35971.54Skamil f = strtol("20", NULL, 10); 35981.54Skamil g = strtol("30", NULL, 10); 35991.54Skamil h = strtol("40", NULL, 10); 36001.1Skamil 36011.54Skamil return (a + b * c - d) + (e * f - g / h); 36021.1Skamil} 36031.1Skamil 36041.54Skamilstatic void 36051.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 36061.1Skamil{ 36071.1Skamil const int exitval = 5; 36081.1Skamil const int sigval = SIGSTOP; 36091.1Skamil pid_t child, wpid; 36101.54Skamil bool skip = false; 36111.1Skamil 36121.54Skamil int lookup_me = 0; 36131.54Skamil uint8_t lookup_me8 = 0; 36141.54Skamil uint16_t lookup_me16 = 0; 36151.54Skamil uint32_t lookup_me32 = 0; 36161.54Skamil uint64_t lookup_me64 = 0; 36171.1Skamil 36181.54Skamil int magic = 0x13579246; 36191.54Skamil uint8_t magic8 = 0xab; 36201.54Skamil uint16_t magic16 = 0x1234; 36211.54Skamil uint32_t magic32 = 0x98765432; 36221.54Skamil uint64_t magic64 = 0xabcdef0123456789; 36231.1Skamil 36241.54Skamil struct ptrace_io_desc io; 36251.1Skamil#if defined(TWAIT_HAVE_STATUS) 36261.1Skamil int status; 36271.1Skamil#endif 36281.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 36291.60Skre AuxInfo ai[513], *aip; 36301.55Schristos 36311.55Schristos ATF_REQUIRE(size < sizeof(ai)); 36321.1Skamil 36331.54Skamil /* Prepare variables for .TEXT transfers */ 36341.54Skamil switch (type) { 36351.54Skamil case BYTES_TRANSFER_TEXT: 36361.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 36371.54Skamil break; 36381.54Skamil case BYTES_TRANSFER_TEXTIO: 36391.54Skamil switch (size) { 36401.54Skamil case 8: 36411.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 36421.54Skamil break; 36431.54Skamil case 16: 36441.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 36451.54Skamil break; 36461.54Skamil case 32: 36471.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 36481.54Skamil break; 36491.54Skamil case 64: 36501.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 36511.54Skamil break; 36521.54Skamil } 36531.54Skamil break; 36541.54Skamil default: 36551.54Skamil break; 36561.54Skamil } 36571.1Skamil 36581.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 36591.54Skamil switch (type) { 36601.54Skamil case BYTES_TRANSFER_TEXTIO: 36611.54Skamil case BYTES_TRANSFER_DATAIO: 36621.54Skamil io.piod_op = operation; 36631.54Skamil switch (size) { 36641.54Skamil case 8: 36651.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36661.54Skamil (void *)bytes_transfer_dummy : 36671.54Skamil &lookup_me8; 36681.54Skamil io.piod_addr = &lookup_me8; 36691.54Skamil io.piod_len = sizeof(lookup_me8); 36701.54Skamil break; 36711.54Skamil case 16: 36721.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36731.54Skamil (void *)bytes_transfer_dummy : 36741.54Skamil &lookup_me16; 36751.54Skamil io.piod_addr = &lookup_me16; 36761.54Skamil io.piod_len = sizeof(lookup_me16); 36771.54Skamil break; 36781.54Skamil case 32: 36791.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36801.54Skamil (void *)bytes_transfer_dummy : 36811.54Skamil &lookup_me32; 36821.54Skamil io.piod_addr = &lookup_me32; 36831.54Skamil io.piod_len = sizeof(lookup_me32); 36841.54Skamil break; 36851.54Skamil case 64: 36861.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36871.54Skamil (void *)bytes_transfer_dummy : 36881.54Skamil &lookup_me64; 36891.54Skamil io.piod_addr = &lookup_me64; 36901.54Skamil io.piod_len = sizeof(lookup_me64); 36911.54Skamil break; 36921.54Skamil default: 36931.54Skamil break; 36941.54Skamil } 36951.54Skamil break; 36961.54Skamil case BYTES_TRANSFER_AUXV: 36971.54Skamil io.piod_op = operation; 36981.54Skamil io.piod_offs = 0; 36991.54Skamil io.piod_addr = ai; 37001.54Skamil io.piod_len = size; 37011.54Skamil break; 37021.54Skamil default: 37031.54Skamil break; 37041.1Skamil } 37051.1Skamil 37061.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 37071.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 37081.1Skamil if (child == 0) { 37091.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 37101.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 37111.1Skamil 37121.54Skamil switch (type) { 37131.54Skamil case BYTES_TRANSFER_DATA: 37141.54Skamil switch (operation) { 37151.54Skamil case PT_READ_D: 37161.54Skamil case PT_READ_I: 37171.54Skamil lookup_me = magic; 37181.54Skamil break; 37191.54Skamil default: 37201.54Skamil break; 37211.54Skamil } 37221.54Skamil break; 37231.54Skamil case BYTES_TRANSFER_DATAIO: 37241.54Skamil switch (operation) { 37251.54Skamil case PIOD_READ_D: 37261.54Skamil case PIOD_READ_I: 37271.54Skamil switch (size) { 37281.54Skamil case 8: 37291.54Skamil lookup_me8 = magic8; 37301.54Skamil break; 37311.54Skamil case 16: 37321.54Skamil lookup_me16 = magic16; 37331.54Skamil break; 37341.54Skamil case 32: 37351.54Skamil lookup_me32 = magic32; 37361.54Skamil break; 37371.54Skamil case 64: 37381.54Skamil lookup_me64 = magic64; 37391.54Skamil break; 37401.54Skamil default: 37411.54Skamil break; 37421.54Skamil } 37431.54Skamil break; 37441.54Skamil default: 37451.54Skamil break; 37461.54Skamil } 37471.54Skamil default: 37481.54Skamil break; 37491.54Skamil } 37501.54Skamil 37511.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37521.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37531.1Skamil 37541.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 37551.54Skamil switch (type) { 37561.54Skamil case BYTES_TRANSFER_DATA: 37571.54Skamil switch (operation) { 37581.54Skamil case PT_WRITE_D: 37591.54Skamil case PT_WRITE_I: 37601.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 37611.54Skamil break; 37621.54Skamil default: 37631.54Skamil break; 37641.54Skamil } 37651.54Skamil break; 37661.54Skamil case BYTES_TRANSFER_DATAIO: 37671.54Skamil switch (operation) { 37681.54Skamil case PIOD_WRITE_D: 37691.54Skamil case PIOD_WRITE_I: 37701.54Skamil switch (size) { 37711.54Skamil case 8: 37721.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 37731.54Skamil break; 37741.54Skamil case 16: 37751.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 37761.54Skamil break; 37771.54Skamil case 32: 37781.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 37791.54Skamil break; 37801.54Skamil case 64: 37811.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 37821.54Skamil break; 37831.54Skamil default: 37841.54Skamil break; 37851.54Skamil } 37861.54Skamil break; 37871.54Skamil default: 37881.54Skamil break; 37891.54Skamil } 37901.54Skamil break; 37911.54Skamil case BYTES_TRANSFER_TEXT: 37921.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 37931.54Skamil sizeof(magic)) == 0); 37941.54Skamil break; 37951.54Skamil case BYTES_TRANSFER_TEXTIO: 37961.54Skamil switch (size) { 37971.54Skamil case 8: 37981.54Skamil FORKEE_ASSERT(memcmp(&magic8, 37991.54Skamil bytes_transfer_dummy, 38001.54Skamil sizeof(magic8)) == 0); 38011.54Skamil break; 38021.54Skamil case 16: 38031.54Skamil FORKEE_ASSERT(memcmp(&magic16, 38041.54Skamil bytes_transfer_dummy, 38051.54Skamil sizeof(magic16)) == 0); 38061.54Skamil break; 38071.54Skamil case 32: 38081.54Skamil FORKEE_ASSERT(memcmp(&magic32, 38091.54Skamil bytes_transfer_dummy, 38101.54Skamil sizeof(magic32)) == 0); 38111.54Skamil break; 38121.54Skamil case 64: 38131.54Skamil FORKEE_ASSERT(memcmp(&magic64, 38141.54Skamil bytes_transfer_dummy, 38151.54Skamil sizeof(magic64)) == 0); 38161.54Skamil break; 38171.54Skamil } 38181.54Skamil break; 38191.54Skamil default: 38201.54Skamil break; 38211.54Skamil } 38221.54Skamil 38231.13Schristos DPRINTF("Before exiting of the child process\n"); 38241.1Skamil _exit(exitval); 38251.1Skamil } 38261.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 38271.1Skamil 38281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38301.1Skamil 38311.1Skamil validate_status_stopped(status, sigval); 38321.1Skamil 38331.54Skamil /* Check PaX MPROTECT */ 38341.54Skamil if (!can_we_write_to_text(child)) { 38351.54Skamil switch (type) { 38361.54Skamil case BYTES_TRANSFER_TEXTIO: 38371.54Skamil switch (operation) { 38381.54Skamil case PIOD_WRITE_D: 38391.54Skamil case PIOD_WRITE_I: 38401.54Skamil skip = true; 38411.54Skamil break; 38421.54Skamil default: 38431.54Skamil break; 38441.54Skamil } 38451.54Skamil break; 38461.54Skamil case BYTES_TRANSFER_TEXT: 38471.54Skamil switch (operation) { 38481.54Skamil case PT_WRITE_D: 38491.54Skamil case PT_WRITE_I: 38501.54Skamil skip = true; 38511.54Skamil break; 38521.54Skamil default: 38531.54Skamil break; 38541.54Skamil } 38551.54Skamil break; 38561.54Skamil default: 38571.54Skamil break; 38581.54Skamil } 38591.54Skamil } 38601.1Skamil 38611.54Skamil /* Bailout cleanly killing the child process */ 38621.54Skamil if (skip) { 38631.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 38641.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38651.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38661.54Skamil child); 38671.1Skamil 38681.54Skamil validate_status_signaled(status, SIGKILL, 0); 38691.1Skamil 38701.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 38711.54Skamil } 38721.1Skamil 38731.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 38741.54Skamil "parent=%d\n", child, getpid()); 38751.1Skamil 38761.54Skamil switch (type) { 38771.54Skamil case BYTES_TRANSFER_TEXTIO: 38781.54Skamil case BYTES_TRANSFER_DATAIO: 38791.54Skamil case BYTES_TRANSFER_AUXV: 38801.54Skamil switch (operation) { 38811.54Skamil case PIOD_WRITE_D: 38821.54Skamil case PIOD_WRITE_I: 38831.54Skamil switch (size) { 38841.54Skamil case 8: 38851.54Skamil lookup_me8 = magic8; 38861.54Skamil break; 38871.54Skamil case 16: 38881.54Skamil lookup_me16 = magic16; 38891.54Skamil break; 38901.54Skamil case 32: 38911.54Skamil lookup_me32 = magic32; 38921.54Skamil break; 38931.54Skamil case 64: 38941.54Skamil lookup_me64 = magic64; 38951.54Skamil break; 38961.54Skamil default: 38971.54Skamil break; 38981.54Skamil } 38991.54Skamil break; 39001.54Skamil default: 39011.54Skamil break; 39021.54Skamil } 39031.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 39041.54Skamil switch (operation) { 39051.54Skamil case PIOD_READ_D: 39061.54Skamil case PIOD_READ_I: 39071.54Skamil switch (size) { 39081.54Skamil case 8: 39091.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 39101.54Skamil break; 39111.54Skamil case 16: 39121.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 39131.54Skamil break; 39141.54Skamil case 32: 39151.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 39161.54Skamil break; 39171.54Skamil case 64: 39181.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 39191.54Skamil break; 39201.54Skamil default: 39211.54Skamil break; 39221.54Skamil } 39231.54Skamil break; 39241.54Skamil case PIOD_READ_AUXV: 39251.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 39261.54Skamil io.piod_len); 39271.54Skamil ATF_REQUIRE(io.piod_len > 0); 39281.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 39291.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 39301.54Skamil (long long int)aip->a_type, 39311.54Skamil (long long int)aip->a_v); 39321.54Skamil break; 39331.54Skamil default: 39341.54Skamil break; 39351.54Skamil } 39361.54Skamil break; 39371.54Skamil case BYTES_TRANSFER_TEXT: 39381.54Skamil switch (operation) { 39391.54Skamil case PT_READ_D: 39401.54Skamil case PT_READ_I: 39411.54Skamil errno = 0; 39421.54Skamil lookup_me = ptrace(operation, child, 39431.54Skamil bytes_transfer_dummy, 0); 39441.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39451.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39461.54Skamil break; 39471.54Skamil case PT_WRITE_D: 39481.54Skamil case PT_WRITE_I: 39491.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 39501.54Skamil bytes_transfer_dummy, magic) 39511.54Skamil != -1); 39521.54Skamil break; 39531.54Skamil default: 39541.54Skamil break; 39551.54Skamil } 39561.54Skamil break; 39571.54Skamil case BYTES_TRANSFER_DATA: 39581.54Skamil switch (operation) { 39591.54Skamil case PT_READ_D: 39601.54Skamil case PT_READ_I: 39611.54Skamil errno = 0; 39621.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 39631.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39641.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39651.54Skamil break; 39661.54Skamil case PT_WRITE_D: 39671.54Skamil case PT_WRITE_I: 39681.54Skamil lookup_me = magic; 39691.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 39701.54Skamil magic) != -1); 39711.54Skamil break; 39721.54Skamil default: 39731.54Skamil break; 39741.54Skamil } 39751.54Skamil break; 39761.54Skamil default: 39771.54Skamil break; 39781.54Skamil } 39791.1Skamil 39801.13Schristos DPRINTF("Before resuming the child process where it left off and " 39811.1Skamil "without signal to be sent\n"); 39821.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39831.1Skamil 39841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39861.1Skamil 39871.1Skamil validate_status_exited(status, exitval); 39881.1Skamil 39891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39901.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39911.1Skamil} 39921.1Skamil 39931.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 39941.61SkreATF_TC(test); \ 39951.61SkreATF_TC_HEAD(test, tc) \ 39961.61Skre{ \ 39971.61Skre atf_tc_set_md_var(tc, "descr", \ 39981.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 39991.61Skre " of type " #type); \ 40001.61Skre} \ 40011.61Skre \ 40021.61SkreATF_TC_BODY(test, tc) \ 40031.61Skre{ \ 40041.61Skre \ 40051.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 40061.1Skamil} 40071.1Skamil 40081.54Skamil// DATA 40091.1Skamil 40101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 40131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 40141.54Skamil 40151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 40161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 40171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 40181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 40191.54Skamil 40201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 40211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 40221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 40231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 40241.54Skamil 40251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 40261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 40271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 40281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 40291.54Skamil 40301.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 40311.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 40321.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 40331.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 40341.54Skamil 40351.54Skamil// TEXT 40361.54Skamil 40371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 40381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 40391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 40401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 40411.54Skamil 40421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 40431.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 40441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 40451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 40461.54Skamil 40471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 40481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 40491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 40501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 40511.54Skamil 40521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 40531.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 40541.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 40551.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 40561.54Skamil 40571.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 40581.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 40591.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 40601.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 40611.1Skamil 40621.54Skamil// AUXV 40631.1Skamil 40641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 40651.1Skamil 40661.54Skamil/// ---------------------------------------------------------------------------- 40671.1Skamil 40681.101Skamilstatic void 40691.101Skamilbytes_transfer_alignment(const char *operation) 40701.101Skamil{ 40711.101Skamil const int exitval = 5; 40721.101Skamil const int sigval = SIGSTOP; 40731.101Skamil pid_t child, wpid; 40741.101Skamil#if defined(TWAIT_HAVE_STATUS) 40751.101Skamil int status; 40761.101Skamil#endif 40771.101Skamil char *buffer; 40781.101Skamil int vector; 40791.101Skamil size_t len; 40801.101Skamil size_t i; 40811.101Skamil int op; 40821.101Skamil 40831.101Skamil struct ptrace_io_desc io; 40841.101Skamil struct ptrace_siginfo info; 40851.101Skamil 40861.101Skamil memset(&io, 0, sizeof(io)); 40871.101Skamil memset(&info, 0, sizeof(info)); 40881.101Skamil 40891.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 40901.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 40911.101Skamil buffer = malloc(len); 40921.101Skamil ATF_REQUIRE(buffer != NULL); 40931.101Skamil 40941.101Skamil /* Initialize the buffer with random data */ 40951.101Skamil for (i = 0; i < len; i++) 40961.101Skamil buffer[i] = i & 0xff; 40971.101Skamil 40981.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 40991.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 41001.101Skamil if (child == 0) { 41011.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41021.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41031.101Skamil 41041.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 41051.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 41061.101Skamil 41071.101Skamil DPRINTF("Before exiting of the child process\n"); 41081.101Skamil _exit(exitval); 41091.101Skamil } 41101.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41111.101Skamil 41121.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41131.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41141.101Skamil 41151.101Skamil validate_status_stopped(status, sigval); 41161.101Skamil 41171.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 41181.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 41191.101Skamil != -1); 41201.101Skamil 41211.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 41221.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 41231.101Skamil "si_errno=%#x\n", 41241.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 41251.101Skamil info.psi_siginfo.si_errno); 41261.101Skamil 41271.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 41281.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 41291.101Skamil 41301.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 41311.101Skamil strcmp(operation, "PT_READ_D") == 0) { 41321.101Skamil if (strcmp(operation, "PT_READ_I")) 41331.101Skamil op = PT_READ_I; 41341.101Skamil else 41351.101Skamil op = PT_READ_D; 41361.101Skamil 41371.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41381.101Skamil errno = 0; 41391.101Skamil vector = ptrace(op, child, buffer + i, 0); 41401.101Skamil ATF_REQUIRE_EQ(errno, 0); 41411.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41421.101Skamil } 41431.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41441.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41451.101Skamil if (strcmp(operation, "PT_WRITE_I")) 41461.101Skamil op = PT_WRITE_I; 41471.101Skamil else 41481.101Skamil op = PT_WRITE_D; 41491.101Skamil 41501.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41511.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 41521.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 41531.101Skamil != -1); 41541.101Skamil } 41551.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41561.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41571.101Skamil if (strcmp(operation, "PIOD_READ_I")) 41581.101Skamil op = PIOD_READ_I; 41591.101Skamil else 41601.101Skamil op = PIOD_READ_D; 41611.101Skamil 41621.101Skamil io.piod_op = op; 41631.101Skamil io.piod_addr = &vector; 41641.101Skamil io.piod_len = sizeof(int); 41651.101Skamil 41661.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41671.101Skamil io.piod_offs = buffer + i; 41681.101Skamil 41691.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41701.101Skamil != -1); 41711.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41721.101Skamil } 41731.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 41741.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 41751.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 41761.101Skamil op = PIOD_WRITE_I; 41771.101Skamil else 41781.101Skamil op = PIOD_WRITE_D; 41791.101Skamil 41801.101Skamil io.piod_op = op; 41811.101Skamil io.piod_addr = &vector; 41821.101Skamil io.piod_len = sizeof(int); 41831.101Skamil 41841.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41851.101Skamil io.piod_offs = buffer + i; 41861.101Skamil 41871.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41881.101Skamil != -1); 41891.101Skamil } 41901.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 41911.101Skamil io.piod_op = PIOD_READ_AUXV; 41921.101Skamil io.piod_addr = &vector; 41931.101Skamil io.piod_len = sizeof(int); 41941.101Skamil 41951.101Skamil errno = 0; 41961.101Skamil i = 0; 41971.101Skamil /* Read the whole AUXV vector, it has no clear length */ 41981.120Skamil while (io.piod_len > 0) { 41991.101Skamil io.piod_offs = (void *)(intptr_t)i; 42001.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 42011.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 42021.101Skamil ++i; 42031.101Skamil } 42041.101Skamil } 42051.101Skamil 42061.101Skamil DPRINTF("Before resuming the child process where it left off " 42071.101Skamil "and without signal to be sent\n"); 42081.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 42091.101Skamil 42101.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42111.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 42121.101Skamil child); 42131.101Skamil 42141.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42151.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 42161.101Skamil} 42171.101Skamil 42181.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 42191.101SkamilATF_TC(test); \ 42201.101SkamilATF_TC_HEAD(test, tc) \ 42211.101Skamil{ \ 42221.101Skamil atf_tc_set_md_var(tc, "descr", \ 42231.101Skamil "Verify bytes transfer for potentially misaligned " \ 42241.101Skamil "operation " operation); \ 42251.101Skamil} \ 42261.101Skamil \ 42271.101SkamilATF_TC_BODY(test, tc) \ 42281.101Skamil{ \ 42291.101Skamil \ 42301.101Skamil bytes_transfer_alignment(operation); \ 42311.101Skamil} 42321.101Skamil 42331.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 42341.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 42351.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 42361.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 42371.101Skamil 42381.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 42391.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 42401.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 42411.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 42421.101Skamil 42431.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 42441.101Skamil 42451.101Skamil/// ---------------------------------------------------------------------------- 42461.101Skamil 42471.115Skamilstatic void 42481.115Skamilbytes_transfer_eof(const char *operation) 42491.115Skamil{ 42501.115Skamil const int exitval = 5; 42511.115Skamil const int sigval = SIGSTOP; 42521.115Skamil pid_t child, wpid; 42531.115Skamil#if defined(TWAIT_HAVE_STATUS) 42541.115Skamil int status; 42551.115Skamil#endif 42561.115Skamil FILE *fp; 42571.115Skamil char *p; 42581.115Skamil int vector; 42591.115Skamil int op; 42601.115Skamil 42611.115Skamil struct ptrace_io_desc io; 42621.115Skamil struct ptrace_siginfo info; 42631.115Skamil 42641.115Skamil memset(&io, 0, sizeof(io)); 42651.115Skamil memset(&info, 0, sizeof(info)); 42661.115Skamil 42671.115Skamil vector = 0; 42681.115Skamil 42691.115Skamil fp = tmpfile(); 42701.115Skamil ATF_REQUIRE(fp != NULL); 42711.115Skamil 42721.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 42731.115Skamil ATF_REQUIRE(p != MAP_FAILED); 42741.115Skamil 42751.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42761.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42771.115Skamil if (child == 0) { 42781.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42791.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42801.115Skamil 42811.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42821.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 42831.115Skamil 42841.115Skamil DPRINTF("Before exiting of the child process\n"); 42851.115Skamil _exit(exitval); 42861.115Skamil } 42871.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42881.115Skamil 42891.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42901.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42911.115Skamil 42921.115Skamil validate_status_stopped(status, sigval); 42931.115Skamil 42941.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42951.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 42961.115Skamil != -1); 42971.115Skamil 42981.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42991.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 43001.115Skamil "si_errno=%#x\n", 43011.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 43021.115Skamil info.psi_siginfo.si_errno); 43031.115Skamil 43041.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 43051.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 43061.115Skamil 43071.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 43081.115Skamil strcmp(operation, "PT_READ_D") == 0) { 43091.115Skamil if (strcmp(operation, "PT_READ_I")) 43101.115Skamil op = PT_READ_I; 43111.115Skamil else 43121.115Skamil op = PT_READ_D; 43131.115Skamil 43141.115Skamil errno = 0; 43151.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 43161.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43171.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 43181.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 43191.115Skamil if (strcmp(operation, "PT_WRITE_I")) 43201.115Skamil op = PT_WRITE_I; 43211.115Skamil else 43221.115Skamil op = PT_WRITE_D; 43231.115Skamil 43241.115Skamil errno = 0; 43251.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 43261.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43271.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 43281.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 43291.115Skamil if (strcmp(operation, "PIOD_READ_I")) 43301.115Skamil op = PIOD_READ_I; 43311.115Skamil else 43321.115Skamil op = PIOD_READ_D; 43331.115Skamil 43341.115Skamil io.piod_op = op; 43351.115Skamil io.piod_addr = &vector; 43361.115Skamil io.piod_len = sizeof(int); 43371.115Skamil io.piod_offs = p; 43381.115Skamil 43391.115Skamil errno = 0; 43401.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43411.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43421.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 43431.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 43441.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 43451.115Skamil op = PIOD_WRITE_I; 43461.115Skamil else 43471.115Skamil op = PIOD_WRITE_D; 43481.115Skamil 43491.115Skamil io.piod_op = op; 43501.115Skamil io.piod_addr = &vector; 43511.115Skamil io.piod_len = sizeof(int); 43521.115Skamil io.piod_offs = p; 43531.115Skamil 43541.115Skamil errno = 0; 43551.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43561.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43571.115Skamil } 43581.115Skamil 43591.115Skamil DPRINTF("Before resuming the child process where it left off " 43601.115Skamil "and without signal to be sent\n"); 43611.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43621.115Skamil 43631.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43641.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43651.115Skamil child); 43661.115Skamil 43671.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43681.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43691.115Skamil} 43701.115Skamil 43711.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 43721.115SkamilATF_TC(test); \ 43731.115SkamilATF_TC_HEAD(test, tc) \ 43741.115Skamil{ \ 43751.115Skamil atf_tc_set_md_var(tc, "descr", \ 43761.115Skamil "Verify bytes EOF byte transfer for the " operation \ 43771.115Skamil " operation"); \ 43781.115Skamil} \ 43791.115Skamil \ 43801.115SkamilATF_TC_BODY(test, tc) \ 43811.115Skamil{ \ 43821.115Skamil \ 43831.115Skamil bytes_transfer_eof(operation); \ 43841.115Skamil} 43851.115Skamil 43861.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 43871.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 43881.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 43891.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 43901.115Skamil 43911.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 43921.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 43931.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 43941.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 43951.115Skamil 43961.115Skamil/// ---------------------------------------------------------------------------- 43971.115Skamil 43981.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 43991.72Skamilstatic void 44001.72Skamilaccess_regs(const char *regset, const char *aux) 44011.1Skamil{ 44021.1Skamil const int exitval = 5; 44031.1Skamil const int sigval = SIGSTOP; 44041.1Skamil pid_t child, wpid; 44051.1Skamil#if defined(TWAIT_HAVE_STATUS) 44061.1Skamil int status; 44071.1Skamil#endif 44081.72Skamil#if defined(HAVE_GPREGS) 44091.72Skamil struct reg gpr; 44101.76Sscole register_t rgstr; 44111.1Skamil#endif 44121.72Skamil#if defined(HAVE_FPREGS) 44131.72Skamil struct fpreg fpr; 44141.1Skamil#endif 44151.76Sscole 44161.72Skamil#if !defined(HAVE_GPREGS) 44171.72Skamil if (strcmp(regset, "regs") == 0) 44181.72Skamil atf_tc_fail("Impossible test scenario!"); 44191.1Skamil#endif 44201.1Skamil 44211.72Skamil#if !defined(HAVE_FPREGS) 44221.72Skamil if (strcmp(regset, "fpregs") == 0) 44231.72Skamil atf_tc_fail("Impossible test scenario!"); 44241.1Skamil#endif 44251.1Skamil 44261.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44271.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44281.1Skamil if (child == 0) { 44291.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44301.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44311.1Skamil 44321.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44331.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44341.1Skamil 44351.13Schristos DPRINTF("Before exiting of the child process\n"); 44361.1Skamil _exit(exitval); 44371.1Skamil } 44381.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44391.1Skamil 44401.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44411.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44421.1Skamil 44431.1Skamil validate_status_stopped(status, sigval); 44441.1Skamil 44451.1Skamil#if defined(HAVE_GPREGS) 44461.72Skamil if (strcmp(regset, "regs") == 0) { 44471.72Skamil DPRINTF("Call GETREGS for the child process\n"); 44481.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44491.72Skamil 44501.72Skamil if (strcmp(aux, "none") == 0) { 44511.72Skamil DPRINTF("Retrieved registers\n"); 44521.72Skamil } else if (strcmp(aux, "pc") == 0) { 44531.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44541.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44551.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 44561.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44571.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 44581.72Skamil } else if (strcmp(aux, "sp") == 0) { 44591.72Skamil rgstr = PTRACE_REG_SP(&gpr); 44601.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44611.72Skamil } else if (strcmp(aux, "intrv") == 0) { 44621.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 44631.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44641.72Skamil } else if (strcmp(aux, "setregs") == 0) { 44651.72Skamil DPRINTF("Call SETREGS for the child process\n"); 44661.72Skamil SYSCALL_REQUIRE( 44671.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44681.72Skamil } 44691.72Skamil } 44701.1Skamil#endif 44711.1Skamil 44721.72Skamil#if defined(HAVE_FPREGS) 44731.72Skamil if (strcmp(regset, "fpregs") == 0) { 44741.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 44751.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 44761.72Skamil 44771.72Skamil if (strcmp(aux, "getfpregs") == 0) { 44781.72Skamil DPRINTF("Retrieved FP registers\n"); 44791.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 44801.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 44811.72Skamil SYSCALL_REQUIRE( 44821.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 44831.72Skamil } 44841.1Skamil } 44851.1Skamil#endif 44861.1Skamil 44871.13Schristos DPRINTF("Before resuming the child process where it left off and " 44881.1Skamil "without signal to be sent\n"); 44891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44901.1Skamil 44911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44931.1Skamil 44941.1Skamil validate_status_exited(status, exitval); 44951.1Skamil 44961.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44971.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44981.1Skamil} 44991.1Skamil 45001.72Skamil#define ACCESS_REGS(test, regset, aux) \ 45011.72SkamilATF_TC(test); \ 45021.72SkamilATF_TC_HEAD(test, tc) \ 45031.72Skamil{ \ 45041.72Skamil atf_tc_set_md_var(tc, "descr", \ 45051.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 45061.72Skamil} \ 45071.72Skamil \ 45081.72SkamilATF_TC_BODY(test, tc) \ 45091.72Skamil{ \ 45101.72Skamil \ 45111.72Skamil access_regs(regset, aux); \ 45121.1Skamil} 45131.1Skamil#endif 45141.1Skamil 45151.72Skamil#if defined(HAVE_GPREGS) 45161.72SkamilACCESS_REGS(access_regs1, "regs", "none") 45171.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 45181.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 45191.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 45201.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 45211.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 45221.1Skamil#endif 45231.1Skamil#if defined(HAVE_FPREGS) 45241.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 45251.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 45261.1Skamil#endif 45271.1Skamil 45281.72Skamil/// ---------------------------------------------------------------------------- 45291.1Skamil 45301.1Skamil#if defined(PT_STEP) 45311.1Skamilstatic void 45321.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 45331.1Skamil{ 45341.1Skamil const int exitval = 5; 45351.1Skamil const int sigval = SIGSTOP; 45361.1Skamil pid_t child, wpid; 45371.1Skamil#if defined(TWAIT_HAVE_STATUS) 45381.1Skamil int status; 45391.1Skamil#endif 45401.1Skamil int happy; 45411.95Skamil struct sigaction sa; 45421.81Skamil struct ptrace_siginfo info; 45431.95Skamil sigset_t intmask; 45441.95Skamil struct kinfo_proc2 kp; 45451.95Skamil size_t len = sizeof(kp); 45461.95Skamil 45471.95Skamil int name[6]; 45481.95Skamil const size_t namelen = __arraycount(name); 45491.95Skamil ki_sigset_t kp_sigmask; 45501.95Skamil ki_sigset_t kp_sigignore; 45511.1Skamil 45521.1Skamil#if defined(__arm__) 45531.1Skamil /* PT_STEP not supported on arm 32-bit */ 45541.1Skamil atf_tc_expect_fail("PR kern/52119"); 45551.1Skamil#endif 45561.1Skamil 45571.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45581.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45591.1Skamil if (child == 0) { 45601.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45611.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45621.1Skamil 45631.95Skamil if (masked) { 45641.95Skamil sigemptyset(&intmask); 45651.95Skamil sigaddset(&intmask, SIGTRAP); 45661.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 45671.95Skamil } 45681.95Skamil 45691.95Skamil if (ignored) { 45701.95Skamil memset(&sa, 0, sizeof(sa)); 45711.95Skamil sa.sa_handler = SIG_IGN; 45721.95Skamil sigemptyset(&sa.sa_mask); 45731.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 45741.95Skamil } 45751.95Skamil 45761.1Skamil happy = check_happy(999); 45771.1Skamil 45781.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 45791.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 45801.1Skamil 45811.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 45821.1Skamil 45831.13Schristos DPRINTF("Before exiting of the child process\n"); 45841.1Skamil _exit(exitval); 45851.1Skamil } 45861.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45871.1Skamil 45881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45901.1Skamil 45911.1Skamil validate_status_stopped(status, sigval); 45921.1Skamil 45931.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45941.81Skamil SYSCALL_REQUIRE( 45951.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45961.81Skamil 45971.81Skamil DPRINTF("Before checking siginfo_t\n"); 45981.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45991.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 46001.81Skamil 46011.95Skamil name[0] = CTL_KERN, 46021.95Skamil name[1] = KERN_PROC2, 46031.95Skamil name[2] = KERN_PROC_PID; 46041.95Skamil name[3] = child; 46051.95Skamil name[4] = sizeof(kp); 46061.95Skamil name[5] = 1; 46071.95Skamil 46081.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46091.95Skamil 46101.95Skamil if (masked) 46111.95Skamil kp_sigmask = kp.p_sigmask; 46121.95Skamil 46131.95Skamil if (ignored) 46141.95Skamil kp_sigignore = kp.p_sigignore; 46151.95Skamil 46161.1Skamil while (N --> 0) { 46171.2Skamil if (setstep) { 46181.13Schristos DPRINTF("Before resuming the child process where it " 46191.2Skamil "left off and without signal to be sent (use " 46201.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 46211.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 46221.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 46231.2Skamil != -1); 46241.2Skamil } else { 46251.13Schristos DPRINTF("Before resuming the child process where it " 46261.2Skamil "left off and without signal to be sent (use " 46271.2Skamil "PT_STEP)\n"); 46281.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 46291.2Skamil != -1); 46301.2Skamil } 46311.1Skamil 46321.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46331.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 46341.1Skamil child); 46351.1Skamil 46361.1Skamil validate_status_stopped(status, SIGTRAP); 46371.2Skamil 46381.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46391.81Skamil SYSCALL_REQUIRE( 46401.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46411.81Skamil 46421.81Skamil DPRINTF("Before checking siginfo_t\n"); 46431.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46441.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 46451.81Skamil 46461.2Skamil if (setstep) { 46471.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 46481.2Skamil } 46491.95Skamil 46501.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46511.95Skamil 46521.95Skamil if (masked) { 46531.95Skamil DPRINTF("kp_sigmask=" 46541.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46551.95Skamil PRIx32 "\n", 46561.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 46571.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 46581.95Skamil 46591.95Skamil DPRINTF("kp.p_sigmask=" 46601.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46611.95Skamil PRIx32 "\n", 46621.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 46631.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 46641.95Skamil 46651.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 46661.95Skamil sizeof(kp_sigmask))); 46671.95Skamil } 46681.95Skamil 46691.95Skamil if (ignored) { 46701.95Skamil DPRINTF("kp_sigignore=" 46711.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46721.95Skamil PRIx32 "\n", 46731.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 46741.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 46751.95Skamil 46761.95Skamil DPRINTF("kp.p_sigignore=" 46771.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46781.95Skamil PRIx32 "\n", 46791.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 46801.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 46811.95Skamil 46821.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 46831.95Skamil sizeof(kp_sigignore))); 46841.95Skamil } 46851.1Skamil } 46861.1Skamil 46871.13Schristos DPRINTF("Before resuming the child process where it left off and " 46881.1Skamil "without signal to be sent\n"); 46891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46901.1Skamil 46911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46931.1Skamil 46941.1Skamil validate_status_exited(status, exitval); 46951.1Skamil 46961.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46971.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46981.1Skamil} 46991.1Skamil 47001.73Skamil#define PTRACE_STEP(test, N, setstep) \ 47011.73SkamilATF_TC(test); \ 47021.73SkamilATF_TC_HEAD(test, tc) \ 47031.73Skamil{ \ 47041.73Skamil atf_tc_set_md_var(tc, "descr", \ 47051.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 47061.73Skamil} \ 47071.73Skamil \ 47081.73SkamilATF_TC_BODY(test, tc) \ 47091.73Skamil{ \ 47101.73Skamil \ 47111.95Skamil ptrace_step(N, setstep, false, false); \ 47121.1Skamil} 47131.1Skamil 47141.73SkamilPTRACE_STEP(step1, 1, 0) 47151.73SkamilPTRACE_STEP(step2, 2, 0) 47161.73SkamilPTRACE_STEP(step3, 3, 0) 47171.73SkamilPTRACE_STEP(step4, 4, 0) 47181.73SkamilPTRACE_STEP(setstep1, 1, 1) 47191.73SkamilPTRACE_STEP(setstep2, 2, 1) 47201.73SkamilPTRACE_STEP(setstep3, 3, 1) 47211.73SkamilPTRACE_STEP(setstep4, 4, 1) 47221.95Skamil 47231.95SkamilATF_TC(step_signalmasked); 47241.95SkamilATF_TC_HEAD(step_signalmasked, tc) 47251.95Skamil{ 47261.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 47271.95Skamil} 47281.95Skamil 47291.95SkamilATF_TC_BODY(step_signalmasked, tc) 47301.95Skamil{ 47311.95Skamil 47321.95Skamil ptrace_step(1, 0, true, false); 47331.95Skamil} 47341.95Skamil 47351.95SkamilATF_TC(step_signalignored); 47361.95SkamilATF_TC_HEAD(step_signalignored, tc) 47371.95Skamil{ 47381.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 47391.95Skamil} 47401.95Skamil 47411.95SkamilATF_TC_BODY(step_signalignored, tc) 47421.95Skamil{ 47431.95Skamil 47441.95Skamil ptrace_step(1, 0, false, true); 47451.95Skamil} 47461.1Skamil#endif 47471.1Skamil 47481.73Skamil/// ---------------------------------------------------------------------------- 47491.1Skamil 47501.75Skamilstatic void 47511.75Skamilptrace_kill(const char *type) 47521.1Skamil{ 47531.75Skamil const int sigval = SIGSTOP; 47541.1Skamil pid_t child, wpid; 47551.1Skamil#if defined(TWAIT_HAVE_STATUS) 47561.1Skamil int status; 47571.1Skamil#endif 47581.1Skamil 47591.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47601.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47611.1Skamil if (child == 0) { 47621.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47631.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47641.1Skamil 47651.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47661.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47671.1Skamil 47681.1Skamil /* NOTREACHED */ 47691.1Skamil FORKEE_ASSERTX(0 && 47701.1Skamil "Child should be terminated by a signal from its parent"); 47711.1Skamil } 47721.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47731.1Skamil 47741.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47751.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47761.1Skamil 47771.1Skamil validate_status_stopped(status, sigval); 47781.1Skamil 47791.75Skamil DPRINTF("Before killing the child process with %s\n", type); 47801.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 47811.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 47821.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 47831.75Skamil kill(child, SIGKILL); 47841.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 47851.75Skamil setpgid(child, 0); 47861.75Skamil killpg(getpgid(child), SIGKILL); 47871.75Skamil } 47881.1Skamil 47891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47911.1Skamil 47921.75Skamil validate_status_signaled(status, SIGKILL, 0); 47931.1Skamil 47941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47951.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47961.1Skamil} 47971.1Skamil 47981.75Skamil#define PTRACE_KILL(test, type) \ 47991.75SkamilATF_TC(test); \ 48001.75SkamilATF_TC_HEAD(test, tc) \ 48011.75Skamil{ \ 48021.75Skamil atf_tc_set_md_var(tc, "descr", \ 48031.75Skamil "Verify killing the child with " type); \ 48041.75Skamil} \ 48051.75Skamil \ 48061.75SkamilATF_TC_BODY(test, tc) \ 48071.75Skamil{ \ 48081.75Skamil \ 48091.75Skamil ptrace_kill(type); \ 48101.1Skamil} 48111.1Skamil 48121.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 48131.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 48141.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 48151.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 48161.1Skamil 48171.75Skamil/// ---------------------------------------------------------------------------- 48181.1Skamil 48191.77Skamilstatic void 48201.77Skamiltraceme_lwpinfo(const int threads) 48211.1Skamil{ 48221.1Skamil const int sigval = SIGSTOP; 48231.77Skamil const int sigval2 = SIGINT; 48241.1Skamil pid_t child, wpid; 48251.1Skamil#if defined(TWAIT_HAVE_STATUS) 48261.1Skamil int status; 48271.1Skamil#endif 48281.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 48291.77Skamil struct ptrace_siginfo info; 48301.77Skamil 48311.77Skamil /* Maximum number of supported threads in this test */ 48321.77Skamil pthread_t t[3]; 48331.77Skamil int n, rv; 48341.77Skamil 48351.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 48361.1Skamil 48371.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48381.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48391.1Skamil if (child == 0) { 48401.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48411.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48421.1Skamil 48431.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48441.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48451.1Skamil 48461.77Skamil for (n = 0; n < threads; n++) { 48471.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48481.77Skamil FORKEE_ASSERT(rv == 0); 48491.77Skamil } 48501.77Skamil 48511.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 48521.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 48531.77Skamil 48541.77Skamil /* NOTREACHED */ 48551.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48561.1Skamil } 48571.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48581.1Skamil 48591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48611.1Skamil 48621.1Skamil validate_status_stopped(status, sigval); 48631.1Skamil 48641.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48651.77Skamil SYSCALL_REQUIRE( 48661.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48671.77Skamil 48681.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48691.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48701.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48711.77Skamil info.psi_siginfo.si_errno); 48721.77Skamil 48731.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 48741.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48751.77Skamil 48761.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48771.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48781.1Skamil 48791.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48801.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48811.1Skamil 48821.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 48831.77Skamil lwp.pl_lwpid); 48841.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 48851.1Skamil 48861.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48871.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48881.1Skamil 48891.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48901.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48911.1Skamil 48921.13Schristos DPRINTF("Before resuming the child process where it left off and " 48931.1Skamil "without signal to be sent\n"); 48941.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48951.1Skamil 48961.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48981.1Skamil 48991.77Skamil validate_status_stopped(status, sigval2); 49001.77Skamil 49011.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 49021.77Skamil SYSCALL_REQUIRE( 49031.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 49041.77Skamil 49051.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49061.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 49071.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49081.77Skamil info.psi_siginfo.si_errno); 49091.77Skamil 49101.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 49111.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 49121.77Skamil 49131.77Skamil memset(&lwp, 0, sizeof(lwp)); 49141.77Skamil 49151.77Skamil for (n = 0; n <= threads; n++) { 49161.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49171.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 49181.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49191.77Skamil 49201.77Skamil DPRINTF("Assert that the thread exists\n"); 49211.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 49221.77Skamil 49231.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 49241.77Skamil lwp.pl_lwpid); 49251.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 49261.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 49271.77Skamil } 49281.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49291.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 49301.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49311.77Skamil 49321.77Skamil DPRINTF("Assert that there are no more threads\n"); 49331.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 49341.77Skamil 49351.77Skamil DPRINTF("Before resuming the child process where it left off and " 49361.77Skamil "without signal to be sent\n"); 49371.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 49381.77Skamil 49391.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49401.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49411.77Skamil 49421.77Skamil validate_status_signaled(status, SIGKILL, 0); 49431.1Skamil 49441.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49451.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49461.1Skamil} 49471.1Skamil 49481.77Skamil#define TRACEME_LWPINFO(test, threads) \ 49491.77SkamilATF_TC(test); \ 49501.77SkamilATF_TC_HEAD(test, tc) \ 49511.77Skamil{ \ 49521.77Skamil atf_tc_set_md_var(tc, "descr", \ 49531.77Skamil "Verify LWPINFO with the child with " #threads \ 49541.77Skamil " spawned extra threads"); \ 49551.77Skamil} \ 49561.77Skamil \ 49571.77SkamilATF_TC_BODY(test, tc) \ 49581.77Skamil{ \ 49591.77Skamil \ 49601.77Skamil traceme_lwpinfo(threads); \ 49611.1Skamil} 49621.1Skamil 49631.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 49641.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 49651.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 49661.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 49671.77Skamil 49681.77Skamil/// ---------------------------------------------------------------------------- 49691.77Skamil 49701.77Skamil#if defined(TWAIT_HAVE_PID) 49711.77Skamilstatic void 49721.77Skamilattach_lwpinfo(const int threads) 49731.1Skamil{ 49741.77Skamil const int sigval = SIGINT; 49751.1Skamil struct msg_fds parent_tracee, parent_tracer; 49761.1Skamil const int exitval_tracer = 10; 49771.1Skamil pid_t tracee, tracer, wpid; 49781.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 49791.1Skamil#if defined(TWAIT_HAVE_STATUS) 49801.1Skamil int status; 49811.1Skamil#endif 49821.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 49831.77Skamil struct ptrace_siginfo info; 49841.77Skamil 49851.77Skamil /* Maximum number of supported threads in this test */ 49861.77Skamil pthread_t t[3]; 49871.77Skamil int n, rv; 49881.1Skamil 49891.13Schristos DPRINTF("Spawn tracee\n"); 49901.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 49911.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 49921.1Skamil tracee = atf_utils_fork(); 49931.1Skamil if (tracee == 0) { 49941.1Skamil /* Wait for message from the parent */ 49951.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 49961.1Skamil 49971.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 49981.77Skamil 49991.77Skamil for (n = 0; n < threads; n++) { 50001.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 50011.77Skamil FORKEE_ASSERT(rv == 0); 50021.77Skamil } 50031.77Skamil 50041.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 50051.77Skamil 50061.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 50071.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 50081.77Skamil 50091.77Skamil /* NOTREACHED */ 50101.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 50111.1Skamil } 50121.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 50131.1Skamil 50141.13Schristos DPRINTF("Spawn debugger\n"); 50151.1Skamil tracer = atf_utils_fork(); 50161.1Skamil if (tracer == 0) { 50171.1Skamil /* No IPC to communicate with the child */ 50181.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 50191.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 50201.1Skamil 50211.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 50221.1Skamil FORKEE_REQUIRE_SUCCESS( 50231.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50241.1Skamil 50251.1Skamil forkee_status_stopped(status, SIGSTOP); 50261.1Skamil 50271.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50281.77Skamil "tracee"); 50291.77Skamil FORKEE_ASSERT( 50301.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50311.77Skamil 50321.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50331.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50341.77Skamil "si_errno=%#x\n", 50351.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50361.77Skamil info.psi_siginfo.si_errno); 50371.77Skamil 50381.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 50391.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 50401.77Skamil 50411.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 50421.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50431.1Skamil != -1); 50441.1Skamil 50451.13Schristos DPRINTF("Assert that there exists a thread\n"); 50461.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 50471.1Skamil 50481.13Schristos DPRINTF("Assert that lwp thread %d received event " 50491.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 50501.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 50511.1Skamil 50521.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50531.77Skamil "tracee\n"); 50541.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50551.1Skamil != -1); 50561.1Skamil 50571.77Skamil DPRINTF("Assert that there are no more lwp threads in " 50581.77Skamil "tracee\n"); 50591.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50601.1Skamil 50611.1Skamil /* Resume tracee with PT_CONTINUE */ 50621.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 50631.1Skamil 50641.1Skamil /* Inform parent that tracer has attached to tracee */ 50651.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 50661.77Skamil 50671.1Skamil /* Wait for parent */ 50681.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 50691.1Skamil 50701.77Skamil /* Wait for tracee and assert that it raised a signal */ 50711.77Skamil FORKEE_REQUIRE_SUCCESS( 50721.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50731.77Skamil 50741.77Skamil forkee_status_stopped(status, SIGINT); 50751.77Skamil 50761.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50771.77Skamil "child"); 50781.77Skamil FORKEE_ASSERT( 50791.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50801.77Skamil 50811.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50821.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50831.77Skamil "si_errno=%#x\n", 50841.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50851.77Skamil info.psi_siginfo.si_errno); 50861.77Skamil 50871.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 50881.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 50891.77Skamil 50901.77Skamil memset(&lwp, 0, sizeof(lwp)); 50911.77Skamil 50921.77Skamil for (n = 0; n <= threads; n++) { 50931.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50941.77Skamil "child\n"); 50951.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 50961.77Skamil sizeof(lwp)) != -1); 50971.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50981.77Skamil 50991.77Skamil DPRINTF("Assert that the thread exists\n"); 51001.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 51011.77Skamil 51021.77Skamil DPRINTF("Assert that lwp thread %d received expected " 51031.77Skamil "event\n", lwp.pl_lwpid); 51041.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 51051.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 51061.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 51071.77Skamil } 51081.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 51091.77Skamil "tracee\n"); 51101.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 51111.77Skamil != -1); 51121.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 51131.77Skamil 51141.77Skamil DPRINTF("Assert that there are no more threads\n"); 51151.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 51161.77Skamil 51171.77Skamil DPRINTF("Before resuming the child process where it left off " 51181.77Skamil "and without signal to be sent\n"); 51191.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 51201.77Skamil != -1); 51211.77Skamil 51221.1Skamil /* Wait for tracee and assert that it exited */ 51231.1Skamil FORKEE_REQUIRE_SUCCESS( 51241.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 51251.1Skamil 51261.77Skamil forkee_status_signaled(status, SIGKILL, 0); 51271.1Skamil 51281.13Schristos DPRINTF("Before exiting of the tracer process\n"); 51291.1Skamil _exit(exitval_tracer); 51301.1Skamil } 51311.1Skamil 51321.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 51331.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 51341.1Skamil 51351.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 51361.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 51371.77Skamil 51381.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 51391.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 51401.1Skamil 51411.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 51421.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 51431.1Skamil 51441.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 51451.1Skamil TWAIT_FNAME); 51461.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 51471.1Skamil tracer); 51481.1Skamil 51491.1Skamil validate_status_exited(status, exitval_tracer); 51501.1Skamil 51511.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 51521.1Skamil TWAIT_FNAME); 51531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 51541.1Skamil tracee); 51551.1Skamil 51561.77Skamil validate_status_signaled(status, SIGKILL, 0); 51571.1Skamil 51581.1Skamil msg_close(&parent_tracer); 51591.1Skamil msg_close(&parent_tracee); 51601.1Skamil} 51611.77Skamil 51621.77Skamil#define ATTACH_LWPINFO(test, threads) \ 51631.77SkamilATF_TC(test); \ 51641.77SkamilATF_TC_HEAD(test, tc) \ 51651.77Skamil{ \ 51661.77Skamil atf_tc_set_md_var(tc, "descr", \ 51671.77Skamil "Verify LWPINFO with the child with " #threads \ 51681.77Skamil " spawned extra threads (tracer is not the original " \ 51691.77Skamil "parent)"); \ 51701.77Skamil} \ 51711.77Skamil \ 51721.77SkamilATF_TC_BODY(test, tc) \ 51731.77Skamil{ \ 51741.77Skamil \ 51751.77Skamil attach_lwpinfo(threads); \ 51761.77Skamil} 51771.77Skamil 51781.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 51791.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 51801.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 51811.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 51821.1Skamil#endif 51831.1Skamil 51841.77Skamil/// ---------------------------------------------------------------------------- 51851.77Skamil 51861.1Skamilstatic void 51871.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 51881.1Skamil{ 51891.1Skamil const int exitval = 5; 51901.1Skamil const int sigval = SIGINT; 51911.1Skamil const int sigfaked = SIGTRAP; 51921.1Skamil const int sicodefaked = TRAP_BRKPT; 51931.1Skamil pid_t child, wpid; 51941.1Skamil struct sigaction sa; 51951.1Skamil#if defined(TWAIT_HAVE_STATUS) 51961.1Skamil int status; 51971.1Skamil#endif 51981.1Skamil struct ptrace_siginfo info; 51991.1Skamil memset(&info, 0, sizeof(info)); 52001.1Skamil 52011.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52021.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52031.1Skamil if (child == 0) { 52041.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 52051.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 52061.1Skamil 52071.79Skamil sa.sa_sigaction = sah; 52081.1Skamil sa.sa_flags = SA_SIGINFO; 52091.1Skamil sigemptyset(&sa.sa_mask); 52101.1Skamil 52111.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 52121.79Skamil != -1); 52131.1Skamil 52141.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 52151.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 52161.1Skamil 52171.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 52181.1Skamil 52191.13Schristos DPRINTF("Before exiting of the child process\n"); 52201.1Skamil _exit(exitval); 52211.1Skamil } 52221.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52231.1Skamil 52241.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52261.1Skamil 52271.1Skamil validate_status_stopped(status, sigval); 52281.1Skamil 52291.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52301.61Skre SYSCALL_REQUIRE( 52311.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52321.1Skamil 52331.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52341.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52351.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52361.1Skamil info.psi_siginfo.si_errno); 52371.1Skamil 52381.79Skamil if (faked) { 52391.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 52401.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 52411.79Skamil info.psi_siginfo.si_signo = sigfaked; 52421.79Skamil info.psi_siginfo.si_code = sicodefaked; 52431.79Skamil } 52441.1Skamil 52451.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 52461.61Skre SYSCALL_REQUIRE( 52471.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 52481.1Skamil 52491.79Skamil if (faked) { 52501.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52511.79Skamil "child\n"); 52521.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 52531.79Skamil sizeof(info)) != -1); 52541.1Skamil 52551.79Skamil DPRINTF("Before checking siginfo_t\n"); 52561.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 52571.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 52581.79Skamil } 52591.1Skamil 52601.13Schristos DPRINTF("Before resuming the child process where it left off and " 52611.1Skamil "without signal to be sent\n"); 52621.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 52631.79Skamil faked ? sigfaked : sigval) != -1); 52641.1Skamil 52651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52671.1Skamil 52681.1Skamil validate_status_exited(status, exitval); 52691.1Skamil 52701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52711.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 52721.1Skamil} 52731.1Skamil 52741.79Skamil#define PTRACE_SIGINFO(test, faked) \ 52751.79SkamilATF_TC(test); \ 52761.79SkamilATF_TC_HEAD(test, tc) \ 52771.79Skamil{ \ 52781.79Skamil atf_tc_set_md_var(tc, "descr", \ 52791.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 52801.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 52811.79Skamil} \ 52821.79Skamil \ 52831.79Skamilstatic int test##_caught = 0; \ 52841.79Skamil \ 52851.79Skamilstatic void \ 52861.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 52871.79Skamil{ \ 52881.79Skamil if (faked) { \ 52891.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 52901.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 52911.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 52921.79Skamil } else { \ 52931.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 52941.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 52951.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 52961.79Skamil } \ 52971.79Skamil \ 52981.79Skamil ++ test##_caught; \ 52991.79Skamil} \ 53001.79Skamil \ 53011.79SkamilATF_TC_BODY(test, tc) \ 53021.79Skamil{ \ 53031.79Skamil \ 53041.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 53051.79Skamil} 53061.79Skamil 53071.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 53081.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 53091.79Skamil 53101.79Skamil/// ---------------------------------------------------------------------------- 53111.79Skamil 53121.97Skamilstatic void 53131.97Skamiltraceme_exec(bool masked, bool ignored) 53141.1Skamil{ 53151.1Skamil const int sigval = SIGTRAP; 53161.1Skamil pid_t child, wpid; 53171.1Skamil#if defined(TWAIT_HAVE_STATUS) 53181.1Skamil int status; 53191.1Skamil#endif 53201.97Skamil struct sigaction sa; 53211.97Skamil struct ptrace_siginfo info; 53221.97Skamil sigset_t intmask; 53231.97Skamil struct kinfo_proc2 kp; 53241.97Skamil size_t len = sizeof(kp); 53251.97Skamil 53261.97Skamil int name[6]; 53271.97Skamil const size_t namelen = __arraycount(name); 53281.97Skamil ki_sigset_t kp_sigmask; 53291.97Skamil ki_sigset_t kp_sigignore; 53301.1Skamil 53311.1Skamil memset(&info, 0, sizeof(info)); 53321.1Skamil 53331.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53341.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53351.1Skamil if (child == 0) { 53361.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53371.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53381.1Skamil 53391.97Skamil if (masked) { 53401.97Skamil sigemptyset(&intmask); 53411.97Skamil sigaddset(&intmask, sigval); 53421.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53431.97Skamil } 53441.97Skamil 53451.97Skamil if (ignored) { 53461.97Skamil memset(&sa, 0, sizeof(sa)); 53471.97Skamil sa.sa_handler = SIG_IGN; 53481.97Skamil sigemptyset(&sa.sa_mask); 53491.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 53501.97Skamil } 53511.97Skamil 53521.13Schristos DPRINTF("Before calling execve(2) from child\n"); 53531.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 53541.1Skamil 53551.1Skamil FORKEE_ASSERT(0 && "Not reached"); 53561.1Skamil } 53571.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53581.1Skamil 53591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53611.1Skamil 53621.1Skamil validate_status_stopped(status, sigval); 53631.1Skamil 53641.97Skamil name[0] = CTL_KERN, 53651.97Skamil name[1] = KERN_PROC2, 53661.97Skamil name[2] = KERN_PROC_PID; 53671.97Skamil name[3] = getpid(); 53681.97Skamil name[4] = sizeof(kp); 53691.97Skamil name[5] = 1; 53701.97Skamil 53711.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53721.97Skamil 53731.97Skamil if (masked) 53741.97Skamil kp_sigmask = kp.p_sigmask; 53751.97Skamil 53761.97Skamil if (ignored) 53771.97Skamil kp_sigignore = kp.p_sigignore; 53781.97Skamil 53791.97Skamil name[3] = getpid(); 53801.97Skamil 53811.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53821.97Skamil 53831.97Skamil if (masked) { 53841.97Skamil DPRINTF("kp_sigmask=" 53851.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53861.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53871.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53881.97Skamil 53891.97Skamil DPRINTF("kp.p_sigmask=" 53901.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53911.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53921.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53931.97Skamil 53941.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53951.97Skamil sizeof(kp_sigmask))); 53961.97Skamil } 53971.97Skamil 53981.97Skamil if (ignored) { 53991.97Skamil DPRINTF("kp_sigignore=" 54001.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 54011.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 54021.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 54031.97Skamil 54041.97Skamil DPRINTF("kp.p_sigignore=" 54051.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 54061.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 54071.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 54081.97Skamil 54091.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 54101.97Skamil sizeof(kp_sigignore))); 54111.97Skamil } 54121.97Skamil 54131.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 54141.61Skre SYSCALL_REQUIRE( 54151.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54161.1Skamil 54171.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54181.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 54191.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54201.1Skamil info.psi_siginfo.si_errno); 54211.1Skamil 54221.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 54231.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 54241.1Skamil 54251.13Schristos DPRINTF("Before resuming the child process where it left off and " 54261.1Skamil "without signal to be sent\n"); 54271.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54281.1Skamil 54291.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54301.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54311.1Skamil 54321.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54331.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54341.1Skamil} 54351.1Skamil 54361.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 54371.97SkamilATF_TC(test); \ 54381.97SkamilATF_TC_HEAD(test, tc) \ 54391.97Skamil{ \ 54401.97Skamil atf_tc_set_md_var(tc, "descr", \ 54411.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 54421.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 54431.97Skamil masked ? " with ignored signal" : ""); \ 54441.97Skamil} \ 54451.97Skamil \ 54461.97SkamilATF_TC_BODY(test, tc) \ 54471.97Skamil{ \ 54481.97Skamil \ 54491.97Skamil traceme_exec(masked, ignored); \ 54501.97Skamil} 54511.97Skamil 54521.97SkamilTRACEME_EXEC(traceme_exec, false, false) 54531.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 54541.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 54551.97Skamil 54561.82Skamil/// ---------------------------------------------------------------------------- 54571.82Skamil 54581.135Skamil#define TRACE_THREADS_NUM 100 54591.135Skamil 54601.83Skamilstatic volatile int done; 54611.137Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER; 54621.1Skamil 54631.83Skamilstatic void * 54641.83Skamiltrace_threads_cb(void *arg __unused) 54651.1Skamil{ 54661.1Skamil 54671.137Skamil pthread_mutex_lock(&trace_threads_mtx); 54681.83Skamil done++; 54691.137Skamil pthread_mutex_unlock(&trace_threads_mtx); 54701.83Skamil 54711.135Skamil while (done < TRACE_THREADS_NUM) 54721.135Skamil sched_yield(); 54731.83Skamil 54741.83Skamil return NULL; 54751.1Skamil} 54761.1Skamil 54771.83Skamilstatic void 54781.83Skamiltrace_threads(bool trace_create, bool trace_exit) 54791.1Skamil{ 54801.1Skamil const int sigval = SIGSTOP; 54811.1Skamil pid_t child, wpid; 54821.1Skamil#if defined(TWAIT_HAVE_STATUS) 54831.1Skamil int status; 54841.1Skamil#endif 54851.1Skamil ptrace_state_t state; 54861.1Skamil const int slen = sizeof(state); 54871.1Skamil ptrace_event_t event; 54881.1Skamil const int elen = sizeof(event); 54891.83Skamil struct ptrace_siginfo info; 54901.83Skamil 54911.135Skamil pthread_t t[TRACE_THREADS_NUM]; 54921.83Skamil int rv; 54931.83Skamil size_t n; 54941.1Skamil lwpid_t lid; 54951.83Skamil 54961.83Skamil /* Track created and exited threads */ 54971.83Skamil bool traced_lwps[__arraycount(t)]; 54981.83Skamil 54991.128Skamil#if !TEST_LWP_ENABLED 55001.120Skamil if (trace_create || trace_exit) 55011.119Skamil atf_tc_skip("PR kern/51995"); 55021.128Skamil#endif 55031.1Skamil 55041.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 55051.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 55061.1Skamil if (child == 0) { 55071.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 55081.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55091.1Skamil 55101.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 55111.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 55121.1Skamil 55131.83Skamil for (n = 0; n < __arraycount(t); n++) { 55141.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 55151.83Skamil NULL); 55161.83Skamil FORKEE_ASSERT(rv == 0); 55171.83Skamil } 55181.1Skamil 55191.83Skamil for (n = 0; n < __arraycount(t); n++) { 55201.83Skamil rv = pthread_join(t[n], NULL); 55211.83Skamil FORKEE_ASSERT(rv == 0); 55221.83Skamil } 55231.1Skamil 55241.83Skamil /* 55251.83Skamil * There is race between _exit() and pthread_join() detaching 55261.83Skamil * a thread. For simplicity kill the process after detecting 55271.83Skamil * LWP events. 55281.83Skamil */ 55291.83Skamil while (true) 55301.83Skamil continue; 55311.1Skamil 55321.83Skamil FORKEE_ASSERT(0 && "Not reached"); 55331.1Skamil } 55341.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55351.1Skamil 55361.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55371.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55381.1Skamil 55391.1Skamil validate_status_stopped(status, sigval); 55401.1Skamil 55411.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 55421.83Skamil SYSCALL_REQUIRE( 55431.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55441.1Skamil 55451.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55461.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55471.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55481.83Skamil info.psi_siginfo.si_errno); 55491.1Skamil 55501.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55511.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55521.1Skamil 55531.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 55541.83Skamil memset(&event, 0, sizeof(event)); 55551.83Skamil if (trace_create) 55561.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 55571.83Skamil if (trace_exit) 55581.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 55591.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 55601.1Skamil 55611.13Schristos DPRINTF("Before resuming the child process where it left off and " 55621.1Skamil "without signal to be sent\n"); 55631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55641.1Skamil 55651.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 55661.1Skamil 55671.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 55681.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55691.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55701.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55711.83Skamil child); 55721.1Skamil 55731.83Skamil validate_status_stopped(status, SIGTRAP); 55741.1Skamil 55751.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55761.83Skamil "child\n"); 55771.83Skamil SYSCALL_REQUIRE( 55781.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55791.1Skamil 55801.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55811.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55821.83Skamil "si_errno=%#x\n", 55831.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55841.83Skamil info.psi_siginfo.si_errno); 55851.1Skamil 55861.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55871.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55881.1Skamil 55891.83Skamil SYSCALL_REQUIRE( 55901.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55911.1Skamil 55921.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 55931.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 55941.1Skamil 55951.83Skamil lid = state.pe_lwp; 55961.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 55971.1Skamil 55981.83Skamil traced_lwps[lid - 1] = true; 55991.1Skamil 56001.83Skamil DPRINTF("Before resuming the child process where it left off " 56011.83Skamil "and without signal to be sent\n"); 56021.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56031.83Skamil } 56041.1Skamil 56051.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 56061.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 56071.83Skamil "SIGTRAP\n", TWAIT_FNAME); 56081.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 56091.83Skamil child); 56101.1Skamil 56111.83Skamil validate_status_stopped(status, SIGTRAP); 56121.1Skamil 56131.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 56141.83Skamil "child\n"); 56151.83Skamil SYSCALL_REQUIRE( 56161.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56171.1Skamil 56181.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 56191.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 56201.83Skamil "si_errno=%#x\n", 56211.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 56221.83Skamil info.psi_siginfo.si_errno); 56231.1Skamil 56241.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 56251.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 56261.1Skamil 56271.83Skamil SYSCALL_REQUIRE( 56281.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 56291.1Skamil 56301.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 56311.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 56321.1Skamil 56331.83Skamil lid = state.pe_lwp; 56341.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 56351.1Skamil 56361.83Skamil if (trace_create) { 56371.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 56381.83Skamil traced_lwps[lid - 1] = false; 56391.83Skamil } 56401.1Skamil 56411.83Skamil DPRINTF("Before resuming the child process where it left off " 56421.83Skamil "and without signal to be sent\n"); 56431.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56441.83Skamil } 56451.1Skamil 56461.83Skamil kill(child, SIGKILL); 56471.1Skamil 56481.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 56491.1Skamil TWAIT_FNAME); 56501.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56511.1Skamil 56521.83Skamil validate_status_signaled(status, SIGKILL, 0); 56531.1Skamil 56541.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 56551.1Skamil TWAIT_FNAME); 56561.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56571.1Skamil} 56581.1Skamil 56591.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 56601.83SkamilATF_TC(test); \ 56611.83SkamilATF_TC_HEAD(test, tc) \ 56621.83Skamil{ \ 56631.83Skamil atf_tc_set_md_var(tc, "descr", \ 56641.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 56651.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 56661.83Skamil trace_exit ? "" : "out"); \ 56671.83Skamil} \ 56681.83Skamil \ 56691.83SkamilATF_TC_BODY(test, tc) \ 56701.83Skamil{ \ 56711.83Skamil \ 56721.83Skamil trace_threads(trace_create, trace_exit); \ 56731.83Skamil} 56741.83Skamil 56751.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 56761.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 56771.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 56781.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 56791.83Skamil 56801.83Skamil/// ---------------------------------------------------------------------------- 56811.83Skamil 56821.84SkamilATF_TC(signal_mask_unrelated); 56831.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 56841.1Skamil{ 56851.1Skamil atf_tc_set_md_var(tc, "descr", 56861.1Skamil "Verify that masking single unrelated signal does not stop tracer " 56871.1Skamil "from catching other signals"); 56881.1Skamil} 56891.1Skamil 56901.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 56911.1Skamil{ 56921.1Skamil const int exitval = 5; 56931.1Skamil const int sigval = SIGSTOP; 56941.1Skamil const int sigmasked = SIGTRAP; 56951.1Skamil const int signotmasked = SIGINT; 56961.1Skamil pid_t child, wpid; 56971.1Skamil#if defined(TWAIT_HAVE_STATUS) 56981.1Skamil int status; 56991.1Skamil#endif 57001.1Skamil sigset_t intmask; 57011.1Skamil 57021.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57031.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57041.1Skamil if (child == 0) { 57051.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57061.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57071.1Skamil 57081.1Skamil sigemptyset(&intmask); 57091.1Skamil sigaddset(&intmask, sigmasked); 57101.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 57111.1Skamil 57121.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57131.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57141.1Skamil 57151.13Schristos DPRINTF("Before raising %s from child\n", 57161.1Skamil strsignal(signotmasked)); 57171.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 57181.1Skamil 57191.13Schristos DPRINTF("Before exiting of the child process\n"); 57201.1Skamil _exit(exitval); 57211.1Skamil } 57221.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57231.1Skamil 57241.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57261.1Skamil 57271.1Skamil validate_status_stopped(status, sigval); 57281.1Skamil 57291.13Schristos DPRINTF("Before resuming the child process where it left off and " 57301.1Skamil "without signal to be sent\n"); 57311.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57321.1Skamil 57331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57351.1Skamil 57361.1Skamil validate_status_stopped(status, signotmasked); 57371.1Skamil 57381.13Schristos DPRINTF("Before resuming the child process where it left off and " 57391.1Skamil "without signal to be sent\n"); 57401.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57411.1Skamil 57421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57441.1Skamil 57451.1Skamil validate_status_exited(status, exitval); 57461.1Skamil 57471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57481.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57491.1Skamil} 57501.1Skamil 57511.84Skamil/// ---------------------------------------------------------------------------- 57521.84Skamil 57531.1Skamil#if defined(TWAIT_HAVE_PID) 57541.99Skamilstatic void 57551.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 57561.1Skamil{ 57571.1Skamil const int exitval = 5; 57581.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 57591.1Skamil const int sigval = SIGSTOP; 57601.99Skamil pid_t child, child2 = 0, wpid; 57611.1Skamil#if defined(TWAIT_HAVE_STATUS) 57621.1Skamil int status; 57631.1Skamil#endif 57641.1Skamil ptrace_state_t state; 57651.1Skamil const int slen = sizeof(state); 57661.1Skamil ptrace_event_t event; 57671.1Skamil const int elen = sizeof(event); 57681.99Skamil struct sigaction sa; 57691.99Skamil struct ptrace_siginfo info; 57701.99Skamil sigset_t intmask; 57711.99Skamil struct kinfo_proc2 kp; 57721.99Skamil size_t len = sizeof(kp); 57731.99Skamil 57741.99Skamil int name[6]; 57751.99Skamil const size_t namelen = __arraycount(name); 57761.99Skamil ki_sigset_t kp_sigmask; 57771.99Skamil ki_sigset_t kp_sigignore; 57781.1Skamil 57791.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 57801.14Schristos 57811.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57821.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57831.1Skamil if (child == 0) { 57841.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57851.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57861.1Skamil 57871.99Skamil if (masked) { 57881.99Skamil sigemptyset(&intmask); 57891.99Skamil sigaddset(&intmask, SIGTRAP); 57901.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 57911.99Skamil } 57921.99Skamil 57931.99Skamil if (ignored) { 57941.99Skamil memset(&sa, 0, sizeof(sa)); 57951.99Skamil sa.sa_handler = SIG_IGN; 57961.99Skamil sigemptyset(&sa.sa_mask); 57971.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 57981.99Skamil } 57991.1Skamil 58001.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 58011.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 58021.1Skamil 58031.126Skamil if (strcmp(fn, "spawn") == 0) { 58041.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 58051.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 58061.126Skamil } else { 58071.126Skamil if (strcmp(fn, "fork") == 0) { 58081.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 58091.126Skamil } else { 58101.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 58111.126Skamil } 58121.126Skamil if (child2 == 0) 58131.126Skamil _exit(exitval2); 58141.126Skamil } 58151.1Skamil 58161.1Skamil FORKEE_REQUIRE_SUCCESS 58171.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 58181.1Skamil 58191.1Skamil forkee_status_exited(status, exitval2); 58201.1Skamil 58211.13Schristos DPRINTF("Before exiting of the child process\n"); 58221.1Skamil _exit(exitval); 58231.1Skamil } 58241.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 58251.1Skamil 58261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 58271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58281.1Skamil 58291.1Skamil validate_status_stopped(status, sigval); 58301.1Skamil 58311.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 58321.99Skamil SYSCALL_REQUIRE( 58331.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 58341.99Skamil 58351.99Skamil DPRINTF("Before checking siginfo_t\n"); 58361.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 58371.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 58381.1Skamil 58391.99Skamil name[0] = CTL_KERN, 58401.99Skamil name[1] = KERN_PROC2, 58411.99Skamil name[2] = KERN_PROC_PID; 58421.99Skamil name[3] = child; 58431.99Skamil name[4] = sizeof(kp); 58441.99Skamil name[5] = 1; 58451.1Skamil 58461.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58471.1Skamil 58481.99Skamil if (masked) 58491.99Skamil kp_sigmask = kp.p_sigmask; 58501.1Skamil 58511.99Skamil if (ignored) 58521.99Skamil kp_sigignore = kp.p_sigignore; 58531.1Skamil 58541.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 58551.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 58561.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 58571.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 58581.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 58591.99Skamil event.pe_set_event = 0; 58601.126Skamil if (strcmp(fn, "spawn") == 0) 58611.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 58621.126Skamil if (strcmp(fn, "fork") == 0) 58631.99Skamil event.pe_set_event |= PTRACE_FORK; 58641.126Skamil if (strcmp(fn, "vfork") == 0) 58651.99Skamil event.pe_set_event |= PTRACE_VFORK; 58661.126Skamil if (strcmp(fn, "vforkdone") == 0) 58671.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 58681.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58691.1Skamil 58701.99Skamil DPRINTF("Before resuming the child process where it left off and " 58711.99Skamil "without signal to be sent\n"); 58721.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58731.1Skamil 58741.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 58751.126Skamil strcmp(fn, "vfork") == 0) { 58761.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58771.99Skamil child); 58781.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58791.99Skamil child); 58801.1Skamil 58811.99Skamil validate_status_stopped(status, SIGTRAP); 58821.1Skamil 58831.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58841.1Skamil 58851.99Skamil if (masked) { 58861.99Skamil DPRINTF("kp_sigmask=" 58871.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58881.99Skamil PRIx32 "\n", 58891.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58901.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58911.1Skamil 58921.99Skamil DPRINTF("kp.p_sigmask=" 58931.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58941.99Skamil PRIx32 "\n", 58951.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58961.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58971.1Skamil 58981.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58991.99Skamil sizeof(kp_sigmask))); 59001.99Skamil } 59011.1Skamil 59021.99Skamil if (ignored) { 59031.99Skamil DPRINTF("kp_sigignore=" 59041.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59051.99Skamil PRIx32 "\n", 59061.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59071.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59081.1Skamil 59091.99Skamil DPRINTF("kp.p_sigignore=" 59101.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59111.99Skamil PRIx32 "\n", 59121.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59131.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59141.1Skamil 59151.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59161.99Skamil sizeof(kp_sigignore))); 59171.99Skamil } 59181.1Skamil 59191.99Skamil SYSCALL_REQUIRE( 59201.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 59211.126Skamil if (strcmp(fn, "spawn") == 0) { 59221.126Skamil ATF_REQUIRE_EQ( 59231.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59241.126Skamil PTRACE_POSIX_SPAWN); 59251.126Skamil } 59261.126Skamil if (strcmp(fn, "fork") == 0) { 59271.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59281.99Skamil PTRACE_FORK); 59291.99Skamil } 59301.126Skamil if (strcmp(fn, "vfork") == 0) { 59311.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59321.99Skamil PTRACE_VFORK); 59331.99Skamil } 59341.1Skamil 59351.99Skamil child2 = state.pe_other_pid; 59361.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 59371.1Skamil 59381.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 59391.99Skamil "%d\n", TWAIT_FNAME, child2, child); 59401.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 59411.99Skamil child2); 59421.1Skamil 59431.99Skamil validate_status_stopped(status, SIGTRAP); 59441.1Skamil 59451.99Skamil name[3] = child2; 59461.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59471.1Skamil 59481.99Skamil if (masked) { 59491.99Skamil DPRINTF("kp_sigmask=" 59501.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59511.99Skamil PRIx32 "\n", 59521.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59531.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59541.1Skamil 59551.99Skamil DPRINTF("kp.p_sigmask=" 59561.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59571.99Skamil PRIx32 "\n", 59581.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59591.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59601.14Schristos 59611.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59621.99Skamil sizeof(kp_sigmask))); 59631.99Skamil } 59641.1Skamil 59651.99Skamil if (ignored) { 59661.99Skamil DPRINTF("kp_sigignore=" 59671.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59681.99Skamil PRIx32 "\n", 59691.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59701.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59711.1Skamil 59721.99Skamil DPRINTF("kp.p_sigignore=" 59731.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59741.99Skamil PRIx32 "\n", 59751.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59761.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59771.1Skamil 59781.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59791.99Skamil sizeof(kp_sigignore))); 59801.99Skamil } 59811.1Skamil 59821.99Skamil SYSCALL_REQUIRE( 59831.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 59841.126Skamil if (strcmp(fn, "spawn") == 0) { 59851.126Skamil ATF_REQUIRE_EQ( 59861.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59871.126Skamil PTRACE_POSIX_SPAWN); 59881.126Skamil } 59891.126Skamil if (strcmp(fn, "fork") == 0) { 59901.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59911.99Skamil PTRACE_FORK); 59921.99Skamil } 59931.126Skamil if (strcmp(fn, "vfork") == 0) { 59941.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59951.99Skamil PTRACE_VFORK); 59961.99Skamil } 59971.1Skamil 59981.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 59991.1Skamil 60001.99Skamil DPRINTF("Before resuming the forkee process where it left off " 60011.99Skamil "and without signal to be sent\n"); 60021.99Skamil SYSCALL_REQUIRE( 60031.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 60041.1Skamil 60051.99Skamil DPRINTF("Before resuming the child process where it left off " 60061.99Skamil "and without signal to be sent\n"); 60071.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60081.1Skamil } 60091.1Skamil 60101.126Skamil if (strcmp(fn, "vforkdone") == 0) { 60111.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 60121.99Skamil child); 60131.99Skamil TWAIT_REQUIRE_SUCCESS( 60141.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 60151.1Skamil 60161.99Skamil validate_status_stopped(status, SIGTRAP); 60171.1Skamil 60181.99Skamil name[3] = child; 60191.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 60201.1Skamil 60211.102Skamil /* 60221.102Skamil * SIGCHLD is now pending in the signal queue and 60231.102Skamil * the kernel presents it to userland as a masked signal. 60241.102Skamil */ 60251.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 60261.102Skamil 60271.99Skamil if (masked) { 60281.99Skamil DPRINTF("kp_sigmask=" 60291.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60301.99Skamil PRIx32 "\n", 60311.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 60321.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 60331.1Skamil 60341.99Skamil DPRINTF("kp.p_sigmask=" 60351.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60361.99Skamil PRIx32 "\n", 60371.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 60381.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 60391.1Skamil 60401.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 60411.99Skamil sizeof(kp_sigmask))); 60421.99Skamil } 60431.1Skamil 60441.99Skamil if (ignored) { 60451.99Skamil DPRINTF("kp_sigignore=" 60461.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60471.99Skamil PRIx32 "\n", 60481.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 60491.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 60501.1Skamil 60511.99Skamil DPRINTF("kp.p_sigignore=" 60521.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60531.99Skamil PRIx32 "\n", 60541.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 60551.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 60561.1Skamil 60571.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 60581.99Skamil sizeof(kp_sigignore))); 60591.99Skamil } 60601.1Skamil 60611.99Skamil SYSCALL_REQUIRE( 60621.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60631.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 60641.1Skamil 60651.99Skamil child2 = state.pe_other_pid; 60661.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 60671.99Skamil child2); 60681.1Skamil 60691.99Skamil DPRINTF("Before resuming the child process where it left off " 60701.99Skamil "and without signal to be sent\n"); 60711.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60721.99Skamil } 60731.1Skamil 60741.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 60751.126Skamil strcmp(fn, "vfork") == 0) { 60761.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 60771.99Skamil "\n", TWAIT_FNAME); 60781.99Skamil TWAIT_REQUIRE_SUCCESS( 60791.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 60801.1Skamil 60811.99Skamil validate_status_exited(status, exitval2); 60821.1Skamil 60831.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 60841.99Skamil "process\n", TWAIT_FNAME); 60851.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 60861.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 60871.99Skamil } 60881.1Skamil 60891.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60901.1Skamil "SIGCHLD\n", TWAIT_FNAME); 60911.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60921.1Skamil 60931.1Skamil validate_status_stopped(status, SIGCHLD); 60941.1Skamil 60951.57Skamil DPRINTF("Before resuming the child process where it left off and " 60961.1Skamil "without signal to be sent\n"); 60971.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60981.1Skamil 60991.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 61001.1Skamil TWAIT_FNAME); 61011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61021.1Skamil 61031.1Skamil validate_status_exited(status, exitval); 61041.1Skamil 61051.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 61061.57Skamil TWAIT_FNAME); 61071.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 61081.1Skamil} 61091.1Skamil 61101.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 61111.99SkamilATF_TC(name); \ 61121.99SkamilATF_TC_HEAD(name, tc) \ 61131.99Skamil{ \ 61141.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 61151.99Skamil "regardless of signal %s%s", \ 61161.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 61171.99Skamil} \ 61181.99Skamil \ 61191.99SkamilATF_TC_BODY(name, tc) \ 61201.99Skamil{ \ 61211.99Skamil \ 61221.126Skamil fork2_body(fn, masked, ignored); \ 61231.1Skamil} 61241.1Skamil 61251.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 61261.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 61271.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 61281.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 61291.110Skamil#if TEST_VFORK_ENABLED 61301.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 61311.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 61321.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 61331.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 61341.1Skamil#endif 61351.110Skamil#endif 61361.1Skamil 61371.99Skamil/// ---------------------------------------------------------------------------- 61381.1Skamil 61391.83Skamilvolatile lwpid_t the_lwp_id = 0; 61401.83Skamil 61411.83Skamilstatic void 61421.83Skamillwp_main_func(void *arg) 61431.83Skamil{ 61441.83Skamil the_lwp_id = _lwp_self(); 61451.83Skamil _lwp_exit(); 61461.83Skamil} 61471.83Skamil 61481.1SkamilATF_TC(signal9); 61491.1SkamilATF_TC_HEAD(signal9, tc) 61501.1Skamil{ 61511.1Skamil atf_tc_set_md_var(tc, "descr", 61521.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61531.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 61541.1Skamil} 61551.1Skamil 61561.1SkamilATF_TC_BODY(signal9, tc) 61571.1Skamil{ 61581.1Skamil const int exitval = 5; 61591.1Skamil const int sigval = SIGSTOP; 61601.1Skamil const int sigmasked = SIGTRAP; 61611.1Skamil pid_t child, wpid; 61621.1Skamil#if defined(TWAIT_HAVE_STATUS) 61631.1Skamil int status; 61641.1Skamil#endif 61651.1Skamil sigset_t intmask; 61661.1Skamil ptrace_state_t state; 61671.1Skamil const int slen = sizeof(state); 61681.1Skamil ptrace_event_t event; 61691.1Skamil const int elen = sizeof(event); 61701.1Skamil ucontext_t uc; 61711.1Skamil lwpid_t lid; 61721.1Skamil static const size_t ssize = 16*1024; 61731.1Skamil void *stack; 61741.1Skamil 61751.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61761.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61771.1Skamil if (child == 0) { 61781.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61791.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61801.1Skamil 61811.1Skamil sigemptyset(&intmask); 61821.1Skamil sigaddset(&intmask, sigmasked); 61831.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61841.1Skamil 61851.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61861.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61871.1Skamil 61881.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61891.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61901.1Skamil 61911.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61921.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61931.1Skamil 61941.13Schristos DPRINTF("Before creating new in child\n"); 61951.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61961.1Skamil 61971.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61981.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61991.1Skamil 62001.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62011.1Skamil "are the same\n", lid, the_lwp_id); 62021.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62031.1Skamil 62041.13Schristos DPRINTF("Before exiting of the child process\n"); 62051.1Skamil _exit(exitval); 62061.1Skamil } 62071.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62081.1Skamil 62091.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62111.1Skamil 62121.1Skamil validate_status_stopped(status, sigval); 62131.1Skamil 62141.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 62151.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 62161.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 62171.1Skamil 62181.13Schristos DPRINTF("Before resuming the child process where it left off and " 62191.1Skamil "without signal to be sent\n"); 62201.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62211.1Skamil 62221.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62231.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62241.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62251.1Skamil 62261.1Skamil validate_status_stopped(status, sigmasked); 62271.1Skamil 62281.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 62291.1Skamil 62301.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 62311.1Skamil 62321.1Skamil lid = state.pe_lwp; 62331.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 62341.1Skamil 62351.13Schristos DPRINTF("Before resuming the child process where it left off and " 62361.1Skamil "without signal to be sent\n"); 62371.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62381.1Skamil 62391.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62401.1Skamil TWAIT_FNAME); 62411.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62421.1Skamil 62431.1Skamil validate_status_exited(status, exitval); 62441.1Skamil 62451.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62461.1Skamil TWAIT_FNAME); 62471.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62481.1Skamil} 62491.1Skamil 62501.1SkamilATF_TC(signal10); 62511.1SkamilATF_TC_HEAD(signal10, tc) 62521.1Skamil{ 62531.1Skamil atf_tc_set_md_var(tc, "descr", 62541.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 62551.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 62561.1Skamil} 62571.1Skamil 62581.1SkamilATF_TC_BODY(signal10, tc) 62591.1Skamil{ 62601.1Skamil const int exitval = 5; 62611.1Skamil const int sigval = SIGSTOP; 62621.1Skamil const int sigmasked = SIGTRAP; 62631.1Skamil pid_t child, wpid; 62641.1Skamil#if defined(TWAIT_HAVE_STATUS) 62651.1Skamil int status; 62661.1Skamil#endif 62671.1Skamil sigset_t intmask; 62681.1Skamil ptrace_state_t state; 62691.1Skamil const int slen = sizeof(state); 62701.1Skamil ptrace_event_t event; 62711.1Skamil const int elen = sizeof(event); 62721.1Skamil ucontext_t uc; 62731.1Skamil lwpid_t lid; 62741.1Skamil static const size_t ssize = 16*1024; 62751.1Skamil void *stack; 62761.1Skamil 62771.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62781.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62791.1Skamil if (child == 0) { 62801.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62811.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62821.1Skamil 62831.1Skamil sigemptyset(&intmask); 62841.1Skamil sigaddset(&intmask, sigmasked); 62851.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62861.1Skamil 62871.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62881.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62891.1Skamil 62901.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62911.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62921.1Skamil 62931.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62941.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 62951.1Skamil 62961.13Schristos DPRINTF("Before creating new in child\n"); 62971.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62981.1Skamil 62991.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 63001.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 63011.1Skamil 63021.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 63031.1Skamil "are the same\n", lid, the_lwp_id); 63041.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 63051.1Skamil 63061.13Schristos DPRINTF("Before exiting of the child process\n"); 63071.1Skamil _exit(exitval); 63081.1Skamil } 63091.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63101.1Skamil 63111.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63131.1Skamil 63141.1Skamil validate_status_stopped(status, sigval); 63151.1Skamil 63161.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 63171.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 63181.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 63191.1Skamil 63201.13Schristos DPRINTF("Before resuming the child process where it left off and " 63211.1Skamil "without signal to be sent\n"); 63221.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63231.1Skamil 63241.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63251.1Skamil "SIGTRAP\n", TWAIT_FNAME); 63261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63271.1Skamil 63281.1Skamil validate_status_stopped(status, sigmasked); 63291.1Skamil 63301.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 63311.1Skamil 63321.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 63331.1Skamil 63341.1Skamil lid = state.pe_lwp; 63351.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 63361.1Skamil 63371.13Schristos DPRINTF("Before resuming the child process where it left off and " 63381.1Skamil "without signal to be sent\n"); 63391.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63401.1Skamil 63411.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63421.1Skamil TWAIT_FNAME); 63431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63441.1Skamil 63451.1Skamil validate_status_exited(status, exitval); 63461.1Skamil 63471.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63481.1Skamil TWAIT_FNAME); 63491.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63501.1Skamil} 63511.1Skamil 63521.1Skamilstatic void 63531.1Skamillwp_main_stop(void *arg) 63541.1Skamil{ 63551.1Skamil the_lwp_id = _lwp_self(); 63561.1Skamil 63571.1Skamil raise(SIGTRAP); 63581.1Skamil 63591.1Skamil _lwp_exit(); 63601.1Skamil} 63611.1Skamil 63621.1SkamilATF_TC(suspend2); 63631.1SkamilATF_TC_HEAD(suspend2, tc) 63641.1Skamil{ 63651.1Skamil atf_tc_set_md_var(tc, "descr", 63661.1Skamil "Verify that the while the only thread within a process is " 63671.1Skamil "suspended, the whole process cannot be unstopped"); 63681.1Skamil} 63691.1Skamil 63701.1SkamilATF_TC_BODY(suspend2, tc) 63711.1Skamil{ 63721.1Skamil const int exitval = 5; 63731.1Skamil const int sigval = SIGSTOP; 63741.1Skamil pid_t child, wpid; 63751.1Skamil#if defined(TWAIT_HAVE_STATUS) 63761.1Skamil int status; 63771.1Skamil#endif 63781.1Skamil struct ptrace_siginfo psi; 63791.1Skamil 63801.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63811.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63821.1Skamil if (child == 0) { 63831.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63841.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63851.1Skamil 63861.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63871.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63881.1Skamil 63891.13Schristos DPRINTF("Before exiting of the child process\n"); 63901.1Skamil _exit(exitval); 63911.1Skamil } 63921.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63931.1Skamil 63941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63961.1Skamil 63971.1Skamil validate_status_stopped(status, sigval); 63981.1Skamil 63991.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64001.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64011.1Skamil 64021.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64031.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64041.1Skamil 64051.13Schristos DPRINTF("Before resuming the child process where it left off and " 64061.1Skamil "without signal to be sent\n"); 64071.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 64081.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 64091.1Skamil 64101.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 64111.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 64121.1Skamil 64131.13Schristos DPRINTF("Before resuming the child process where it left off and " 64141.1Skamil "without signal to be sent\n"); 64151.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64161.1Skamil 64171.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 64181.1Skamil TWAIT_FNAME); 64191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64201.1Skamil 64211.1Skamil validate_status_exited(status, exitval); 64221.1Skamil 64231.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64241.1Skamil TWAIT_FNAME); 64251.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64261.1Skamil} 64271.1Skamil 64281.1SkamilATF_TC(resume1); 64291.1SkamilATF_TC_HEAD(resume1, tc) 64301.1Skamil{ 64311.1Skamil atf_tc_set_md_var(tc, "descr", 64321.1Skamil "Verify that a thread can be suspended by a debugger and later " 64331.1Skamil "resumed by the debugger"); 64341.1Skamil} 64351.1Skamil 64361.1SkamilATF_TC_BODY(resume1, tc) 64371.1Skamil{ 64381.1Skamil struct msg_fds fds; 64391.1Skamil const int exitval = 5; 64401.1Skamil const int sigval = SIGSTOP; 64411.1Skamil pid_t child, wpid; 64421.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 64431.1Skamil#if defined(TWAIT_HAVE_STATUS) 64441.1Skamil int status; 64451.1Skamil#endif 64461.1Skamil ucontext_t uc; 64471.1Skamil lwpid_t lid; 64481.1Skamil static const size_t ssize = 16*1024; 64491.1Skamil void *stack; 64501.1Skamil struct ptrace_lwpinfo pl; 64511.1Skamil struct ptrace_siginfo psi; 64521.1Skamil 64531.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 64541.1Skamil 64551.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64561.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64571.1Skamil if (child == 0) { 64581.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64591.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64601.1Skamil 64611.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64621.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64631.1Skamil 64641.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 64651.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 64661.1Skamil 64671.13Schristos DPRINTF("Before making context for new lwp in child\n"); 64681.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 64691.1Skamil 64701.13Schristos DPRINTF("Before creating new in child\n"); 64711.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 64721.1Skamil 64731.1Skamil CHILD_TO_PARENT("Message", fds, msg); 64741.1Skamil 64751.1Skamil raise(SIGINT); 64761.1Skamil 64771.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 64781.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 64791.1Skamil 64801.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 64811.1Skamil "are the same\n", lid, the_lwp_id); 64821.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 64831.1Skamil 64841.13Schristos DPRINTF("Before exiting of the child process\n"); 64851.1Skamil _exit(exitval); 64861.1Skamil } 64871.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64881.1Skamil 64891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64911.1Skamil 64921.1Skamil validate_status_stopped(status, sigval); 64931.1Skamil 64941.13Schristos DPRINTF("Before resuming the child process where it left off and " 64951.1Skamil "without signal to be sent\n"); 64961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64971.1Skamil 64981.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64991.1Skamil "SIGTRAP\n", TWAIT_FNAME); 65001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65011.1Skamil 65021.1Skamil validate_status_stopped(status, SIGTRAP); 65031.1Skamil 65041.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 65051.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 65061.1Skamil 65071.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 65081.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 65091.1Skamil 65101.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 65111.1Skamil 65121.13Schristos DPRINTF("Before resuming the child process where it left off and " 65131.1Skamil "without signal to be sent\n"); 65141.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65151.1Skamil 65161.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 65171.1Skamil "SIGINT\n", TWAIT_FNAME); 65181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65191.1Skamil 65201.1Skamil validate_status_stopped(status, SIGINT); 65211.1Skamil 65221.1Skamil pl.pl_lwpid = 0; 65231.1Skamil 65241.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65251.1Skamil while (pl.pl_lwpid != 0) { 65261.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65271.1Skamil switch (pl.pl_lwpid) { 65281.1Skamil case 1: 65291.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 65301.1Skamil break; 65311.1Skamil case 2: 65321.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 65331.1Skamil break; 65341.1Skamil } 65351.1Skamil } 65361.1Skamil 65371.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65381.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65391.1Skamil 65401.13Schristos DPRINTF("Before resuming the child process where it left off and " 65411.1Skamil "without signal to be sent\n"); 65421.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65431.1Skamil 65441.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65451.1Skamil TWAIT_FNAME); 65461.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65471.1Skamil 65481.1Skamil validate_status_exited(status, exitval); 65491.1Skamil 65501.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65511.1Skamil TWAIT_FNAME); 65521.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65531.1Skamil 65541.1Skamil msg_close(&fds); 65551.1Skamil} 65561.1Skamil 65571.1SkamilATF_TC(syscall1); 65581.1SkamilATF_TC_HEAD(syscall1, tc) 65591.1Skamil{ 65601.1Skamil atf_tc_set_md_var(tc, "descr", 65611.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 65621.1Skamil} 65631.1Skamil 65641.1SkamilATF_TC_BODY(syscall1, tc) 65651.1Skamil{ 65661.1Skamil const int exitval = 5; 65671.1Skamil const int sigval = SIGSTOP; 65681.1Skamil pid_t child, wpid; 65691.1Skamil#if defined(TWAIT_HAVE_STATUS) 65701.1Skamil int status; 65711.1Skamil#endif 65721.1Skamil struct ptrace_siginfo info; 65731.1Skamil memset(&info, 0, sizeof(info)); 65741.1Skamil 65751.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65761.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65771.1Skamil if (child == 0) { 65781.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65791.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65801.1Skamil 65811.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65821.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65831.1Skamil 65841.1Skamil syscall(SYS_getpid); 65851.1Skamil 65861.13Schristos DPRINTF("Before exiting of the child process\n"); 65871.1Skamil _exit(exitval); 65881.1Skamil } 65891.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65901.1Skamil 65911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65931.1Skamil 65941.1Skamil validate_status_stopped(status, sigval); 65951.1Skamil 65961.13Schristos DPRINTF("Before resuming the child process where it left off and " 65971.1Skamil "without signal to be sent\n"); 65981.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65991.1Skamil 66001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66021.1Skamil 66031.1Skamil validate_status_stopped(status, SIGTRAP); 66041.1Skamil 66051.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 66061.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66071.1Skamil 66081.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 66091.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66101.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 66111.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 66121.1Skamil 66131.13Schristos DPRINTF("Before resuming the child process where it left off and " 66141.1Skamil "without signal to be sent\n"); 66151.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66161.1Skamil 66171.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66191.1Skamil 66201.1Skamil validate_status_stopped(status, SIGTRAP); 66211.1Skamil 66221.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 66231.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66241.1Skamil 66251.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 66261.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66271.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 66281.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 66291.1Skamil 66301.13Schristos DPRINTF("Before resuming the child process where it left off and " 66311.1Skamil "without signal to be sent\n"); 66321.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66331.1Skamil 66341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66361.1Skamil 66371.1Skamil validate_status_exited(status, exitval); 66381.1Skamil 66391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66401.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66411.1Skamil} 66421.1Skamil 66431.1SkamilATF_TC(syscallemu1); 66441.1SkamilATF_TC_HEAD(syscallemu1, tc) 66451.1Skamil{ 66461.1Skamil atf_tc_set_md_var(tc, "descr", 66471.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 66481.1Skamil} 66491.1Skamil 66501.1SkamilATF_TC_BODY(syscallemu1, tc) 66511.1Skamil{ 66521.1Skamil const int exitval = 5; 66531.1Skamil const int sigval = SIGSTOP; 66541.1Skamil pid_t child, wpid; 66551.1Skamil#if defined(TWAIT_HAVE_STATUS) 66561.1Skamil int status; 66571.1Skamil#endif 66581.1Skamil 66591.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 66601.6Skamil /* syscallemu does not work on sparc (32-bit) */ 66611.6Skamil atf_tc_expect_fail("PR kern/52166"); 66621.6Skamil#endif 66631.6Skamil 66641.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66651.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66661.1Skamil if (child == 0) { 66671.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66681.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66691.1Skamil 66701.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66711.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66721.1Skamil 66731.1Skamil syscall(SYS_exit, 100); 66741.1Skamil 66751.13Schristos DPRINTF("Before exiting of the child process\n"); 66761.1Skamil _exit(exitval); 66771.1Skamil } 66781.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66791.1Skamil 66801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66821.1Skamil 66831.1Skamil validate_status_stopped(status, sigval); 66841.1Skamil 66851.13Schristos DPRINTF("Before resuming the child process where it left off and " 66861.1Skamil "without signal to be sent\n"); 66871.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66881.1Skamil 66891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66911.1Skamil 66921.1Skamil validate_status_stopped(status, SIGTRAP); 66931.1Skamil 66941.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 66951.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 66961.1Skamil 66971.13Schristos DPRINTF("Before resuming the child process where it left off and " 66981.1Skamil "without signal to be sent\n"); 66991.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67001.1Skamil 67011.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67031.1Skamil 67041.1Skamil validate_status_stopped(status, SIGTRAP); 67051.1Skamil 67061.13Schristos DPRINTF("Before resuming the child process where it left off and " 67071.1Skamil "without signal to be sent\n"); 67081.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67091.1Skamil 67101.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67121.1Skamil 67131.1Skamil validate_status_exited(status, exitval); 67141.1Skamil 67151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67161.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 67171.1Skamil} 67181.1Skamil 67191.103Skamil/// ---------------------------------------------------------------------------- 67201.103Skamil 67211.106Skamilstatic void 67221.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 67231.106Skamil bool trackvforkdone) 67241.106Skamil{ 67251.106Skamil const int exitval = 5; 67261.106Skamil const int exitval2 = 15; 67271.106Skamil const int sigval = SIGSTOP; 67281.106Skamil pid_t child, child2 = 0, wpid; 67291.106Skamil#if defined(TWAIT_HAVE_STATUS) 67301.106Skamil int status; 67311.106Skamil#endif 67321.106Skamil ptrace_state_t state; 67331.106Skamil const int slen = sizeof(state); 67341.106Skamil ptrace_event_t event; 67351.106Skamil const int elen = sizeof(event); 67361.106Skamil 67371.106Skamil const size_t stack_size = 1024 * 1024; 67381.106Skamil void *stack, *stack_base; 67391.106Skamil 67401.106Skamil stack = malloc(stack_size); 67411.106Skamil ATF_REQUIRE(stack != NULL); 67421.106Skamil 67431.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 67441.106Skamil stack_base = stack; 67451.106Skamil#else 67461.106Skamil stack_base = (char *)stack + stack_size; 67471.106Skamil#endif 67481.106Skamil 67491.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 67501.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 67511.106Skamil if (child == 0) { 67521.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67531.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67541.106Skamil 67551.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67561.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 67571.106Skamil 67581.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 67591.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 67601.106Skamil 67611.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 67621.106Skamil child2); 67631.106Skamil 67641.106Skamil // XXX WALLSIG? 67651.106Skamil FORKEE_REQUIRE_SUCCESS 67661.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 67671.106Skamil 67681.106Skamil forkee_status_exited(status, exitval2); 67691.106Skamil 67701.106Skamil DPRINTF("Before exiting of the child process\n"); 67711.106Skamil _exit(exitval); 67721.106Skamil } 67731.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67741.106Skamil 67751.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67761.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67771.106Skamil 67781.106Skamil validate_status_stopped(status, sigval); 67791.106Skamil 67801.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 67811.106Skamil trackfork ? "|PTRACE_FORK" : "", 67821.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 67831.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 67841.106Skamil event.pe_set_event = 0; 67851.106Skamil if (trackfork) 67861.106Skamil event.pe_set_event |= PTRACE_FORK; 67871.106Skamil if (trackvfork) 67881.106Skamil event.pe_set_event |= PTRACE_VFORK; 67891.106Skamil if (trackvforkdone) 67901.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 67911.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 67921.106Skamil 67931.106Skamil DPRINTF("Before resuming the child process where it left off and " 67941.106Skamil "without signal to be sent\n"); 67951.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67961.106Skamil 67971.106Skamil#if defined(TWAIT_HAVE_PID) 67981.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 67991.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68001.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68011.106Skamil child); 68021.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 68031.106Skamil child); 68041.106Skamil 68051.106Skamil validate_status_stopped(status, SIGTRAP); 68061.106Skamil 68071.106Skamil SYSCALL_REQUIRE( 68081.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68091.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68101.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68111.106Skamil PTRACE_FORK); 68121.106Skamil } 68131.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 68141.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68151.106Skamil PTRACE_VFORK); 68161.106Skamil } 68171.106Skamil 68181.106Skamil child2 = state.pe_other_pid; 68191.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 68201.106Skamil 68211.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 68221.106Skamil "%d\n", TWAIT_FNAME, child2, child); 68231.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 68241.106Skamil child2); 68251.106Skamil 68261.106Skamil validate_status_stopped(status, SIGTRAP); 68271.106Skamil 68281.106Skamil SYSCALL_REQUIRE( 68291.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 68301.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68311.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68321.106Skamil PTRACE_FORK); 68331.106Skamil } 68341.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 68351.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68361.106Skamil PTRACE_VFORK); 68371.106Skamil } 68381.106Skamil 68391.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 68401.106Skamil 68411.106Skamil DPRINTF("Before resuming the forkee process where it left off " 68421.106Skamil "and without signal to be sent\n"); 68431.106Skamil SYSCALL_REQUIRE( 68441.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 68451.106Skamil 68461.106Skamil DPRINTF("Before resuming the child process where it left off " 68471.106Skamil "and without signal to be sent\n"); 68481.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68491.106Skamil } 68501.106Skamil#endif 68511.106Skamil 68521.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 68531.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68541.106Skamil child); 68551.106Skamil TWAIT_REQUIRE_SUCCESS( 68561.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 68571.106Skamil 68581.106Skamil validate_status_stopped(status, SIGTRAP); 68591.106Skamil 68601.106Skamil SYSCALL_REQUIRE( 68611.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68621.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 68631.106Skamil 68641.106Skamil child2 = state.pe_other_pid; 68651.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 68661.106Skamil child2); 68671.106Skamil 68681.106Skamil DPRINTF("Before resuming the child process where it left off " 68691.106Skamil "and without signal to be sent\n"); 68701.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68711.106Skamil } 68721.106Skamil 68731.103Skamil#if defined(TWAIT_HAVE_PID) 68741.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68751.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68761.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 68771.106Skamil "\n", TWAIT_FNAME); 68781.106Skamil TWAIT_REQUIRE_SUCCESS( 68791.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 68801.106Skamil 68811.106Skamil validate_status_exited(status, exitval2); 68821.106Skamil 68831.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 68841.106Skamil "process\n", TWAIT_FNAME); 68851.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 68861.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 68871.106Skamil } 68881.106Skamil#endif 68891.106Skamil 68901.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 68911.106Skamil "SIGCHLD\n", TWAIT_FNAME); 68921.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68931.106Skamil 68941.106Skamil validate_status_stopped(status, SIGCHLD); 68951.106Skamil 68961.106Skamil DPRINTF("Before resuming the child process where it left off and " 68971.106Skamil "without signal to be sent\n"); 68981.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68991.106Skamil 69001.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 69011.106Skamil TWAIT_FNAME); 69021.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69031.106Skamil 69041.106Skamil validate_status_exited(status, exitval); 69051.103Skamil 69061.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 69071.106Skamil TWAIT_FNAME); 69081.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 69091.106Skamil} 69101.103Skamil 69111.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 69121.106SkamilATF_TC(name); \ 69131.106SkamilATF_TC_HEAD(name, tc) \ 69141.106Skamil{ \ 69151.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 69161.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 69171.106Skamil #flags, \ 69181.106Skamil tfork ? "|PTRACE_FORK" : "", \ 69191.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 69201.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 69211.106Skamil} \ 69221.106Skamil \ 69231.106SkamilATF_TC_BODY(name, tc) \ 69241.106Skamil{ \ 69251.106Skamil \ 69261.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 69271.103Skamil} 69281.103Skamil 69291.106SkamilCLONE_TEST(clone1, 0, false, false, false) 69301.106Skamil#if defined(TWAIT_HAVE_PID) 69311.106SkamilCLONE_TEST(clone2, 0, true, false, false) 69321.106SkamilCLONE_TEST(clone3, 0, false, true, false) 69331.106SkamilCLONE_TEST(clone4, 0, true, true, false) 69341.106Skamil#endif 69351.106SkamilCLONE_TEST(clone5, 0, false, false, true) 69361.106Skamil#if defined(TWAIT_HAVE_PID) 69371.106SkamilCLONE_TEST(clone6, 0, true, false, true) 69381.106SkamilCLONE_TEST(clone7, 0, false, true, true) 69391.106SkamilCLONE_TEST(clone8, 0, true, true, true) 69401.106Skamil#endif 69411.106Skamil 69421.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 69431.106Skamil#if defined(TWAIT_HAVE_PID) 69441.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 69451.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 69461.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 69471.106Skamil#endif 69481.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 69491.106Skamil#if defined(TWAIT_HAVE_PID) 69501.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 69511.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 69521.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 69531.106Skamil#endif 69541.106Skamil 69551.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 69561.106Skamil#if defined(TWAIT_HAVE_PID) 69571.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 69581.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 69591.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 69601.106Skamil#endif 69611.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 69621.106Skamil#if defined(TWAIT_HAVE_PID) 69631.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 69641.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 69651.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 69661.106Skamil#endif 69671.106Skamil 69681.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 69691.106Skamil#if defined(TWAIT_HAVE_PID) 69701.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 69711.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 69721.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 69731.106Skamil#endif 69741.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 69751.106Skamil#if defined(TWAIT_HAVE_PID) 69761.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 69771.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 69781.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 69791.106Skamil#endif 69801.106Skamil 69811.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 69821.106Skamil#if defined(TWAIT_HAVE_PID) 69831.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 69841.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 69851.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 69861.106Skamil#endif 69871.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 69881.106Skamil#if defined(TWAIT_HAVE_PID) 69891.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 69901.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 69911.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 69921.106Skamil#endif 69931.106Skamil 69941.110Skamil#if TEST_VFORK_ENABLED 69951.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 69961.106Skamil#if defined(TWAIT_HAVE_PID) 69971.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 69981.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 69991.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 70001.106Skamil#endif 70011.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 70021.106Skamil#if defined(TWAIT_HAVE_PID) 70031.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 70041.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 70051.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 70061.106Skamil#endif 70071.110Skamil#endif 70081.106Skamil 70091.106Skamil/// ---------------------------------------------------------------------------- 70101.106Skamil 70111.106Skamil#if defined(TWAIT_HAVE_PID) 70121.103Skamilstatic void 70131.106Skamilclone_body2(int flags, bool masked, bool ignored) 70141.103Skamil{ 70151.103Skamil const int exitval = 5; 70161.103Skamil const int exitval2 = 15; 70171.103Skamil const int sigval = SIGSTOP; 70181.103Skamil pid_t child, child2 = 0, wpid; 70191.103Skamil#if defined(TWAIT_HAVE_STATUS) 70201.103Skamil int status; 70211.103Skamil#endif 70221.103Skamil ptrace_state_t state; 70231.103Skamil const int slen = sizeof(state); 70241.103Skamil ptrace_event_t event; 70251.103Skamil const int elen = sizeof(event); 70261.103Skamil struct sigaction sa; 70271.103Skamil struct ptrace_siginfo info; 70281.103Skamil sigset_t intmask; 70291.103Skamil struct kinfo_proc2 kp; 70301.103Skamil size_t len = sizeof(kp); 70311.103Skamil 70321.103Skamil int name[6]; 70331.103Skamil const size_t namelen = __arraycount(name); 70341.103Skamil ki_sigset_t kp_sigmask; 70351.103Skamil ki_sigset_t kp_sigignore; 70361.103Skamil 70371.103Skamil const size_t stack_size = 1024 * 1024; 70381.103Skamil void *stack, *stack_base; 70391.103Skamil 70401.103Skamil stack = malloc(stack_size); 70411.103Skamil ATF_REQUIRE(stack != NULL); 70421.103Skamil 70431.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 70441.103Skamil stack_base = stack; 70451.103Skamil#else 70461.103Skamil stack_base = (char *)stack + stack_size; 70471.103Skamil#endif 70481.103Skamil 70491.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70501.103Skamil if (child == 0) { 70511.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70521.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70531.103Skamil 70541.103Skamil if (masked) { 70551.103Skamil sigemptyset(&intmask); 70561.103Skamil sigaddset(&intmask, SIGTRAP); 70571.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 70581.103Skamil } 70591.103Skamil 70601.103Skamil if (ignored) { 70611.103Skamil memset(&sa, 0, sizeof(sa)); 70621.103Skamil sa.sa_handler = SIG_IGN; 70631.103Skamil sigemptyset(&sa.sa_mask); 70641.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 70651.103Skamil } 70661.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70671.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 70681.103Skamil 70691.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 70701.103Skamil flags); 70711.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 70721.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 70731.103Skamil 70741.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 70751.103Skamil child2); 70761.103Skamil 70771.103Skamil // XXX WALLSIG? 70781.103Skamil FORKEE_REQUIRE_SUCCESS 70791.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 70801.103Skamil 70811.103Skamil forkee_status_exited(status, exitval2); 70821.103Skamil 70831.103Skamil DPRINTF("Before exiting of the child process\n"); 70841.103Skamil _exit(exitval); 70851.103Skamil } 70861.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 70871.103Skamil 70881.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 70891.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70901.103Skamil 70911.103Skamil validate_status_stopped(status, sigval); 70921.103Skamil 70931.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 70941.103Skamil SYSCALL_REQUIRE( 70951.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 70961.103Skamil 70971.103Skamil DPRINTF("Before checking siginfo_t\n"); 70981.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 70991.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71001.103Skamil 71011.103Skamil name[0] = CTL_KERN, 71021.103Skamil name[1] = KERN_PROC2, 71031.103Skamil name[2] = KERN_PROC_PID; 71041.103Skamil name[3] = child; 71051.103Skamil name[4] = sizeof(kp); 71061.103Skamil name[5] = 1; 71071.103Skamil 71081.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71091.103Skamil 71101.103Skamil if (masked) 71111.103Skamil kp_sigmask = kp.p_sigmask; 71121.103Skamil 71131.103Skamil if (ignored) 71141.103Skamil kp_sigignore = kp.p_sigignore; 71151.103Skamil 71161.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 71171.103Skamil "EVENT_MASK for the child %d\n", child); 71181.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 71191.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 71201.103Skamil 71211.103Skamil DPRINTF("Before resuming the child process where it left off and " 71221.103Skamil "without signal to be sent\n"); 71231.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71241.103Skamil 71251.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 71261.103Skamil child); 71271.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71281.103Skamil child); 71291.103Skamil 71301.103Skamil validate_status_stopped(status, SIGTRAP); 71311.103Skamil 71321.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71331.103Skamil 71341.103Skamil if (masked) { 71351.103Skamil DPRINTF("kp_sigmask=" 71361.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71371.103Skamil PRIx32 "\n", 71381.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71391.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71401.103Skamil 71411.103Skamil DPRINTF("kp.p_sigmask=" 71421.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71431.103Skamil PRIx32 "\n", 71441.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 71451.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 71461.103Skamil 71471.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 71481.103Skamil sizeof(kp_sigmask))); 71491.103Skamil } 71501.103Skamil 71511.103Skamil if (ignored) { 71521.103Skamil DPRINTF("kp_sigignore=" 71531.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71541.103Skamil PRIx32 "\n", 71551.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71561.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71571.103Skamil 71581.103Skamil DPRINTF("kp.p_sigignore=" 71591.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71601.103Skamil PRIx32 "\n", 71611.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 71621.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 71631.103Skamil 71641.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 71651.103Skamil sizeof(kp_sigignore))); 71661.103Skamil } 71671.103Skamil 71681.103Skamil SYSCALL_REQUIRE( 71691.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71701.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 71711.103Skamil child2); 71721.103Skamil if (!(flags & CLONE_VFORK)) { 71731.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 71741.103Skamil PTRACE_FORK); 71751.103Skamil } else { 71761.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 71771.103Skamil PTRACE_VFORK); 71781.103Skamil } 71791.103Skamil 71801.103Skamil child2 = state.pe_other_pid; 71811.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 71821.103Skamil 71831.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 71841.103Skamil "%d\n", TWAIT_FNAME, child2, child); 71851.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 71861.103Skamil child2); 71871.103Skamil 71881.103Skamil validate_status_stopped(status, SIGTRAP); 71891.103Skamil 71901.103Skamil name[3] = child2; 71911.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71921.103Skamil 71931.103Skamil if (masked) { 71941.103Skamil DPRINTF("kp_sigmask=" 71951.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71961.103Skamil PRIx32 "\n", 71971.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71981.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71991.103Skamil 72001.103Skamil DPRINTF("kp.p_sigmask=" 72011.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72021.103Skamil PRIx32 "\n", 72031.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72041.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72051.103Skamil 72061.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72071.103Skamil sizeof(kp_sigmask))); 72081.103Skamil } 72091.103Skamil 72101.103Skamil if (ignored) { 72111.103Skamil DPRINTF("kp_sigignore=" 72121.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72131.103Skamil PRIx32 "\n", 72141.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72151.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72161.103Skamil 72171.103Skamil DPRINTF("kp.p_sigignore=" 72181.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72191.103Skamil PRIx32 "\n", 72201.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72211.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72221.103Skamil 72231.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72241.103Skamil sizeof(kp_sigignore))); 72251.103Skamil } 72261.103Skamil 72271.103Skamil SYSCALL_REQUIRE( 72281.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 72291.103Skamil if (!(flags & CLONE_VFORK)) { 72301.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72311.103Skamil PTRACE_FORK); 72321.103Skamil } else { 72331.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72341.103Skamil PTRACE_VFORK); 72351.103Skamil } 72361.103Skamil 72371.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 72381.103Skamil 72391.103Skamil DPRINTF("Before resuming the forkee process where it left off " 72401.103Skamil "and without signal to be sent\n"); 72411.103Skamil SYSCALL_REQUIRE( 72421.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 72431.103Skamil 72441.103Skamil DPRINTF("Before resuming the child process where it left off " 72451.103Skamil "and without signal to be sent\n"); 72461.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72471.103Skamil 72481.103Skamil if (flags & CLONE_VFORK) { 72491.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72501.103Skamil child); 72511.103Skamil TWAIT_REQUIRE_SUCCESS( 72521.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 72531.103Skamil 72541.103Skamil validate_status_stopped(status, SIGTRAP); 72551.103Skamil 72561.103Skamil name[3] = child; 72571.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72581.103Skamil 72591.103Skamil /* 72601.103Skamil * SIGCHLD is now pending in the signal queue and 72611.103Skamil * the kernel presents it to userland as a masked signal. 72621.103Skamil */ 72631.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 72641.103Skamil 72651.103Skamil if (masked) { 72661.103Skamil DPRINTF("kp_sigmask=" 72671.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72681.103Skamil PRIx32 "\n", 72691.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72701.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72711.103Skamil 72721.103Skamil DPRINTF("kp.p_sigmask=" 72731.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72741.103Skamil PRIx32 "\n", 72751.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72761.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72771.103Skamil 72781.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72791.103Skamil sizeof(kp_sigmask))); 72801.103Skamil } 72811.103Skamil 72821.103Skamil if (ignored) { 72831.103Skamil DPRINTF("kp_sigignore=" 72841.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72851.103Skamil PRIx32 "\n", 72861.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72871.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72881.103Skamil 72891.103Skamil DPRINTF("kp.p_sigignore=" 72901.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72911.103Skamil PRIx32 "\n", 72921.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72931.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72941.103Skamil 72951.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72961.103Skamil sizeof(kp_sigignore))); 72971.103Skamil } 72981.103Skamil 72991.103Skamil SYSCALL_REQUIRE( 73001.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 73011.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 73021.103Skamil 73031.103Skamil child2 = state.pe_other_pid; 73041.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 73051.103Skamil child2); 73061.103Skamil 73071.103Skamil DPRINTF("Before resuming the child process where it left off " 73081.103Skamil "and without signal to be sent\n"); 73091.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73101.103Skamil } 73111.103Skamil 73121.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 73131.103Skamil "\n", TWAIT_FNAME); 73141.103Skamil TWAIT_REQUIRE_SUCCESS( 73151.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 73161.103Skamil 73171.103Skamil validate_status_exited(status, exitval2); 73181.103Skamil 73191.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 73201.103Skamil "process\n", TWAIT_FNAME); 73211.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 73221.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 73231.103Skamil 73241.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 73251.103Skamil "SIGCHLD\n", TWAIT_FNAME); 73261.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73271.103Skamil 73281.103Skamil validate_status_stopped(status, SIGCHLD); 73291.103Skamil 73301.103Skamil DPRINTF("Before resuming the child process where it left off and " 73311.103Skamil "without signal to be sent\n"); 73321.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73331.103Skamil 73341.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 73351.103Skamil TWAIT_FNAME); 73361.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73371.103Skamil 73381.103Skamil validate_status_exited(status, exitval); 73391.103Skamil 73401.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 73411.103Skamil TWAIT_FNAME); 73421.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 73431.103Skamil} 73441.103Skamil 73451.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 73461.103SkamilATF_TC(name); \ 73471.103SkamilATF_TC_HEAD(name, tc) \ 73481.103Skamil{ \ 73491.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 73501.103Skamil " regardless of signal %s%s", \ 73511.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 73521.103Skamil} \ 73531.103Skamil \ 73541.103SkamilATF_TC_BODY(name, tc) \ 73551.103Skamil{ \ 73561.103Skamil \ 73571.106Skamil clone_body2(flags, masked, ignored); \ 73581.103Skamil} 73591.103Skamil 73601.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 73611.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 73621.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 73631.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 73641.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 73651.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 73661.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 73671.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 73681.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 73691.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 73701.110Skamil#if TEST_VFORK_ENABLED 73711.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 73721.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 73731.103Skamil#endif 73741.110Skamil#endif 73751.103Skamil 73761.103Skamil/// ---------------------------------------------------------------------------- 73771.103Skamil 73781.111Skamil#if TEST_VFORK_ENABLED 73791.107Skamil#if defined(TWAIT_HAVE_PID) 73801.107Skamilstatic void 73811.107Skamiltraceme_vfork_clone_body(int flags) 73821.107Skamil{ 73831.107Skamil const int exitval = 5; 73841.107Skamil const int exitval2 = 15; 73851.107Skamil pid_t child, child2 = 0, wpid; 73861.107Skamil#if defined(TWAIT_HAVE_STATUS) 73871.107Skamil int status; 73881.107Skamil#endif 73891.107Skamil 73901.107Skamil const size_t stack_size = 1024 * 1024; 73911.107Skamil void *stack, *stack_base; 73921.107Skamil 73931.107Skamil stack = malloc(stack_size); 73941.107Skamil ATF_REQUIRE(stack != NULL); 73951.107Skamil 73961.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 73971.107Skamil stack_base = stack; 73981.107Skamil#else 73991.107Skamil stack_base = (char *)stack + stack_size; 74001.107Skamil#endif 74011.107Skamil 74021.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 74031.107Skamil if (child == 0) { 74041.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74051.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74061.107Skamil 74071.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 74081.107Skamil flags); 74091.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 74101.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 74111.107Skamil 74121.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 74131.107Skamil child2); 74141.107Skamil 74151.107Skamil // XXX WALLSIG? 74161.107Skamil FORKEE_REQUIRE_SUCCESS 74171.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 74181.107Skamil 74191.107Skamil forkee_status_exited(status, exitval2); 74201.107Skamil 74211.107Skamil DPRINTF("Before exiting of the child process\n"); 74221.107Skamil _exit(exitval); 74231.107Skamil } 74241.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74251.107Skamil 74261.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74271.107Skamil TWAIT_FNAME); 74281.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74291.107Skamil 74301.107Skamil validate_status_exited(status, exitval); 74311.107Skamil 74321.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74331.107Skamil TWAIT_FNAME); 74341.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74351.107Skamil} 74361.107Skamil 74371.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 74381.107SkamilATF_TC(name); \ 74391.107SkamilATF_TC_HEAD(name, tc) \ 74401.107Skamil{ \ 74411.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 74421.107Skamil "handled correctly with vfork(2)ed tracer", \ 74431.107Skamil #flags); \ 74441.107Skamil} \ 74451.107Skamil \ 74461.107SkamilATF_TC_BODY(name, tc) \ 74471.107Skamil{ \ 74481.107Skamil \ 74491.107Skamil traceme_vfork_clone_body(flags); \ 74501.107Skamil} 74511.107Skamil 74521.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 74531.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 74541.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 74551.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 74561.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 74571.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 74581.107Skamil#endif 74591.110Skamil#endif 74601.107Skamil 74611.107Skamil/// ---------------------------------------------------------------------------- 74621.107Skamil 74631.122Skamilstatic void 74641.122Skamiluser_va0_disable(int operation) 74651.122Skamil{ 74661.122Skamil pid_t child, wpid; 74671.122Skamil#if defined(TWAIT_HAVE_STATUS) 74681.122Skamil int status; 74691.122Skamil#endif 74701.122Skamil const int sigval = SIGSTOP; 74711.122Skamil int rv; 74721.122Skamil 74731.122Skamil struct ptrace_siginfo info; 74741.122Skamil 74751.122Skamil if (get_user_va0_disable() == 0) 74761.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 74771.122Skamil 74781.122Skamil memset(&info, 0, sizeof(info)); 74791.122Skamil 74801.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 74811.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 74821.122Skamil if (child == 0) { 74831.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74841.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74851.122Skamil 74861.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 74871.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 74881.122Skamil 74891.122Skamil /* NOTREACHED */ 74901.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 74911.122Skamil __unreachable(); 74921.122Skamil } 74931.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74941.122Skamil 74951.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74961.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74971.122Skamil 74981.122Skamil validate_status_stopped(status, sigval); 74991.122Skamil 75001.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 75011.122Skamil "child\n"); 75021.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 75031.122Skamil sizeof(info)) != -1); 75041.122Skamil 75051.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 75061.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 75071.122Skamil "si_errno=%#x\n", 75081.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 75091.122Skamil info.psi_siginfo.si_errno); 75101.122Skamil 75111.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 75121.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 75131.122Skamil 75141.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 75151.122Skamil "and without signal to be sent\n"); 75161.122Skamil errno = 0; 75171.122Skamil rv = ptrace(operation, child, (void *)0, 0); 75181.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 75191.122Skamil ATF_REQUIRE_EQ(rv, -1); 75201.122Skamil 75211.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 75221.122Skamil 75231.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75241.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75251.122Skamil validate_status_signaled(status, SIGKILL, 0); 75261.122Skamil 75271.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75281.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75291.122Skamil} 75301.122Skamil 75311.122Skamil#define USER_VA0_DISABLE(test, operation) \ 75321.122SkamilATF_TC(test); \ 75331.122SkamilATF_TC_HEAD(test, tc) \ 75341.122Skamil{ \ 75351.122Skamil atf_tc_set_md_var(tc, "descr", \ 75361.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 75371.122Skamil} \ 75381.122Skamil \ 75391.122SkamilATF_TC_BODY(test, tc) \ 75401.122Skamil{ \ 75411.122Skamil \ 75421.122Skamil user_va0_disable(operation); \ 75431.122Skamil} 75441.122Skamil 75451.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 75461.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 75471.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 75481.122Skamil 75491.122Skamil/// ---------------------------------------------------------------------------- 75501.122Skamil 75511.130Smgorny/* 75521.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 75531.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 75541.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 75551.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 75561.130Smgorny * found, -1 is returned. 75571.130Smgorny */ 75581.130Smgornystatic ssize_t core_find_note(const char *core_path, 75591.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 75601.130Smgorny{ 75611.130Smgorny int core_fd; 75621.130Smgorny Elf *core_elf; 75631.130Smgorny size_t core_numhdr, i; 75641.130Smgorny ssize_t ret = -1; 75651.130Smgorny /* note: we assume note name will be null-terminated */ 75661.130Smgorny size_t name_len = strlen(note_name) + 1; 75671.130Smgorny 75681.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 75691.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 75701.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 75711.130Smgorny 75721.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 75731.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 75741.130Smgorny GElf_Phdr core_hdr; 75751.130Smgorny size_t offset; 75761.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 75771.130Smgorny if (core_hdr.p_type != PT_NOTE) 75781.130Smgorny continue; 75791.130Smgorny 75801.130Smgorny for (offset = core_hdr.p_offset; 75811.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 75821.130Smgorny Elf64_Nhdr note_hdr; 75831.130Smgorny char name_buf[64]; 75841.130Smgorny 75851.130Smgorny switch (gelf_getclass(core_elf)) { 75861.130Smgorny case ELFCLASS64: 75871.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 75881.130Smgorny sizeof(note_hdr), offset) 75891.130Smgorny == sizeof(note_hdr)); 75901.130Smgorny offset += sizeof(note_hdr); 75911.130Smgorny break; 75921.130Smgorny case ELFCLASS32: 75931.130Smgorny { 75941.130Smgorny Elf32_Nhdr tmp_hdr; 75951.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 75961.130Smgorny sizeof(tmp_hdr), offset) 75971.130Smgorny == sizeof(tmp_hdr)); 75981.130Smgorny offset += sizeof(tmp_hdr); 75991.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 76001.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 76011.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 76021.130Smgorny } 76031.130Smgorny break; 76041.130Smgorny } 76051.130Smgorny 76061.130Smgorny /* indicates end of notes */ 76071.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 76081.130Smgorny break; 76091.130Smgorny if (note_hdr.n_namesz == name_len && 76101.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 76111.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 76121.130Smgorny note_hdr.n_namesz, offset) 76131.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 76141.130Smgorny 76151.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 76161.130Smgorny note_hdr.n_type == note_type) 76171.130Smgorny ret = note_hdr.n_descsz; 76181.130Smgorny } 76191.130Smgorny 76201.130Smgorny offset += note_hdr.n_namesz; 76211.130Smgorny /* fix to alignment */ 76221.130Smgorny offset = ((offset + core_hdr.p_align - 1) 76231.130Smgorny / core_hdr.p_align) * core_hdr.p_align; 76241.130Smgorny 76251.130Smgorny /* if name & type matched above */ 76261.130Smgorny if (ret != -1) { 76271.130Smgorny ssize_t read_len = MIN(buf_len, 76281.130Smgorny note_hdr.n_descsz); 76291.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 76301.130Smgorny read_len, offset) == read_len); 76311.130Smgorny break; 76321.130Smgorny } 76331.130Smgorny 76341.130Smgorny offset += note_hdr.n_descsz; 76351.130Smgorny } 76361.130Smgorny } 76371.130Smgorny 76381.130Smgorny elf_end(core_elf); 76391.130Smgorny close(core_fd); 76401.130Smgorny 76411.130Smgorny return ret; 76421.130Smgorny} 76431.130Smgorny 76441.130SmgornyATF_TC(core_dump_procinfo); 76451.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 76461.130Smgorny{ 76471.130Smgorny atf_tc_set_md_var(tc, "descr", 76481.130Smgorny "Trigger a core dump and verify its contents."); 76491.130Smgorny} 76501.130Smgorny 76511.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 76521.130Smgorny{ 76531.130Smgorny const int exitval = 5; 76541.130Smgorny pid_t child, wpid; 76551.130Smgorny#if defined(TWAIT_HAVE_STATUS) 76561.130Smgorny const int sigval = SIGTRAP; 76571.130Smgorny int status; 76581.130Smgorny#endif 76591.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 76601.130Smgorny int core_fd; 76611.130Smgorny struct netbsd_elfcore_procinfo procinfo; 76621.130Smgorny 76631.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 76641.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 76651.130Smgorny if (child == 0) { 76661.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 76671.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 76681.130Smgorny 76691.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 76701.130Smgorny trigger_trap(); 76711.130Smgorny 76721.130Smgorny DPRINTF("Before exiting of the child process\n"); 76731.130Smgorny _exit(exitval); 76741.130Smgorny } 76751.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 76761.130Smgorny 76771.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76781.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76791.130Smgorny 76801.130Smgorny validate_status_stopped(status, sigval); 76811.130Smgorny 76821.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 76831.130Smgorny close(core_fd); 76841.130Smgorny 76851.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 76861.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 76871.130Smgorny != -1); 76881.130Smgorny 76891.130Smgorny DPRINTF("Read core file\n"); 76901.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 76911.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 76921.130Smgorny sizeof(procinfo)); 76931.130Smgorny 76941.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 76951.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 76961.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 76971.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 76981.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 76991.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 77001.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 77011.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 77021.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 77031.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 77041.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 77051.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 77061.130Smgorny ATF_CHECK_EQ(procinfo.cpi_siglwp, 1); 77071.130Smgorny 77081.130Smgorny unlink(core_path); 77091.130Smgorny 77101.130Smgorny DPRINTF("Before resuming the child process where it left off and " 77111.130Smgorny "without signal to be sent\n"); 77121.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 77131.130Smgorny 77141.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77151.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77161.130Smgorny 77171.130Smgorny validate_status_exited(status, exitval); 77181.130Smgorny 77191.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77201.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 77211.130Smgorny} 77221.130Smgorny 77231.130Smgorny/// ---------------------------------------------------------------------------- 77241.130Smgorny 77251.1Skamil#include "t_ptrace_amd64_wait.h" 77261.1Skamil#include "t_ptrace_i386_wait.h" 77271.1Skamil#include "t_ptrace_x86_wait.h" 77281.1Skamil 77291.1SkamilATF_TP_ADD_TCS(tp) 77301.1Skamil{ 77311.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 77321.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 77331.33Skamil 77341.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 77351.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 77361.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 77371.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 77381.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 77391.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 77401.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 77411.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 77421.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 77431.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 77441.33Skamil 77451.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 77461.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 77471.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 77481.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 77491.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 77501.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 77511.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 77521.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 77531.87Skamil 77541.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 77551.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 77561.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 77571.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 77581.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 77591.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 77601.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 77611.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 77621.86Skamil 77631.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 77641.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 77651.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 77661.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 77671.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 77681.59Skamil 77691.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 77701.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 77711.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 77721.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 77731.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 77741.88Skamil 77751.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 77761.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 77771.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 77781.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 77791.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 77801.88Skamil 77811.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 77821.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 77831.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 77841.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 77851.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 77861.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 77871.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 77881.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 77891.50Skamil 77901.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 77911.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 77921.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 77931.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 77941.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 77951.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 77961.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 77971.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 77981.50Skamil 77991.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 78001.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 78011.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 78021.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 78031.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 78041.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 78051.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 78061.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 78071.50Skamil 78081.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 78091.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 78101.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 78111.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 78121.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 78131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 78141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 78151.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 78161.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 78171.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 78181.1Skamil 78191.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 78201.37Skamil 78211.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 78221.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 78231.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 78241.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 78251.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 78261.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 78271.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 78281.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 78291.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 78301.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 78311.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 78321.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 78331.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 78341.40Skamil 78351.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 78361.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 78371.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 78381.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 78391.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 78401.41Skamil 78411.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 78421.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 78431.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 78441.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 78451.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 78461.92Skamil 78471.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 78481.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 78491.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 78501.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 78511.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 78521.92Skamil 78531.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 78541.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 78551.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 78561.43Skamil 78571.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 78581.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 78591.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 78601.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 78611.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 78621.59Skamil 78631.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78641.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 78651.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78661.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 78671.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78681.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 78691.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78701.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 78711.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78721.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 78731.94Skamil 78741.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78751.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 78761.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78771.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 78781.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78791.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 78801.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78811.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 78821.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78831.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 78841.94Skamil 78851.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 78861.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 78871.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 78881.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 78891.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 78901.51Skamil 78911.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 78921.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 78931.51Skamil 78941.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 78951.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 78961.51Skamil 78971.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78981.51Skamil tracee_sees_its_original_parent_getppid); 78991.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79001.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 79011.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79021.51Skamil tracee_sees_its_original_parent_procfs_status); 79031.1Skamil 79041.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 79051.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 79061.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 79071.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 79081.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 79091.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 79101.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 79111.1Skamil 79121.31Skamil ATF_TP_ADD_TC(tp, fork1); 79131.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 79141.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 79151.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 79161.31Skamil ATF_TP_ADD_TC(tp, fork5); 79171.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 79181.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 79191.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 79201.125Skamil ATF_TP_ADD_TC(tp, fork9); 79211.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 79221.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 79231.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 79241.125Skamil ATF_TP_ADD_TC(tp, fork13); 79251.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 79261.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 79271.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 79281.31Skamil 79291.109Skamil#if TEST_VFORK_ENABLED 79301.31Skamil ATF_TP_ADD_TC(tp, vfork1); 79311.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 79321.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 79331.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 79341.31Skamil ATF_TP_ADD_TC(tp, vfork5); 79351.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 79361.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 79371.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 79381.125Skamil ATF_TP_ADD_TC(tp, vfork9); 79391.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 79401.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 79411.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 79421.125Skamil ATF_TP_ADD_TC(tp, vfork13); 79431.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 79441.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 79451.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 79461.116Skamil#endif 79471.1Skamil 79481.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 79491.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 79501.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 79511.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 79521.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 79531.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 79541.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 79551.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 79561.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 79571.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 79581.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 79591.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 79601.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 79611.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 79621.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 79631.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 79641.124Skamil 79651.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 79661.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 79671.116Skamil#if TEST_VFORK_ENABLED 79681.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 79691.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 79701.116Skamil#endif 79711.126Skamil 79721.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 79731.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 79741.116Skamil#if TEST_VFORK_ENABLED 79751.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 79761.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 79771.116Skamil#endif 79781.116Skamil 79791.116Skamil#if TEST_VFORK_ENABLED 79801.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 79811.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 79821.109Skamil#endif 79831.108Skamil 79841.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 79851.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 79861.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 79871.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 79881.54Skamil 79891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 79901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 79911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 79921.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 79931.54Skamil 79941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 79951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 79961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 79971.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 79981.54Skamil 79991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 80001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 80011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 80021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 80031.54Skamil 80041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 80051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 80061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 80071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 80081.54Skamil 80091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 80101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 80111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 80121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 80131.54Skamil 80141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 80151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 80161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 80171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 80181.54Skamil 80191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 80201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 80211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 80221.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 80231.54Skamil 80241.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 80251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 80261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 80271.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 80281.54Skamil 80291.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 80301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 80311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 80321.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 80331.1Skamil 80341.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 80351.1Skamil 80361.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 80371.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 80381.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 80391.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 80401.101Skamil 80411.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 80421.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 80431.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 80441.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 80451.101Skamil 80461.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 80471.101Skamil 80481.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 80491.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 80501.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 80511.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 80521.115Skamil 80531.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 80541.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 80551.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 80561.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 80571.115Skamil 80581.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 80591.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 80601.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 80611.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 80621.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 80631.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 80641.1Skamil 80651.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 80661.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 80671.1Skamil 80681.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 80691.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 80701.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 80711.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 80721.1Skamil 80731.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 80741.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 80751.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 80761.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 80771.2Skamil 80781.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 80791.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 80801.95Skamil 80811.1Skamil ATF_TP_ADD_TC(tp, kill1); 80821.1Skamil ATF_TP_ADD_TC(tp, kill2); 80831.75Skamil ATF_TP_ADD_TC(tp, kill3); 80841.1Skamil 80851.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 80861.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 80871.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 80881.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 80891.77Skamil 80901.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 80911.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 80921.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 80931.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 80941.1Skamil 80951.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 80961.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 80971.79Skamil 80981.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 80991.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 81001.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 81011.1Skamil 81021.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 81031.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 81041.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 81051.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 81061.1Skamil 81071.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 81081.84Skamil 81091.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 81101.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 81111.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 81121.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 81131.109Skamil#if TEST_VFORK_ENABLED 81141.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 81151.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 81161.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 81171.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 81181.109Skamil#endif 81191.99Skamil 81201.1Skamil ATF_TP_ADD_TC(tp, signal9); 81211.1Skamil ATF_TP_ADD_TC(tp, signal10); 81221.1Skamil 81231.1Skamil ATF_TP_ADD_TC(tp, suspend2); 81241.1Skamil 81251.1Skamil ATF_TP_ADD_TC(tp, resume1); 81261.1Skamil 81271.1Skamil ATF_TP_ADD_TC(tp, syscall1); 81281.1Skamil 81291.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 81301.1Skamil 81311.106Skamil ATF_TP_ADD_TC(tp, clone1); 81321.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 81331.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 81341.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 81351.106Skamil ATF_TP_ADD_TC(tp, clone5); 81361.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 81371.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 81381.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 81391.106Skamil 81401.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 81411.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 81421.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 81431.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 81441.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 81451.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 81461.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 81471.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 81481.106Skamil 81491.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 81501.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 81511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 81521.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 81531.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 81541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 81551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 81561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 81571.106Skamil 81581.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 81591.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 81601.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 81611.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 81621.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 81631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 81641.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 81651.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 81661.106Skamil 81671.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 81681.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 81691.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 81701.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 81711.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 81721.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 81731.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 81741.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 81751.106Skamil 81761.109Skamil#if TEST_VFORK_ENABLED 81771.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 81781.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 81791.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 81801.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 81811.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 81821.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 81831.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 81841.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 81851.109Skamil#endif 81861.106Skamil 81871.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 81881.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 81891.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 81901.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 81911.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 81921.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 81931.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 81941.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 81951.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 81961.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 81971.109Skamil#if TEST_VFORK_ENABLED 81981.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 81991.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 82001.109Skamil#endif 82011.103Skamil 82021.109Skamil#if TEST_VFORK_ENABLED 82031.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 82041.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 82051.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 82061.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 82071.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 82081.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 82091.109Skamil#endif 82101.107Skamil 82111.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 82121.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 82131.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 82141.122Skamil 82151.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 82161.130Smgorny 82171.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 82181.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 82191.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 82201.1Skamil 82211.1Skamil return atf_no_error(); 82221.1Skamil} 8223