t_ptrace_wait.c revision 1.129
11.129Smgorny/* $NetBSD: t_ptrace_wait.c,v 1.129 2019/06/26 12:30:13 mgorny 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.129Smgorny__RCSID("$NetBSD: t_ptrace_wait.c,v 1.129 2019/06/26 12:30:13 mgorny Exp $"); 311.1Skamil 321.1Skamil#include <sys/param.h> 331.1Skamil#include <sys/types.h> 341.39Skamil#include <sys/mman.h> 351.1Skamil#include <sys/ptrace.h> 361.1Skamil#include <sys/resource.h> 371.1Skamil#include <sys/stat.h> 381.1Skamil#include <sys/syscall.h> 391.1Skamil#include <sys/sysctl.h> 401.129Smgorny#include <sys/uio.h> 411.1Skamil#include <sys/wait.h> 421.1Skamil#include <machine/reg.h> 431.1Skamil#include <elf.h> 441.1Skamil#include <err.h> 451.1Skamil#include <errno.h> 461.1Skamil#include <lwp.h> 471.77Skamil#include <pthread.h> 481.1Skamil#include <sched.h> 491.1Skamil#include <signal.h> 501.124Skamil#include <spawn.h> 511.1Skamil#include <stdint.h> 521.1Skamil#include <stdio.h> 531.1Skamil#include <stdlib.h> 541.1Skamil#include <strings.h> 551.26Skamil#include <time.h> 561.1Skamil#include <unistd.h> 571.1Skamil 581.114Skamil#include <fenv.h> 591.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 601.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 611.114Skamil#endif 621.114Skamil 631.121Smgorny#if defined(__i386__) || defined(__x86_64__) 641.121Smgorny#include <cpuid.h> 651.121Smgorny#include <x86/cpu_extended_state.h> 661.129Smgorny#include <x86/specialreg.h> 671.121Smgorny#endif 681.121Smgorny 691.1Skamil#include <atf-c.h> 701.1Skamil 711.1Skamil#include "h_macros.h" 721.1Skamil 731.1Skamil#include "t_ptrace_wait.h" 741.1Skamil#include "msg.h" 751.1Skamil 761.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 771.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 781.61Skre sizeof(msg)) == 0) 791.1Skamil 801.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 811.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 821.61Skre sizeof(msg)) == 0) 831.1Skamil 841.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 851.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 861.61Skre sizeof(msg)) == 0) 871.1Skamil 881.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 891.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 901.61Skre sizeof(msg)) == 0) 911.13Schristos 921.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 931.13Schristos strerror(errno)) 941.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 951.18Schristos "%d(%s) != %d", res, strerror(res), exp) 961.13Schristos 971.13Schristosstatic int debug = 0; 981.13Schristos 991.13Schristos#define DPRINTF(a, ...) do \ 1001.123Skamil if (debug) \ 1011.123Skamil printf("%s() %s:%d " a, __func__, __FILE__, __LINE__, ##__VA_ARGS__); \ 1021.13Schristos while (/*CONSTCOND*/0) 1031.1Skamil 1041.110Skamil#ifndef TEST_VFORK_ENABLED 1051.127Skamil#define TEST_VFORK_ENABLED 1 1061.110Skamil#endif 1071.109Skamil 1081.128Skamil#ifndef TEST_LWP_ENABLED 1091.128Skamil#define TEST_LWP_ENABLED 0 1101.128Skamil#endif 1111.128Skamil 1121.34Skamil/// ---------------------------------------------------------------------------- 1131.34Skamil 1141.33Skamilstatic void 1151.33Skamiltraceme_raise(int sigval) 1161.1Skamil{ 1171.1Skamil const int exitval = 5; 1181.1Skamil pid_t child, wpid; 1191.1Skamil#if defined(TWAIT_HAVE_STATUS) 1201.1Skamil int status; 1211.1Skamil#endif 1221.1Skamil 1231.45Skamil struct ptrace_siginfo info; 1241.45Skamil memset(&info, 0, sizeof(info)); 1251.45Skamil 1261.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1271.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1281.1Skamil if (child == 0) { 1291.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1301.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1311.1Skamil 1321.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1331.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1341.1Skamil 1351.36Skamil switch (sigval) { 1361.36Skamil case SIGKILL: 1371.36Skamil /* NOTREACHED */ 1381.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1391.70Smrg __unreachable(); 1401.36Skamil default: 1411.36Skamil DPRINTF("Before exiting of the child process\n"); 1421.36Skamil _exit(exitval); 1431.36Skamil } 1441.1Skamil } 1451.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1461.1Skamil 1471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1491.1Skamil 1501.36Skamil switch (sigval) { 1511.36Skamil case SIGKILL: 1521.36Skamil validate_status_signaled(status, sigval, 0); 1531.36Skamil break; 1541.36Skamil default: 1551.36Skamil validate_status_stopped(status, sigval); 1561.1Skamil 1571.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1581.61Skre "child\n"); 1591.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1601.61Skre sizeof(info)) != -1); 1611.45Skamil 1621.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1631.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1641.61Skre "si_errno=%#x\n", 1651.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1661.61Skre info.psi_siginfo.si_errno); 1671.45Skamil 1681.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1691.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1701.45Skamil 1711.36Skamil DPRINTF("Before resuming the child process where it left off " 1721.36Skamil "and without signal to be sent\n"); 1731.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1741.1Skamil 1751.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1761.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1771.61Skre child); 1781.36Skamil break; 1791.36Skamil } 1801.1Skamil 1811.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1821.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1831.1Skamil} 1841.1Skamil 1851.61Skre#define TRACEME_RAISE(test, sig) \ 1861.61SkreATF_TC(test); \ 1871.61SkreATF_TC_HEAD(test, tc) \ 1881.61Skre{ \ 1891.61Skre atf_tc_set_md_var(tc, "descr", \ 1901.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1911.61Skre} \ 1921.61Skre \ 1931.61SkreATF_TC_BODY(test, tc) \ 1941.61Skre{ \ 1951.61Skre \ 1961.61Skre traceme_raise(sig); \ 1971.33Skamil} 1981.33Skamil 1991.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2001.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2011.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2021.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2031.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2041.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2051.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2061.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2071.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2081.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2091.33Skamil 2101.34Skamil/// ---------------------------------------------------------------------------- 2111.1Skamil 2121.1Skamilstatic void 2131.87Skamiltraceme_raisesignal_ignored(int sigignored) 2141.87Skamil{ 2151.87Skamil const int exitval = 5; 2161.87Skamil const int sigval = SIGSTOP; 2171.87Skamil pid_t child, wpid; 2181.87Skamil struct sigaction sa; 2191.87Skamil#if defined(TWAIT_HAVE_STATUS) 2201.87Skamil int status; 2211.87Skamil#endif 2221.87Skamil struct ptrace_siginfo info; 2231.87Skamil 2241.87Skamil memset(&info, 0, sizeof(info)); 2251.87Skamil 2261.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2271.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2281.87Skamil if (child == 0) { 2291.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2301.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2311.87Skamil 2321.87Skamil memset(&sa, 0, sizeof(sa)); 2331.87Skamil sa.sa_handler = SIG_IGN; 2341.87Skamil sigemptyset(&sa.sa_mask); 2351.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2361.87Skamil 2371.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2381.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2391.87Skamil 2401.87Skamil DPRINTF("Before raising %s from child\n", 2411.87Skamil strsignal(sigignored)); 2421.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2431.87Skamil 2441.87Skamil DPRINTF("Before exiting of the child process\n"); 2451.87Skamil _exit(exitval); 2461.87Skamil } 2471.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2481.87Skamil 2491.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2501.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2511.87Skamil 2521.87Skamil validate_status_stopped(status, sigval); 2531.87Skamil 2541.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2551.87Skamil SYSCALL_REQUIRE( 2561.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2571.87Skamil 2581.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2591.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2601.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2611.87Skamil info.psi_siginfo.si_errno); 2621.87Skamil 2631.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2641.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2651.87Skamil 2661.87Skamil DPRINTF("Before resuming the child process where it left off and " 2671.87Skamil "without signal to be sent\n"); 2681.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2691.87Skamil 2701.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2711.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2721.87Skamil 2731.87Skamil validate_status_stopped(status, sigignored); 2741.87Skamil 2751.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2761.87Skamil SYSCALL_REQUIRE( 2771.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2781.87Skamil 2791.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2801.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2811.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2821.87Skamil info.psi_siginfo.si_errno); 2831.87Skamil 2841.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2851.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2861.87Skamil 2871.87Skamil DPRINTF("Before resuming the child process where it left off and " 2881.87Skamil "without signal to be sent\n"); 2891.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2901.87Skamil 2911.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2921.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2931.87Skamil 2941.87Skamil validate_status_exited(status, exitval); 2951.87Skamil 2961.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2971.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2981.87Skamil} 2991.87Skamil 3001.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3011.87SkamilATF_TC(test); \ 3021.87SkamilATF_TC_HEAD(test, tc) \ 3031.87Skamil{ \ 3041.87Skamil atf_tc_set_md_var(tc, "descr", \ 3051.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3061.87Skamil "does not stop tracer from catching this raised signal"); \ 3071.87Skamil} \ 3081.87Skamil \ 3091.87SkamilATF_TC_BODY(test, tc) \ 3101.87Skamil{ \ 3111.87Skamil \ 3121.87Skamil traceme_raisesignal_ignored(sig); \ 3131.87Skamil} 3141.87Skamil 3151.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3161.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3171.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3181.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3191.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3201.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3211.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3221.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3231.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3241.87Skamil 3251.87Skamil/// ---------------------------------------------------------------------------- 3261.87Skamil 3271.87Skamilstatic void 3281.86Skamiltraceme_raisesignal_masked(int sigmasked) 3291.86Skamil{ 3301.86Skamil const int exitval = 5; 3311.86Skamil const int sigval = SIGSTOP; 3321.86Skamil pid_t child, wpid; 3331.86Skamil#if defined(TWAIT_HAVE_STATUS) 3341.86Skamil int status; 3351.86Skamil#endif 3361.86Skamil sigset_t intmask; 3371.86Skamil struct ptrace_siginfo info; 3381.86Skamil 3391.86Skamil memset(&info, 0, sizeof(info)); 3401.86Skamil 3411.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3421.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3431.86Skamil if (child == 0) { 3441.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3451.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3461.86Skamil 3471.86Skamil sigemptyset(&intmask); 3481.86Skamil sigaddset(&intmask, sigmasked); 3491.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3501.86Skamil 3511.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3521.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3531.86Skamil 3541.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3551.86Skamil strsignal(sigmasked)); 3561.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3571.86Skamil 3581.86Skamil DPRINTF("Before exiting of the child process\n"); 3591.86Skamil _exit(exitval); 3601.86Skamil } 3611.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3621.86Skamil 3631.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3641.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3651.86Skamil 3661.86Skamil validate_status_stopped(status, sigval); 3671.86Skamil 3681.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3691.86Skamil SYSCALL_REQUIRE( 3701.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3711.86Skamil 3721.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3731.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3741.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3751.86Skamil info.psi_siginfo.si_errno); 3761.86Skamil 3771.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3781.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3791.86Skamil 3801.86Skamil DPRINTF("Before resuming the child process where it left off and " 3811.86Skamil "without signal to be sent\n"); 3821.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3831.86Skamil 3841.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3851.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3861.86Skamil 3871.86Skamil validate_status_exited(status, exitval); 3881.86Skamil 3891.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3901.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3911.86Skamil} 3921.86Skamil 3931.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3941.86SkamilATF_TC(test); \ 3951.86SkamilATF_TC_HEAD(test, tc) \ 3961.86Skamil{ \ 3971.86Skamil atf_tc_set_md_var(tc, "descr", \ 3981.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 3991.86Skamil "stops tracer from catching this raised signal"); \ 4001.86Skamil} \ 4011.86Skamil \ 4021.86SkamilATF_TC_BODY(test, tc) \ 4031.86Skamil{ \ 4041.86Skamil \ 4051.86Skamil traceme_raisesignal_masked(sig); \ 4061.86Skamil} 4071.86Skamil 4081.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4091.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4101.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4111.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4121.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4131.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4141.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4151.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4161.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4171.86Skamil 4181.86Skamil/// ---------------------------------------------------------------------------- 4191.86Skamil 4201.86Skamilstatic void 4211.59Skamiltraceme_crash(int sig) 4221.59Skamil{ 4231.59Skamil pid_t child, wpid; 4241.59Skamil#if defined(TWAIT_HAVE_STATUS) 4251.59Skamil int status; 4261.59Skamil#endif 4271.59Skamil struct ptrace_siginfo info; 4281.61Skre 4291.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4301.71Skamil if (sig == SIGILL) 4311.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4321.71Skamil#endif 4331.71Skamil 4341.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4351.114Skamil atf_tc_skip("FP exceptions are not supported"); 4361.114Skamil 4371.59Skamil memset(&info, 0, sizeof(info)); 4381.59Skamil 4391.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4401.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4411.59Skamil if (child == 0) { 4421.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4431.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4441.59Skamil 4451.59Skamil DPRINTF("Before executing a trap\n"); 4461.59Skamil switch (sig) { 4471.59Skamil case SIGTRAP: 4481.59Skamil trigger_trap(); 4491.59Skamil break; 4501.59Skamil case SIGSEGV: 4511.59Skamil trigger_segv(); 4521.59Skamil break; 4531.59Skamil case SIGILL: 4541.59Skamil trigger_ill(); 4551.59Skamil break; 4561.59Skamil case SIGFPE: 4571.59Skamil trigger_fpe(); 4581.59Skamil break; 4591.59Skamil case SIGBUS: 4601.59Skamil trigger_bus(); 4611.59Skamil break; 4621.59Skamil default: 4631.59Skamil /* NOTREACHED */ 4641.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4651.59Skamil } 4661.59Skamil 4671.59Skamil /* NOTREACHED */ 4681.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4691.59Skamil } 4701.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4711.59Skamil 4721.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4731.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4741.59Skamil 4751.59Skamil validate_status_stopped(status, sig); 4761.59Skamil 4771.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4781.61Skre SYSCALL_REQUIRE( 4791.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4801.59Skamil 4811.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4821.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4831.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4841.61Skre info.psi_siginfo.si_errno); 4851.59Skamil 4861.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4871.59Skamil switch (sig) { 4881.59Skamil case SIGTRAP: 4891.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4901.59Skamil break; 4911.59Skamil case SIGSEGV: 4921.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4931.59Skamil break; 4941.71Skamil case SIGILL: 4951.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 4961.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 4971.71Skamil break; 4981.59Skamil case SIGFPE: 4991.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5001.59Skamil break; 5011.59Skamil case SIGBUS: 5021.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5031.59Skamil break; 5041.59Skamil } 5051.59Skamil 5061.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5071.59Skamil 5081.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5091.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5101.59Skamil 5111.59Skamil validate_status_signaled(status, SIGKILL, 0); 5121.59Skamil 5131.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5141.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5151.59Skamil} 5161.59Skamil 5171.61Skre#define TRACEME_CRASH(test, sig) \ 5181.61SkreATF_TC(test); \ 5191.61SkreATF_TC_HEAD(test, tc) \ 5201.61Skre{ \ 5211.61Skre atf_tc_set_md_var(tc, "descr", \ 5221.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5231.61Skre} \ 5241.61Skre \ 5251.61SkreATF_TC_BODY(test, tc) \ 5261.61Skre{ \ 5271.61Skre \ 5281.61Skre traceme_crash(sig); \ 5291.59Skamil} 5301.59Skamil 5311.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5321.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5331.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5341.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5351.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5361.59Skamil 5371.59Skamil/// ---------------------------------------------------------------------------- 5381.59Skamil 5391.59Skamilstatic void 5401.88Skamiltraceme_signalmasked_crash(int sig) 5411.88Skamil{ 5421.89Skamil const int sigval = SIGSTOP; 5431.88Skamil pid_t child, wpid; 5441.88Skamil#if defined(TWAIT_HAVE_STATUS) 5451.88Skamil int status; 5461.88Skamil#endif 5471.88Skamil struct ptrace_siginfo info; 5481.88Skamil sigset_t intmask; 5491.89Skamil struct kinfo_proc2 kp; 5501.89Skamil size_t len = sizeof(kp); 5511.89Skamil 5521.89Skamil int name[6]; 5531.89Skamil const size_t namelen = __arraycount(name); 5541.89Skamil ki_sigset_t kp_sigmask; 5551.88Skamil 5561.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5571.88Skamil if (sig == SIGILL) 5581.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5591.88Skamil#endif 5601.88Skamil 5611.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5621.114Skamil atf_tc_skip("FP exceptions are not supported"); 5631.114Skamil 5641.88Skamil memset(&info, 0, sizeof(info)); 5651.88Skamil 5661.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5671.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5681.88Skamil if (child == 0) { 5691.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5701.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5711.88Skamil 5721.88Skamil sigemptyset(&intmask); 5731.88Skamil sigaddset(&intmask, sig); 5741.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5751.88Skamil 5761.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5771.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5781.89Skamil 5791.88Skamil DPRINTF("Before executing a trap\n"); 5801.88Skamil switch (sig) { 5811.88Skamil case SIGTRAP: 5821.88Skamil trigger_trap(); 5831.88Skamil break; 5841.88Skamil case SIGSEGV: 5851.88Skamil trigger_segv(); 5861.88Skamil break; 5871.88Skamil case SIGILL: 5881.88Skamil trigger_ill(); 5891.88Skamil break; 5901.88Skamil case SIGFPE: 5911.88Skamil trigger_fpe(); 5921.88Skamil break; 5931.88Skamil case SIGBUS: 5941.88Skamil trigger_bus(); 5951.88Skamil break; 5961.88Skamil default: 5971.88Skamil /* NOTREACHED */ 5981.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5991.88Skamil } 6001.88Skamil 6011.88Skamil /* NOTREACHED */ 6021.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6031.88Skamil } 6041.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6051.88Skamil 6061.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6071.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6081.88Skamil 6091.89Skamil validate_status_stopped(status, sigval); 6101.89Skamil 6111.89Skamil name[0] = CTL_KERN, 6121.89Skamil name[1] = KERN_PROC2, 6131.89Skamil name[2] = KERN_PROC_PID; 6141.89Skamil name[3] = child; 6151.89Skamil name[4] = sizeof(kp); 6161.89Skamil name[5] = 1; 6171.89Skamil 6181.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6191.89Skamil 6201.89Skamil kp_sigmask = kp.p_sigmask; 6211.89Skamil 6221.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6231.89Skamil SYSCALL_REQUIRE( 6241.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6251.89Skamil 6261.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6271.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6281.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6291.89Skamil info.psi_siginfo.si_errno); 6301.89Skamil 6311.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6321.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6331.89Skamil 6341.89Skamil DPRINTF("Before resuming the child process where it left off and " 6351.89Skamil "without signal to be sent\n"); 6361.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6371.89Skamil 6381.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6391.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6401.89Skamil 6411.88Skamil validate_status_stopped(status, sig); 6421.88Skamil 6431.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6441.88Skamil SYSCALL_REQUIRE( 6451.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6461.88Skamil 6471.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6481.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6491.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6501.88Skamil info.psi_siginfo.si_errno); 6511.88Skamil 6521.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6531.89Skamil 6541.89Skamil DPRINTF("kp_sigmask=" 6551.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6561.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6571.89Skamil kp_sigmask.__bits[3]); 6581.89Skamil 6591.89Skamil DPRINTF("kp.p_sigmask=" 6601.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6611.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6621.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6631.89Skamil 6641.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6651.89Skamil 6661.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6671.88Skamil switch (sig) { 6681.88Skamil case SIGTRAP: 6691.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6701.88Skamil break; 6711.88Skamil case SIGSEGV: 6721.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6731.88Skamil break; 6741.88Skamil case SIGILL: 6751.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6761.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6771.88Skamil break; 6781.88Skamil case SIGFPE: 6791.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6801.88Skamil break; 6811.88Skamil case SIGBUS: 6821.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6831.88Skamil break; 6841.88Skamil } 6851.88Skamil 6861.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6871.88Skamil 6881.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6891.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6901.88Skamil 6911.88Skamil validate_status_signaled(status, SIGKILL, 0); 6921.88Skamil 6931.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6941.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6951.88Skamil} 6961.88Skamil 6971.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 6981.88SkamilATF_TC(test); \ 6991.88SkamilATF_TC_HEAD(test, tc) \ 7001.88Skamil{ \ 7011.88Skamil atf_tc_set_md_var(tc, "descr", \ 7021.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7031.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7041.88Skamil} \ 7051.88Skamil \ 7061.88SkamilATF_TC_BODY(test, tc) \ 7071.88Skamil{ \ 7081.88Skamil \ 7091.88Skamil traceme_signalmasked_crash(sig); \ 7101.88Skamil} 7111.88Skamil 7121.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7131.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7141.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7151.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7161.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7171.88Skamil 7181.88Skamil/// ---------------------------------------------------------------------------- 7191.88Skamil 7201.88Skamilstatic void 7211.88Skamiltraceme_signalignored_crash(int sig) 7221.88Skamil{ 7231.90Skamil const int sigval = SIGSTOP; 7241.88Skamil pid_t child, wpid; 7251.88Skamil#if defined(TWAIT_HAVE_STATUS) 7261.88Skamil int status; 7271.88Skamil#endif 7281.88Skamil struct sigaction sa; 7291.88Skamil struct ptrace_siginfo info; 7301.90Skamil struct kinfo_proc2 kp; 7311.90Skamil size_t len = sizeof(kp); 7321.90Skamil 7331.90Skamil int name[6]; 7341.90Skamil const size_t namelen = __arraycount(name); 7351.90Skamil ki_sigset_t kp_sigignore; 7361.88Skamil 7371.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7381.88Skamil if (sig == SIGILL) 7391.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7401.88Skamil#endif 7411.88Skamil 7421.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7431.114Skamil atf_tc_skip("FP exceptions are not supported"); 7441.114Skamil 7451.88Skamil memset(&info, 0, sizeof(info)); 7461.88Skamil 7471.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7481.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7491.88Skamil if (child == 0) { 7501.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7511.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7521.88Skamil 7531.88Skamil memset(&sa, 0, sizeof(sa)); 7541.88Skamil sa.sa_handler = SIG_IGN; 7551.88Skamil sigemptyset(&sa.sa_mask); 7561.88Skamil 7571.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7581.88Skamil 7591.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7601.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7611.90Skamil 7621.88Skamil DPRINTF("Before executing a trap\n"); 7631.88Skamil switch (sig) { 7641.88Skamil case SIGTRAP: 7651.88Skamil trigger_trap(); 7661.88Skamil break; 7671.88Skamil case SIGSEGV: 7681.88Skamil trigger_segv(); 7691.88Skamil break; 7701.88Skamil case SIGILL: 7711.88Skamil trigger_ill(); 7721.88Skamil break; 7731.88Skamil case SIGFPE: 7741.88Skamil trigger_fpe(); 7751.88Skamil break; 7761.88Skamil case SIGBUS: 7771.88Skamil trigger_bus(); 7781.88Skamil break; 7791.88Skamil default: 7801.88Skamil /* NOTREACHED */ 7811.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7821.88Skamil } 7831.88Skamil 7841.88Skamil /* NOTREACHED */ 7851.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7861.88Skamil } 7871.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7881.88Skamil 7891.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7901.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7911.88Skamil 7921.90Skamil validate_status_stopped(status, sigval); 7931.90Skamil 7941.90Skamil name[0] = CTL_KERN, 7951.90Skamil name[1] = KERN_PROC2, 7961.90Skamil name[2] = KERN_PROC_PID; 7971.90Skamil name[3] = child; 7981.90Skamil name[4] = sizeof(kp); 7991.90Skamil name[5] = 1; 8001.90Skamil 8011.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8021.90Skamil 8031.90Skamil kp_sigignore = kp.p_sigignore; 8041.90Skamil 8051.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8061.90Skamil SYSCALL_REQUIRE( 8071.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8081.90Skamil 8091.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8101.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8111.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8121.90Skamil info.psi_siginfo.si_errno); 8131.90Skamil 8141.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8151.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8161.90Skamil 8171.90Skamil DPRINTF("Before resuming the child process where it left off and " 8181.90Skamil "without signal to be sent\n"); 8191.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8201.90Skamil 8211.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8221.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8231.90Skamil 8241.88Skamil validate_status_stopped(status, sig); 8251.88Skamil 8261.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8271.88Skamil SYSCALL_REQUIRE( 8281.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8291.88Skamil 8301.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8311.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8321.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8331.88Skamil info.psi_siginfo.si_errno); 8341.88Skamil 8351.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8361.90Skamil 8371.90Skamil DPRINTF("kp_sigignore=" 8381.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8391.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8401.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8411.90Skamil 8421.90Skamil DPRINTF("kp.p_sigignore=" 8431.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8441.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8451.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8461.90Skamil 8471.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8481.90Skamil 8491.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8501.88Skamil switch (sig) { 8511.88Skamil case SIGTRAP: 8521.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8531.88Skamil break; 8541.88Skamil case SIGSEGV: 8551.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8561.88Skamil break; 8571.88Skamil case SIGILL: 8581.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8591.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8601.88Skamil break; 8611.88Skamil case SIGFPE: 8621.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8631.88Skamil break; 8641.88Skamil case SIGBUS: 8651.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8661.88Skamil break; 8671.88Skamil } 8681.88Skamil 8691.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8701.88Skamil 8711.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8721.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8731.88Skamil 8741.88Skamil validate_status_signaled(status, SIGKILL, 0); 8751.88Skamil 8761.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8771.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8781.88Skamil} 8791.88Skamil 8801.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8811.88SkamilATF_TC(test); \ 8821.88SkamilATF_TC_HEAD(test, tc) \ 8831.88Skamil{ \ 8841.88Skamil atf_tc_set_md_var(tc, "descr", \ 8851.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8861.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8871.88Skamil} \ 8881.88Skamil \ 8891.88SkamilATF_TC_BODY(test, tc) \ 8901.88Skamil{ \ 8911.88Skamil \ 8921.88Skamil traceme_signalignored_crash(sig); \ 8931.88Skamil} 8941.88Skamil 8951.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8961.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 8971.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 8981.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 8991.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9001.88Skamil 9011.88Skamil/// ---------------------------------------------------------------------------- 9021.88Skamil 9031.88Skamilstatic void 9041.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9051.1Skamil{ 9061.1Skamil const int exitval = 5; 9071.34Skamil const int sigval = SIGSTOP; 9081.1Skamil pid_t child, wpid; 9091.1Skamil struct sigaction sa; 9101.1Skamil#if defined(TWAIT_HAVE_STATUS) 9111.1Skamil int status; 9121.1Skamil#endif 9131.61Skre struct ptrace_siginfo info; 9141.1Skamil 9151.45Skamil memset(&info, 0, sizeof(info)); 9161.45Skamil 9171.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9181.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9191.1Skamil if (child == 0) { 9201.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9211.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9221.1Skamil 9231.34Skamil sa.sa_handler = sah; 9241.1Skamil sa.sa_flags = SA_SIGINFO; 9251.1Skamil sigemptyset(&sa.sa_mask); 9261.1Skamil 9271.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9281.1Skamil 9291.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9301.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9311.1Skamil 9321.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9331.1Skamil 9341.13Schristos DPRINTF("Before exiting of the child process\n"); 9351.1Skamil _exit(exitval); 9361.1Skamil } 9371.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9381.1Skamil 9391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9401.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9411.1Skamil 9421.1Skamil validate_status_stopped(status, sigval); 9431.1Skamil 9441.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9451.61Skre SYSCALL_REQUIRE( 9461.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9471.45Skamil 9481.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9491.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9501.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9511.45Skamil info.psi_siginfo.si_errno); 9521.45Skamil 9531.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9541.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9551.45Skamil 9561.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9571.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9581.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9591.1Skamil 9601.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9611.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9621.1Skamil 9631.1Skamil validate_status_exited(status, exitval); 9641.1Skamil 9651.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9661.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9671.1Skamil} 9681.1Skamil 9691.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9701.61SkreATF_TC(test); \ 9711.61SkreATF_TC_HEAD(test, tc) \ 9721.61Skre{ \ 9731.61Skre atf_tc_set_md_var(tc, "descr", \ 9741.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9751.61Skre "handled correctly and caught by a signal handler"); \ 9761.61Skre} \ 9771.61Skre \ 9781.61Skrestatic int test##_caught = 0; \ 9791.61Skre \ 9801.61Skrestatic void \ 9811.61Skretest##_sighandler(int arg) \ 9821.61Skre{ \ 9831.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9841.61Skre \ 9851.61Skre ++ test##_caught; \ 9861.61Skre} \ 9871.61Skre \ 9881.61SkreATF_TC_BODY(test, tc) \ 9891.61Skre{ \ 9901.61Skre \ 9911.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9921.34Skamil} 9931.34Skamil 9941.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9951.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9961.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 9971.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 9981.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 9991.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10001.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10011.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10021.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10031.34Skamil 10041.34Skamil/// ---------------------------------------------------------------------------- 10051.34Skamil 10061.35Skamilstatic void 10071.50Skamiltraceme_sendsignal_masked(int sigsent) 10081.50Skamil{ 10091.50Skamil const int exitval = 5; 10101.50Skamil const int sigval = SIGSTOP; 10111.50Skamil pid_t child, wpid; 10121.50Skamil sigset_t set; 10131.50Skamil#if defined(TWAIT_HAVE_STATUS) 10141.50Skamil int status; 10151.50Skamil#endif 10161.61Skre struct ptrace_siginfo info; 10171.50Skamil 10181.50Skamil memset(&info, 0, sizeof(info)); 10191.50Skamil 10201.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10211.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10221.50Skamil if (child == 0) { 10231.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10241.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10251.50Skamil 10261.50Skamil sigemptyset(&set); 10271.50Skamil sigaddset(&set, sigsent); 10281.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10291.50Skamil 10301.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10311.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10321.50Skamil 10331.50Skamil _exit(exitval); 10341.50Skamil } 10351.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10361.50Skamil 10371.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10381.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10391.50Skamil 10401.50Skamil validate_status_stopped(status, sigval); 10411.50Skamil 10421.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10431.61Skre SYSCALL_REQUIRE( 10441.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10451.50Skamil 10461.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10471.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10481.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10491.50Skamil info.psi_siginfo.si_errno); 10501.50Skamil 10511.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10521.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10531.50Skamil 10541.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10551.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10561.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10571.50Skamil 10581.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10591.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10601.50Skamil 10611.50Skamil validate_status_exited(status, exitval); 10621.50Skamil 10631.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10641.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10651.50Skamil} 10661.50Skamil 10671.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10681.61SkreATF_TC(test); \ 10691.61SkreATF_TC_HEAD(test, tc) \ 10701.61Skre{ \ 10711.61Skre atf_tc_set_md_var(tc, "descr", \ 10721.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10731.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10741.61Skre} \ 10751.61Skre \ 10761.61SkreATF_TC_BODY(test, tc) \ 10771.61Skre{ \ 10781.61Skre \ 10791.61Skre traceme_sendsignal_masked(sig); \ 10801.50Skamil} 10811.50Skamil 10821.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10831.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10841.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10851.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10861.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10871.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10881.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10891.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10901.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10911.50Skamil 10921.50Skamil/// ---------------------------------------------------------------------------- 10931.50Skamil 10941.50Skamilstatic void 10951.50Skamiltraceme_sendsignal_ignored(int sigsent) 10961.50Skamil{ 10971.50Skamil const int exitval = 5; 10981.50Skamil const int sigval = SIGSTOP; 10991.50Skamil pid_t child, wpid; 11001.50Skamil struct sigaction sa; 11011.50Skamil#if defined(TWAIT_HAVE_STATUS) 11021.50Skamil int status; 11031.50Skamil#endif 11041.61Skre struct ptrace_siginfo info; 11051.50Skamil 11061.50Skamil memset(&info, 0, sizeof(info)); 11071.50Skamil 11081.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11091.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11101.50Skamil if (child == 0) { 11111.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11121.61Skre 11131.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11141.50Skamil 11151.50Skamil memset(&sa, 0, sizeof(sa)); 11161.50Skamil sa.sa_handler = SIG_IGN; 11171.50Skamil sigemptyset(&sa.sa_mask); 11181.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11191.50Skamil 11201.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11211.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11221.50Skamil 11231.50Skamil _exit(exitval); 11241.50Skamil } 11251.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11261.50Skamil 11271.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11281.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11291.50Skamil 11301.50Skamil validate_status_stopped(status, sigval); 11311.50Skamil 11321.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11331.61Skre SYSCALL_REQUIRE( 11341.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11351.50Skamil 11361.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11371.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11381.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11391.50Skamil info.psi_siginfo.si_errno); 11401.50Skamil 11411.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11421.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11431.50Skamil 11441.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11451.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11461.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11471.50Skamil 11481.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11491.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11501.50Skamil 11511.50Skamil validate_status_exited(status, exitval); 11521.50Skamil 11531.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11541.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11551.50Skamil} 11561.50Skamil 11571.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11581.61SkreATF_TC(test); \ 11591.61SkreATF_TC_HEAD(test, tc) \ 11601.61Skre{ \ 11611.61Skre atf_tc_set_md_var(tc, "descr", \ 11621.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11631.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11641.61Skre} \ 11651.61Skre \ 11661.61SkreATF_TC_BODY(test, tc) \ 11671.61Skre{ \ 11681.61Skre \ 11691.61Skre traceme_sendsignal_ignored(sig); \ 11701.50Skamil} 11711.50Skamil 11721.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11731.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11741.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11751.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11761.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11771.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11781.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11791.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11801.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11811.50Skamil 11821.50Skamil/// ---------------------------------------------------------------------------- 11831.50Skamil 11841.50Skamilstatic void 11851.50Skamiltraceme_sendsignal_simple(int sigsent) 11861.1Skamil{ 11871.35Skamil const int sigval = SIGSTOP; 11881.35Skamil int exitval = 0; 11891.1Skamil pid_t child, wpid; 11901.1Skamil#if defined(TWAIT_HAVE_STATUS) 11911.1Skamil int status; 11921.85Skamil int expect_core; 11931.85Skamil 11941.85Skamil switch (sigsent) { 11951.85Skamil case SIGABRT: 11961.85Skamil case SIGTRAP: 11971.85Skamil case SIGBUS: 11981.85Skamil case SIGILL: 11991.85Skamil case SIGFPE: 12001.85Skamil case SIGSEGV: 12011.85Skamil expect_core = 1; 12021.85Skamil break; 12031.85Skamil default: 12041.85Skamil expect_core = 0; 12051.85Skamil break; 12061.85Skamil } 12071.1Skamil#endif 12081.61Skre struct ptrace_siginfo info; 12091.1Skamil 12101.45Skamil memset(&info, 0, sizeof(info)); 12111.45Skamil 12121.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12131.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12141.1Skamil if (child == 0) { 12151.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12161.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12171.1Skamil 12181.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12191.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12201.1Skamil 12211.35Skamil switch (sigsent) { 12221.35Skamil case SIGCONT: 12231.48Skamil case SIGSTOP: 12241.35Skamil _exit(exitval); 12251.35Skamil default: 12261.35Skamil /* NOTREACHED */ 12271.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12281.35Skamil } 12291.1Skamil } 12301.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12311.1Skamil 12321.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12331.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12341.1Skamil 12351.1Skamil validate_status_stopped(status, sigval); 12361.1Skamil 12371.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12381.61Skre SYSCALL_REQUIRE( 12391.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12401.45Skamil 12411.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12421.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12431.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12441.45Skamil info.psi_siginfo.si_errno); 12451.45Skamil 12461.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12471.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12481.45Skamil 12491.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12501.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12511.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12521.1Skamil 12531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12551.1Skamil 12561.35Skamil switch (sigsent) { 12571.48Skamil case SIGSTOP: 12581.48Skamil validate_status_stopped(status, sigsent); 12591.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12601.61Skre "child\n"); 12611.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12621.61Skre sizeof(info)) != -1); 12631.48Skamil 12641.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12651.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12661.61Skre "si_errno=%#x\n", 12671.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12681.61Skre info.psi_siginfo.si_errno); 12691.48Skamil 12701.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12711.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12721.48Skamil 12731.48Skamil DPRINTF("Before resuming the child process where it left off " 12741.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12751.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12761.48Skamil 12771.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12781.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12791.61Skre child); 12801.48Skamil /* FALLTHROUGH */ 12811.35Skamil case SIGCONT: 12821.35Skamil validate_status_exited(status, exitval); 12831.35Skamil break; 12841.35Skamil default: 12851.35Skamil validate_status_signaled(status, sigsent, expect_core); 12861.35Skamil break; 12871.35Skamil } 12881.1Skamil 12891.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12901.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12911.1Skamil} 12921.1Skamil 12931.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12941.61SkreATF_TC(test); \ 12951.61SkreATF_TC_HEAD(test, tc) \ 12961.61Skre{ \ 12971.61Skre atf_tc_set_md_var(tc, "descr", \ 12981.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 12991.61Skre "handled correctly in a child without a signal handler"); \ 13001.61Skre} \ 13011.61Skre \ 13021.61SkreATF_TC_BODY(test, tc) \ 13031.61Skre{ \ 13041.61Skre \ 13051.61Skre traceme_sendsignal_simple(sig); \ 13061.35Skamil} 13071.35Skamil 13081.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13091.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13101.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13111.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13121.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13131.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13141.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13151.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13161.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13171.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13181.35Skamil 13191.35Skamil/// ---------------------------------------------------------------------------- 13201.35Skamil 13211.37SkamilATF_TC(traceme_pid1_parent); 13221.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13231.37Skamil{ 13241.37Skamil atf_tc_set_md_var(tc, "descr", 13251.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13261.37Skamil} 13271.37Skamil 13281.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13291.37Skamil{ 13301.37Skamil struct msg_fds parent_child; 13311.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13321.37Skamil pid_t child1, child2, wpid; 13331.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13341.37Skamil#if defined(TWAIT_HAVE_STATUS) 13351.37Skamil int status; 13361.37Skamil#endif 13371.37Skamil 13381.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13391.37Skamil 13401.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13411.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13421.37Skamil if (child1 == 0) { 13431.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13441.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13451.37Skamil if (child2 != 0) { 13461.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13471.61Skre getpid(), child2); 13481.37Skamil _exit(exitval_child1); 13491.37Skamil } 13501.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13511.37Skamil 13521.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13531.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13541.37Skamil 13551.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13561.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13571.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13581.37Skamil 13591.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13601.37Skamil 13611.37Skamil _exit(exitval_child2); 13621.37Skamil } 13631.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13641.37Skamil 13651.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13661.61Skre TWAIT_REQUIRE_SUCCESS( 13671.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13681.37Skamil 13691.37Skamil validate_status_exited(status, exitval_child1); 13701.37Skamil 13711.37Skamil DPRINTF("Notify that child1 is dead\n"); 13721.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13731.37Skamil 13741.37Skamil DPRINTF("Wait for exiting of child2\n"); 13751.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13761.37Skamil} 13771.37Skamil 13781.37Skamil/// ---------------------------------------------------------------------------- 13791.37Skamil 13801.40Skamilstatic void 13811.40Skamiltraceme_vfork_raise(int sigval) 13821.40Skamil{ 13831.46Skamil const int exitval = 5, exitval_watcher = 10; 13841.46Skamil pid_t child, parent, watcher, wpid; 13851.46Skamil int rv; 13861.40Skamil#if defined(TWAIT_HAVE_STATUS) 13871.40Skamil int status; 13881.85Skamil 13891.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13901.85Skamil volatile int expect_core; 13911.85Skamil 13921.85Skamil switch (sigval) { 13931.85Skamil case SIGABRT: 13941.85Skamil case SIGTRAP: 13951.85Skamil case SIGBUS: 13961.85Skamil case SIGILL: 13971.85Skamil case SIGFPE: 13981.85Skamil case SIGSEGV: 13991.85Skamil expect_core = 1; 14001.85Skamil break; 14011.85Skamil default: 14021.85Skamil expect_core = 0; 14031.85Skamil break; 14041.85Skamil } 14051.40Skamil#endif 14061.40Skamil 14071.46Skamil /* 14081.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14091.46Skamil * the SIGKILL signal to it. 14101.46Skamil * 14111.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14121.46Skamil * simpler to reparent this process to initproc and forget about it. 14131.46Skamil */ 14141.46Skamil if (sigval == SIGSTOP) { 14151.46Skamil parent = getpid(); 14161.46Skamil 14171.46Skamil watcher = fork(); 14181.46Skamil ATF_REQUIRE(watcher != 1); 14191.46Skamil if (watcher == 0) { 14201.46Skamil /* Double fork(2) trick to reparent to initproc */ 14211.46Skamil watcher = fork(); 14221.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14231.46Skamil if (watcher != 0) 14241.46Skamil _exit(exitval_watcher); 14251.46Skamil 14261.46Skamil child = await_stopped_child(parent); 14271.46Skamil 14281.46Skamil errno = 0; 14291.46Skamil rv = kill(child, SIGKILL); 14301.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14311.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14321.46Skamil 14331.46Skamil /* This exit value will be collected by initproc */ 14341.46Skamil _exit(0); 14351.46Skamil } 14361.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14371.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14381.61Skre watcher); 14391.46Skamil 14401.46Skamil validate_status_exited(status, exitval_watcher); 14411.46Skamil 14421.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14431.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14441.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14451.46Skamil } 14461.46Skamil 14471.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14481.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14491.40Skamil if (child == 0) { 14501.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14511.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14521.40Skamil 14531.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14541.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14551.40Skamil 14561.40Skamil switch (sigval) { 14571.46Skamil case SIGSTOP: 14581.40Skamil case SIGKILL: 14591.40Skamil case SIGABRT: 14601.40Skamil case SIGHUP: 14611.85Skamil case SIGTRAP: 14621.85Skamil case SIGBUS: 14631.85Skamil case SIGILL: 14641.85Skamil case SIGFPE: 14651.85Skamil case SIGSEGV: 14661.40Skamil /* NOTREACHED */ 14671.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14681.70Smrg __unreachable(); 14691.40Skamil default: 14701.40Skamil DPRINTF("Before exiting of the child process\n"); 14711.40Skamil _exit(exitval); 14721.40Skamil } 14731.40Skamil } 14741.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14751.40Skamil 14761.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14771.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14781.40Skamil 14791.40Skamil switch (sigval) { 14801.40Skamil case SIGKILL: 14811.40Skamil case SIGABRT: 14821.40Skamil case SIGHUP: 14831.85Skamil case SIGTRAP: 14841.85Skamil case SIGBUS: 14851.85Skamil case SIGILL: 14861.85Skamil case SIGFPE: 14871.85Skamil case SIGSEGV: 14881.40Skamil validate_status_signaled(status, sigval, expect_core); 14891.40Skamil break; 14901.40Skamil case SIGSTOP: 14911.46Skamil validate_status_signaled(status, SIGKILL, 0); 14921.46Skamil break; 14931.40Skamil case SIGCONT: 14941.47Skamil case SIGTSTP: 14951.47Skamil case SIGTTIN: 14961.47Skamil case SIGTTOU: 14971.40Skamil validate_status_exited(status, exitval); 14981.40Skamil break; 14991.40Skamil default: 15001.40Skamil /* NOTREACHED */ 15011.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15021.40Skamil break; 15031.40Skamil } 15041.40Skamil 15051.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15061.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15071.40Skamil} 15081.40Skamil 15091.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15101.61SkreATF_TC(test); \ 15111.61SkreATF_TC_HEAD(test, tc) \ 15121.61Skre{ \ 15131.61Skre atf_tc_set_md_var(tc, "descr", \ 15141.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15151.61Skre "vfork(2)ed child"); \ 15161.61Skre} \ 15171.61Skre \ 15181.61SkreATF_TC_BODY(test, tc) \ 15191.61Skre{ \ 15201.61Skre \ 15211.61Skre traceme_vfork_raise(sig); \ 15221.40Skamil} 15231.40Skamil 15241.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15251.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15261.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15271.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15281.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15291.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15301.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15311.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15321.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15331.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15341.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15351.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15361.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15371.40Skamil 15381.40Skamil/// ---------------------------------------------------------------------------- 15391.40Skamil 15401.52Skamilstatic void 15411.52Skamiltraceme_vfork_crash(int sig) 15421.41Skamil{ 15431.41Skamil pid_t child, wpid; 15441.41Skamil#if defined(TWAIT_HAVE_STATUS) 15451.41Skamil int status; 15461.41Skamil#endif 15471.41Skamil 15481.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15491.71Skamil if (sig == SIGILL) 15501.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15511.71Skamil#endif 15521.71Skamil 15531.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15541.114Skamil atf_tc_skip("FP exceptions are not supported"); 15551.114Skamil 15561.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15571.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15581.41Skamil if (child == 0) { 15591.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15601.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15611.41Skamil 15621.52Skamil DPRINTF("Before executing a trap\n"); 15631.52Skamil switch (sig) { 15641.52Skamil case SIGTRAP: 15651.52Skamil trigger_trap(); 15661.52Skamil break; 15671.52Skamil case SIGSEGV: 15681.52Skamil trigger_segv(); 15691.52Skamil break; 15701.52Skamil case SIGILL: 15711.52Skamil trigger_ill(); 15721.52Skamil break; 15731.52Skamil case SIGFPE: 15741.52Skamil trigger_fpe(); 15751.52Skamil break; 15761.52Skamil case SIGBUS: 15771.52Skamil trigger_bus(); 15781.52Skamil break; 15791.52Skamil default: 15801.52Skamil /* NOTREACHED */ 15811.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15821.52Skamil } 15831.41Skamil 15841.41Skamil /* NOTREACHED */ 15851.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15861.41Skamil } 15871.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15881.41Skamil 15891.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15901.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15911.41Skamil 15921.52Skamil validate_status_signaled(status, sig, 1); 15931.41Skamil 15941.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15951.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15961.41Skamil} 15971.41Skamil 15981.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 15991.61SkreATF_TC(test); \ 16001.61SkreATF_TC_HEAD(test, tc) \ 16011.61Skre{ \ 16021.61Skre atf_tc_set_md_var(tc, "descr", \ 16031.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16041.61Skre "vfork(2)ed child"); \ 16051.61Skre} \ 16061.61Skre \ 16071.61SkreATF_TC_BODY(test, tc) \ 16081.61Skre{ \ 16091.61Skre \ 16101.61Skre traceme_vfork_crash(sig); \ 16111.52Skamil} 16121.52Skamil 16131.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16141.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16151.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16161.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16171.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16181.52Skamil 16191.41Skamil/// ---------------------------------------------------------------------------- 16201.41Skamil 16211.92Skamilstatic void 16221.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16231.92Skamil{ 16241.92Skamil pid_t child, wpid; 16251.92Skamil#if defined(TWAIT_HAVE_STATUS) 16261.92Skamil int status; 16271.92Skamil#endif 16281.92Skamil sigset_t intmask; 16291.92Skamil 16301.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16311.92Skamil if (sig == SIGILL) 16321.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16331.92Skamil#endif 16341.92Skamil 16351.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16361.114Skamil atf_tc_skip("FP exceptions are not supported"); 16371.114Skamil 16381.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16391.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16401.92Skamil if (child == 0) { 16411.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16421.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16431.92Skamil 16441.92Skamil sigemptyset(&intmask); 16451.92Skamil sigaddset(&intmask, sig); 16461.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16471.92Skamil 16481.92Skamil DPRINTF("Before executing a trap\n"); 16491.92Skamil switch (sig) { 16501.92Skamil case SIGTRAP: 16511.92Skamil trigger_trap(); 16521.92Skamil break; 16531.92Skamil case SIGSEGV: 16541.92Skamil trigger_segv(); 16551.92Skamil break; 16561.92Skamil case SIGILL: 16571.92Skamil trigger_ill(); 16581.92Skamil break; 16591.92Skamil case SIGFPE: 16601.92Skamil trigger_fpe(); 16611.92Skamil break; 16621.92Skamil case SIGBUS: 16631.92Skamil trigger_bus(); 16641.92Skamil break; 16651.92Skamil default: 16661.92Skamil /* NOTREACHED */ 16671.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16681.92Skamil } 16691.92Skamil 16701.92Skamil /* NOTREACHED */ 16711.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16721.92Skamil } 16731.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16741.92Skamil 16751.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16761.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16771.92Skamil 16781.92Skamil validate_status_signaled(status, sig, 1); 16791.92Skamil 16801.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16811.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16821.92Skamil} 16831.92Skamil 16841.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16851.92SkamilATF_TC(test); \ 16861.92SkamilATF_TC_HEAD(test, tc) \ 16871.92Skamil{ \ 16881.92Skamil atf_tc_set_md_var(tc, "descr", \ 16891.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16901.92Skamil "vfork(2)ed child with a masked signal"); \ 16911.92Skamil} \ 16921.92Skamil \ 16931.92SkamilATF_TC_BODY(test, tc) \ 16941.92Skamil{ \ 16951.92Skamil \ 16961.92Skamil traceme_vfork_signalmasked_crash(sig); \ 16971.92Skamil} 16981.92Skamil 16991.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17001.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17011.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17021.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17031.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17041.92Skamil 17051.92Skamil/// ---------------------------------------------------------------------------- 17061.92Skamil 17071.92Skamilstatic void 17081.92Skamiltraceme_vfork_signalignored_crash(int sig) 17091.92Skamil{ 17101.92Skamil pid_t child, wpid; 17111.92Skamil#if defined(TWAIT_HAVE_STATUS) 17121.92Skamil int status; 17131.92Skamil#endif 17141.92Skamil struct sigaction sa; 17151.92Skamil 17161.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17171.92Skamil if (sig == SIGILL) 17181.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17191.92Skamil#endif 17201.92Skamil 17211.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17221.114Skamil atf_tc_skip("FP exceptions are not supported"); 17231.114Skamil 17241.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17251.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17261.92Skamil if (child == 0) { 17271.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17281.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17291.92Skamil 17301.92Skamil memset(&sa, 0, sizeof(sa)); 17311.92Skamil sa.sa_handler = SIG_IGN; 17321.92Skamil sigemptyset(&sa.sa_mask); 17331.92Skamil 17341.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17351.92Skamil 17361.92Skamil DPRINTF("Before executing a trap\n"); 17371.92Skamil switch (sig) { 17381.92Skamil case SIGTRAP: 17391.92Skamil trigger_trap(); 17401.92Skamil break; 17411.92Skamil case SIGSEGV: 17421.92Skamil trigger_segv(); 17431.92Skamil break; 17441.92Skamil case SIGILL: 17451.92Skamil trigger_ill(); 17461.92Skamil break; 17471.92Skamil case SIGFPE: 17481.92Skamil trigger_fpe(); 17491.92Skamil break; 17501.92Skamil case SIGBUS: 17511.92Skamil trigger_bus(); 17521.92Skamil break; 17531.92Skamil default: 17541.92Skamil /* NOTREACHED */ 17551.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17561.92Skamil } 17571.92Skamil 17581.92Skamil /* NOTREACHED */ 17591.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17601.92Skamil } 17611.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17621.92Skamil 17631.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17641.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17651.92Skamil 17661.92Skamil validate_status_signaled(status, sig, 1); 17671.92Skamil 17681.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17691.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17701.92Skamil} 17711.92Skamil 17721.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17731.92SkamilATF_TC(test); \ 17741.92SkamilATF_TC_HEAD(test, tc) \ 17751.92Skamil{ \ 17761.92Skamil atf_tc_set_md_var(tc, "descr", \ 17771.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17781.92Skamil "vfork(2)ed child with ignored signal"); \ 17791.92Skamil} \ 17801.92Skamil \ 17811.92SkamilATF_TC_BODY(test, tc) \ 17821.92Skamil{ \ 17831.92Skamil \ 17841.92Skamil traceme_vfork_signalignored_crash(sig); \ 17851.92Skamil} 17861.92Skamil 17871.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17881.92Skamil SIGTRAP) 17891.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17901.92Skamil SIGSEGV) 17911.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17921.92Skamil SIGILL) 17931.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17941.92Skamil SIGFPE) 17951.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17961.92Skamil SIGBUS) 17971.92Skamil 17981.92Skamil/// ---------------------------------------------------------------------------- 17991.92Skamil 18001.96Skamilstatic void 18011.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18021.43Skamil{ 18031.43Skamil const int sigval = SIGTRAP; 18041.43Skamil pid_t child, wpid; 18051.43Skamil#if defined(TWAIT_HAVE_STATUS) 18061.43Skamil int status; 18071.43Skamil#endif 18081.96Skamil struct sigaction sa; 18091.61Skre struct ptrace_siginfo info; 18101.96Skamil sigset_t intmask; 18111.96Skamil struct kinfo_proc2 kp; 18121.96Skamil size_t len = sizeof(kp); 18131.96Skamil 18141.96Skamil int name[6]; 18151.96Skamil const size_t namelen = __arraycount(name); 18161.96Skamil ki_sigset_t kp_sigmask; 18171.96Skamil ki_sigset_t kp_sigignore; 18181.43Skamil 18191.43Skamil memset(&info, 0, sizeof(info)); 18201.43Skamil 18211.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18221.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18231.43Skamil if (child == 0) { 18241.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18251.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18261.43Skamil 18271.96Skamil if (masked) { 18281.96Skamil sigemptyset(&intmask); 18291.96Skamil sigaddset(&intmask, sigval); 18301.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18311.96Skamil } 18321.96Skamil 18331.96Skamil if (ignored) { 18341.96Skamil memset(&sa, 0, sizeof(sa)); 18351.96Skamil sa.sa_handler = SIG_IGN; 18361.96Skamil sigemptyset(&sa.sa_mask); 18371.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18381.96Skamil } 18391.96Skamil 18401.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18411.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18421.43Skamil 18431.43Skamil /* NOTREACHED */ 18441.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18451.43Skamil } 18461.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18471.43Skamil 18481.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18491.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18501.43Skamil 18511.43Skamil validate_status_stopped(status, sigval); 18521.43Skamil 18531.96Skamil name[0] = CTL_KERN, 18541.96Skamil name[1] = KERN_PROC2, 18551.96Skamil name[2] = KERN_PROC_PID; 18561.96Skamil name[3] = getpid(); 18571.96Skamil name[4] = sizeof(kp); 18581.96Skamil name[5] = 1; 18591.96Skamil 18601.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18611.96Skamil 18621.96Skamil if (masked) 18631.96Skamil kp_sigmask = kp.p_sigmask; 18641.96Skamil 18651.96Skamil if (ignored) 18661.96Skamil kp_sigignore = kp.p_sigignore; 18671.96Skamil 18681.96Skamil name[3] = getpid(); 18691.96Skamil 18701.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18711.96Skamil 18721.96Skamil if (masked) { 18731.96Skamil DPRINTF("kp_sigmask=" 18741.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18751.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18761.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18771.96Skamil 18781.96Skamil DPRINTF("kp.p_sigmask=" 18791.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18801.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18811.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18821.96Skamil 18831.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18841.96Skamil sizeof(kp_sigmask))); 18851.96Skamil } 18861.96Skamil 18871.96Skamil if (ignored) { 18881.96Skamil DPRINTF("kp_sigignore=" 18891.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18901.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18911.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18921.96Skamil 18931.96Skamil DPRINTF("kp.p_sigignore=" 18941.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18951.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 18961.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 18971.96Skamil 18981.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 18991.96Skamil sizeof(kp_sigignore))); 19001.96Skamil } 19011.96Skamil 19021.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19031.61Skre SYSCALL_REQUIRE( 19041.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19051.43Skamil 19061.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19071.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19081.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19091.43Skamil info.psi_siginfo.si_errno); 19101.43Skamil 19111.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19121.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19131.43Skamil 19141.43Skamil DPRINTF("Before resuming the child process where it left off and " 19151.43Skamil "without signal to be sent\n"); 19161.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19171.43Skamil 19181.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19191.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19201.43Skamil 19211.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19221.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19231.43Skamil} 19241.43Skamil 19251.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19261.96SkamilATF_TC(test); \ 19271.96SkamilATF_TC_HEAD(test, tc) \ 19281.96Skamil{ \ 19291.96Skamil atf_tc_set_md_var(tc, "descr", \ 19301.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19311.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19321.96Skamil masked ? " with ignored signal" : ""); \ 19331.96Skamil} \ 19341.96Skamil \ 19351.96SkamilATF_TC_BODY(test, tc) \ 19361.96Skamil{ \ 19371.96Skamil \ 19381.96Skamil traceme_vfork_exec(masked, ignored); \ 19391.96Skamil} 19401.96Skamil 19411.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19421.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19431.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19441.96Skamil 19451.43Skamil/// ---------------------------------------------------------------------------- 19461.43Skamil 19471.1Skamil#if defined(TWAIT_HAVE_PID) 19481.51Skamilstatic void 19491.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19501.59Skamil{ 19511.94Skamil const int sigval = SIGSTOP; 19521.59Skamil struct msg_fds parent_tracee, parent_tracer; 19531.59Skamil const int exitval = 10; 19541.59Skamil pid_t tracee, tracer, wpid; 19551.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19561.59Skamil#if defined(TWAIT_HAVE_STATUS) 19571.59Skamil int status; 19581.59Skamil#endif 19591.94Skamil struct sigaction sa; 19601.59Skamil struct ptrace_siginfo info; 19611.94Skamil sigset_t intmask; 19621.94Skamil struct kinfo_proc2 kp; 19631.94Skamil size_t len = sizeof(kp); 19641.94Skamil 19651.94Skamil int name[6]; 19661.94Skamil const size_t namelen = __arraycount(name); 19671.94Skamil ki_sigset_t kp_sigmask; 19681.94Skamil ki_sigset_t kp_sigignore; 19691.61Skre 19701.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19711.71Skamil if (sig == SIGILL) 19721.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19731.71Skamil#endif 19741.71Skamil 19751.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19761.114Skamil atf_tc_skip("FP exceptions are not supported"); 19771.114Skamil 19781.59Skamil memset(&info, 0, sizeof(info)); 19791.59Skamil 19801.59Skamil DPRINTF("Spawn tracee\n"); 19811.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19821.59Skamil tracee = atf_utils_fork(); 19831.59Skamil if (tracee == 0) { 19841.59Skamil // Wait for parent to let us crash 19851.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19861.61Skre 19871.94Skamil if (masked) { 19881.94Skamil sigemptyset(&intmask); 19891.94Skamil sigaddset(&intmask, sig); 19901.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19911.94Skamil } 19921.94Skamil 19931.94Skamil if (ignored) { 19941.94Skamil memset(&sa, 0, sizeof(sa)); 19951.94Skamil sa.sa_handler = SIG_IGN; 19961.94Skamil sigemptyset(&sa.sa_mask); 19971.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 19981.94Skamil } 19991.94Skamil 20001.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20011.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20021.94Skamil 20031.59Skamil DPRINTF("Before executing a trap\n"); 20041.59Skamil switch (sig) { 20051.59Skamil case SIGTRAP: 20061.59Skamil trigger_trap(); 20071.59Skamil break; 20081.59Skamil case SIGSEGV: 20091.59Skamil trigger_segv(); 20101.59Skamil break; 20111.59Skamil case SIGILL: 20121.59Skamil trigger_ill(); 20131.59Skamil break; 20141.59Skamil case SIGFPE: 20151.59Skamil trigger_fpe(); 20161.59Skamil break; 20171.59Skamil case SIGBUS: 20181.59Skamil trigger_bus(); 20191.59Skamil break; 20201.59Skamil default: 20211.59Skamil /* NOTREACHED */ 20221.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20231.59Skamil } 20241.59Skamil 20251.59Skamil /* NOTREACHED */ 20261.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20271.59Skamil } 20281.59Skamil 20291.59Skamil DPRINTF("Spawn debugger\n"); 20301.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20311.59Skamil tracer = atf_utils_fork(); 20321.59Skamil if (tracer == 0) { 20331.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20341.59Skamil tracer = atf_utils_fork(); 20351.59Skamil if (tracer != 0) 20361.61Skre _exit(exitval); 20371.59Skamil 20381.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20391.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20401.59Skamil 20411.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20421.59Skamil FORKEE_REQUIRE_SUCCESS( 20431.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20441.59Skamil 20451.59Skamil forkee_status_stopped(status, SIGSTOP); 20461.59Skamil 20471.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20481.94Skamil "traced process\n"); 20491.94Skamil SYSCALL_REQUIRE( 20501.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20511.94Skamil 20521.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20531.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20541.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20551.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20561.94Skamil 20571.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20581.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20591.94Skamil 20601.59Skamil /* Resume tracee with PT_CONTINUE */ 20611.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20621.59Skamil 20631.59Skamil /* Inform parent that tracer has attached to tracee */ 20641.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20651.59Skamil 20661.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20671.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20681.59Skamil 20691.59Skamil /* Wait for tracee and assert that it exited */ 20701.59Skamil FORKEE_REQUIRE_SUCCESS( 20711.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20721.59Skamil 20731.94Skamil forkee_status_stopped(status, sigval); 20741.94Skamil 20751.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20761.94Skamil "traced process\n"); 20771.94Skamil SYSCALL_REQUIRE( 20781.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20791.94Skamil 20801.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20811.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20821.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20831.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20841.94Skamil 20851.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20861.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20871.94Skamil 20881.94Skamil name[0] = CTL_KERN, 20891.94Skamil name[1] = KERN_PROC2, 20901.94Skamil name[2] = KERN_PROC_PID; 20911.94Skamil name[3] = tracee; 20921.94Skamil name[4] = sizeof(kp); 20931.94Skamil name[5] = 1; 20941.94Skamil 20951.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20961.94Skamil 20971.94Skamil if (masked) 20981.94Skamil kp_sigmask = kp.p_sigmask; 20991.94Skamil 21001.94Skamil if (ignored) 21011.94Skamil kp_sigignore = kp.p_sigignore; 21021.94Skamil 21031.94Skamil /* Resume tracee with PT_CONTINUE */ 21041.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21051.94Skamil 21061.94Skamil /* Wait for tracee and assert that it exited */ 21071.94Skamil FORKEE_REQUIRE_SUCCESS( 21081.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21091.94Skamil 21101.93Skamil forkee_status_stopped(status, sig); 21111.59Skamil 21121.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21131.61Skre "traced process\n"); 21141.61Skre SYSCALL_REQUIRE( 21151.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21161.59Skamil 21171.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21181.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21191.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21201.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21211.59Skamil 21221.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21231.94Skamil 21241.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21251.94Skamil 21261.94Skamil if (masked) { 21271.94Skamil DPRINTF("kp_sigmask=" 21281.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21291.94Skamil PRIx32 "\n", 21301.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21311.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21321.94Skamil 21331.94Skamil DPRINTF("kp.p_sigmask=" 21341.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21351.94Skamil PRIx32 "\n", 21361.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21371.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21381.94Skamil 21391.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21401.94Skamil sizeof(kp_sigmask))); 21411.94Skamil } 21421.94Skamil 21431.94Skamil if (ignored) { 21441.94Skamil DPRINTF("kp_sigignore=" 21451.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21461.94Skamil PRIx32 "\n", 21471.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21481.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21491.94Skamil 21501.94Skamil DPRINTF("kp.p_sigignore=" 21511.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21521.94Skamil PRIx32 "\n", 21531.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21541.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21551.94Skamil 21561.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21571.94Skamil sizeof(kp_sigignore))); 21581.94Skamil } 21591.94Skamil 21601.59Skamil switch (sig) { 21611.59Skamil case SIGTRAP: 21621.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21631.59Skamil break; 21641.59Skamil case SIGSEGV: 21651.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21661.59Skamil break; 21671.71Skamil case SIGILL: 21681.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21691.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21701.71Skamil break; 21711.59Skamil case SIGFPE: 21721.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21731.59Skamil break; 21741.59Skamil case SIGBUS: 21751.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21761.59Skamil break; 21771.59Skamil } 21781.59Skamil 21791.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21801.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21811.93Skamil FORKEE_REQUIRE_SUCCESS( 21821.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21831.59Skamil 21841.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21851.59Skamil 21861.71Skamil /* Inform parent that tracer is exiting normally */ 21871.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21881.71Skamil 21891.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21901.59Skamil _exit(0 /* collect by initproc */); 21911.59Skamil } 21921.59Skamil 21931.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21941.59Skamil "calling %s()\n", TWAIT_FNAME); 21951.59Skamil TWAIT_REQUIRE_SUCCESS( 21961.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 21971.59Skamil 21981.59Skamil validate_status_exited(status, exitval); 21991.59Skamil 22001.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22011.59Skamil TWAIT_FNAME); 22021.59Skamil TWAIT_REQUIRE_SUCCESS( 22031.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22041.59Skamil 22051.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22061.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22071.59Skamil 22081.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22091.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22101.59Skamil 22111.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22121.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22131.59Skamil 22141.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22151.59Skamil TWAIT_FNAME); 22161.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22171.59Skamil 22181.59Skamil validate_status_signaled(status, SIGKILL, 0); 22191.59Skamil 22201.71Skamil DPRINTF("Await normal exit of tracer\n"); 22211.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22221.71Skamil 22231.59Skamil msg_close(&parent_tracer); 22241.59Skamil msg_close(&parent_tracee); 22251.59Skamil} 22261.59Skamil 22271.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22281.61SkreATF_TC(test); \ 22291.61SkreATF_TC_HEAD(test, tc) \ 22301.61Skre{ \ 22311.61Skre atf_tc_set_md_var(tc, "descr", \ 22321.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22331.94Skamil "the debuggee"); \ 22341.61Skre} \ 22351.61Skre \ 22361.61SkreATF_TC_BODY(test, tc) \ 22371.61Skre{ \ 22381.61Skre \ 22391.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22401.59Skamil} 22411.59Skamil 22421.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22431.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22441.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22451.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22461.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22471.94Skamil 22481.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22491.94SkamilATF_TC(test); \ 22501.94SkamilATF_TC_HEAD(test, tc) \ 22511.94Skamil{ \ 22521.94Skamil atf_tc_set_md_var(tc, "descr", \ 22531.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22541.94Skamil "the debuggee with masked signal"); \ 22551.94Skamil} \ 22561.94Skamil \ 22571.94SkamilATF_TC_BODY(test, tc) \ 22581.94Skamil{ \ 22591.94Skamil \ 22601.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22611.94Skamil} 22621.94Skamil 22631.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22641.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22651.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22661.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22671.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22681.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22691.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22701.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22711.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22721.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22731.94Skamil 22741.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22751.94SkamilATF_TC(test); \ 22761.94SkamilATF_TC_HEAD(test, tc) \ 22771.94Skamil{ \ 22781.94Skamil atf_tc_set_md_var(tc, "descr", \ 22791.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22801.94Skamil "the debuggee with signal ignored"); \ 22811.94Skamil} \ 22821.94Skamil \ 22831.94SkamilATF_TC_BODY(test, tc) \ 22841.94Skamil{ \ 22851.94Skamil \ 22861.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22871.94Skamil} 22881.94Skamil 22891.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22901.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22911.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22921.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22931.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22941.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 22951.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22961.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 22971.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22981.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 22991.59Skamil#endif 23001.59Skamil 23011.59Skamil/// ---------------------------------------------------------------------------- 23021.59Skamil 23031.59Skamil#if defined(TWAIT_HAVE_PID) 23041.59Skamilstatic void 23051.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23061.67Skamil bool stopped) 23071.1Skamil{ 23081.51Skamil /* 23091.51Skamil * notimeout - disable timeout in await zombie function 23101.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23111.67Skamil * stopped - attach to a stopped process 23121.51Skamil */ 23131.1Skamil 23141.1Skamil struct msg_fds parent_tracee, parent_tracer; 23151.1Skamil const int exitval_tracee = 5; 23161.1Skamil const int exitval_tracer = 10; 23171.1Skamil pid_t tracee, tracer, wpid; 23181.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23191.1Skamil#if defined(TWAIT_HAVE_STATUS) 23201.1Skamil int status; 23211.1Skamil#endif 23221.1Skamil 23231.67Skamil /* 23241.67Skamil * Only a subset of options are supported. 23251.67Skamil */ 23261.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23271.67Skamil (!notimeout && unrelated && !stopped) || 23281.67Skamil (notimeout && !unrelated && !stopped) || 23291.67Skamil (!notimeout && unrelated && stopped)); 23301.67Skamil 23311.13Schristos DPRINTF("Spawn tracee\n"); 23321.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23331.1Skamil tracee = atf_utils_fork(); 23341.1Skamil if (tracee == 0) { 23351.67Skamil if (stopped) { 23361.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23371.67Skamil raise(SIGSTOP); 23381.67Skamil } 23391.67Skamil 23401.1Skamil // Wait for parent to let us exit 23411.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23421.1Skamil _exit(exitval_tracee); 23431.1Skamil } 23441.1Skamil 23451.13Schristos DPRINTF("Spawn debugger\n"); 23461.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23471.1Skamil tracer = atf_utils_fork(); 23481.1Skamil if (tracer == 0) { 23491.51Skamil if(unrelated) { 23501.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23511.51Skamil tracer = atf_utils_fork(); 23521.51Skamil if (tracer != 0) 23531.51Skamil _exit(exitval_tracer); 23541.51Skamil } 23551.51Skamil 23561.67Skamil if (stopped) { 23571.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23581.67Skamil await_stopped(tracee); 23591.67Skamil } 23601.67Skamil 23611.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23621.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23631.1Skamil 23641.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23651.1Skamil FORKEE_REQUIRE_SUCCESS( 23661.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23671.1Skamil 23681.1Skamil forkee_status_stopped(status, SIGSTOP); 23691.1Skamil 23701.1Skamil /* Resume tracee with PT_CONTINUE */ 23711.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23721.1Skamil 23731.1Skamil /* Inform parent that tracer has attached to tracee */ 23741.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23751.1Skamil 23761.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23771.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23781.1Skamil 23791.1Skamil /* Wait for tracee and assert that it exited */ 23801.1Skamil FORKEE_REQUIRE_SUCCESS( 23811.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23821.1Skamil 23831.1Skamil forkee_status_exited(status, exitval_tracee); 23841.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23851.1Skamil 23861.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23871.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23881.51Skamil } 23891.51Skamil 23901.51Skamil if (unrelated) { 23911.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23921.51Skamil "calling %s()\n", TWAIT_FNAME); 23931.51Skamil TWAIT_REQUIRE_SUCCESS( 23941.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 23951.51Skamil 23961.51Skamil validate_status_exited(status, exitval_tracer); 23971.51Skamil 23981.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 23991.51Skamil TWAIT_FNAME); 24001.51Skamil TWAIT_REQUIRE_SUCCESS( 24011.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24021.1Skamil } 24031.1Skamil 24041.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24051.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24061.1Skamil 24071.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24081.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24091.1Skamil 24101.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24111.51Skamil if (notimeout) 24121.26Skamil await_zombie_raw(tracee, 0); 24131.26Skamil else 24141.26Skamil await_zombie(tracee); 24151.1Skamil 24161.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24171.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24181.1Skamil TWAIT_FNAME); 24191.1Skamil TWAIT_REQUIRE_SUCCESS( 24201.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24211.1Skamil 24221.51Skamil if (unrelated) { 24231.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24241.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24251.51Skamil } else { 24261.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24271.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24281.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24291.59Skamil "%s()\n", TWAIT_FNAME); 24301.51Skamil 24311.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24321.59Skamil "tracee\n"); 24331.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24341.51Skamil tracer); 24351.1Skamil 24361.51Skamil validate_status_exited(status, exitval_tracer); 24371.51Skamil } 24381.1Skamil 24391.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24401.1Skamil TWAIT_FNAME); 24411.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24421.1Skamil 24431.1Skamil validate_status_exited(status, exitval_tracee); 24441.1Skamil 24451.1Skamil msg_close(&parent_tracer); 24461.1Skamil msg_close(&parent_tracee); 24471.1Skamil} 24481.26Skamil 24491.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24501.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24511.51Skamil{ 24521.51Skamil atf_tc_set_md_var(tc, "descr", 24531.51Skamil "Assert that tracer sees process termination before the parent"); 24541.51Skamil} 24551.51Skamil 24561.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24571.26Skamil{ 24581.26Skamil 24591.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24601.26Skamil} 24611.26Skamil 24621.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24631.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24641.1Skamil{ 24651.1Skamil atf_tc_set_md_var(tc, "descr", 24661.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24671.51Skamil "process and no other error is reported"); 24681.1Skamil} 24691.1Skamil 24701.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24711.1Skamil{ 24721.51Skamil time_t start, end; 24731.51Skamil double diff; 24741.51Skamil unsigned long N = 0; 24751.1Skamil 24761.51Skamil /* 24771.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24781.51Skamil * This test body isn't specific to this race, however it's just good 24791.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24801.51Skamil */ 24811.1Skamil 24821.51Skamil start = time(NULL); 24831.51Skamil while (true) { 24841.51Skamil DPRINTF("Step: %lu\n", N); 24851.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24861.67Skamil false); 24871.51Skamil end = time(NULL); 24881.51Skamil diff = difftime(end, start); 24891.51Skamil if (diff >= 5.0) 24901.51Skamil break; 24911.51Skamil ++N; 24921.1Skamil } 24931.51Skamil DPRINTF("Iterations: %lu\n", N); 24941.51Skamil} 24951.1Skamil 24961.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 24971.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24981.51Skamil{ 24991.51Skamil atf_tc_set_md_var(tc, "descr", 25001.51Skamil "Assert that tracer sees process termination before the parent"); 25011.51Skamil} 25021.1Skamil 25031.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25041.51Skamil{ 25051.1Skamil 25061.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25071.67Skamil} 25081.67Skamil 25091.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25101.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25111.67Skamil{ 25121.67Skamil atf_tc_set_md_var(tc, "descr", 25131.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25141.67Skamil} 25151.67Skamil 25161.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25171.67Skamil{ 25181.67Skamil 25191.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25201.1Skamil} 25211.1Skamil#endif 25221.1Skamil 25231.51Skamil/// ---------------------------------------------------------------------------- 25241.51Skamil 25251.66Skamilstatic void 25261.66Skamilparent_attach_to_its_child(bool stopped) 25271.1Skamil{ 25281.1Skamil struct msg_fds parent_tracee; 25291.1Skamil const int exitval_tracee = 5; 25301.1Skamil pid_t tracee, wpid; 25311.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25321.1Skamil#if defined(TWAIT_HAVE_STATUS) 25331.1Skamil int status; 25341.1Skamil#endif 25351.1Skamil 25361.13Schristos DPRINTF("Spawn tracee\n"); 25371.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25381.1Skamil tracee = atf_utils_fork(); 25391.1Skamil if (tracee == 0) { 25401.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25411.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25421.1Skamil 25431.66Skamil if (stopped) { 25441.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25451.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25461.66Skamil } 25471.66Skamil 25481.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25491.1Skamil /* Wait for message from the parent */ 25501.1Skamil _exit(exitval_tracee); 25511.1Skamil } 25521.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25531.57Skamil 25541.66Skamil if (stopped) { 25551.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25561.66Skamil await_stopped(tracee); 25571.66Skamil } 25581.66Skamil 25591.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25601.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25611.1Skamil 25621.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25631.1Skamil TWAIT_FNAME); 25641.1Skamil TWAIT_REQUIRE_SUCCESS( 25651.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25661.1Skamil 25671.1Skamil validate_status_stopped(status, SIGSTOP); 25681.1Skamil 25691.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25701.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25711.1Skamil 25721.13Schristos DPRINTF("Let the tracee exit now\n"); 25731.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25741.1Skamil 25751.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25761.1Skamil TWAIT_REQUIRE_SUCCESS( 25771.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25781.1Skamil 25791.1Skamil validate_status_exited(status, exitval_tracee); 25801.1Skamil 25811.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25821.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25831.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25841.1Skamil 25851.1Skamil msg_close(&parent_tracee); 25861.1Skamil} 25871.1Skamil 25881.66SkamilATF_TC(parent_attach_to_its_child); 25891.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25901.66Skamil{ 25911.66Skamil atf_tc_set_md_var(tc, "descr", 25921.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25931.66Skamil} 25941.66Skamil 25951.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 25961.66Skamil{ 25971.66Skamil 25981.66Skamil parent_attach_to_its_child(false); 25991.66Skamil} 26001.66Skamil 26011.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26021.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26031.66Skamil{ 26041.66Skamil atf_tc_set_md_var(tc, "descr", 26051.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26061.66Skamil} 26071.66Skamil 26081.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26091.66Skamil{ 26101.66Skamil 26111.66Skamil parent_attach_to_its_child(true); 26121.66Skamil} 26131.66Skamil 26141.51Skamil/// ---------------------------------------------------------------------------- 26151.51Skamil 26161.65Skamilstatic void 26171.65Skamilchild_attach_to_its_parent(bool stopped) 26181.1Skamil{ 26191.1Skamil struct msg_fds parent_tracee; 26201.1Skamil const int exitval_tracer = 5; 26211.1Skamil pid_t tracer, wpid; 26221.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26231.1Skamil#if defined(TWAIT_HAVE_STATUS) 26241.1Skamil int status; 26251.1Skamil#endif 26261.1Skamil 26271.13Schristos DPRINTF("Spawn tracer\n"); 26281.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26291.1Skamil tracer = atf_utils_fork(); 26301.1Skamil if (tracer == 0) { 26311.1Skamil /* Wait for message from the parent */ 26321.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26331.1Skamil 26341.65Skamil if (stopped) { 26351.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26361.65Skamil getppid()); 26371.65Skamil await_stopped(getppid()); 26381.65Skamil } 26391.65Skamil 26401.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26411.1Skamil getppid()); 26421.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26431.1Skamil 26441.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26451.1Skamil TWAIT_FNAME); 26461.1Skamil FORKEE_REQUIRE_SUCCESS( 26471.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26481.1Skamil 26491.1Skamil forkee_status_stopped(status, SIGSTOP); 26501.1Skamil 26511.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26521.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26531.1Skamil != -1); 26541.1Skamil 26551.1Skamil /* Tell parent we are ready */ 26561.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26571.1Skamil 26581.1Skamil _exit(exitval_tracer); 26591.1Skamil } 26601.1Skamil 26611.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26621.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26631.65Skamil 26641.65Skamil if (stopped) { 26651.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26661.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26671.65Skamil } 26681.65Skamil 26691.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26701.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26711.1Skamil 26721.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26731.1Skamil TWAIT_REQUIRE_SUCCESS( 26741.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26751.1Skamil 26761.1Skamil validate_status_exited(status, exitval_tracer); 26771.1Skamil 26781.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26791.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26801.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26811.1Skamil 26821.1Skamil msg_close(&parent_tracee); 26831.1Skamil} 26841.1Skamil 26851.65SkamilATF_TC(child_attach_to_its_parent); 26861.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26871.65Skamil{ 26881.65Skamil atf_tc_set_md_var(tc, "descr", 26891.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26901.65Skamil} 26911.65Skamil 26921.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26931.65Skamil{ 26941.65Skamil 26951.65Skamil child_attach_to_its_parent(false); 26961.65Skamil} 26971.65Skamil 26981.65SkamilATF_TC(child_attach_to_its_stopped_parent); 26991.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27001.65Skamil{ 27011.65Skamil atf_tc_set_md_var(tc, "descr", 27021.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27031.65Skamil} 27041.65Skamil 27051.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27061.65Skamil{ 27071.65Skamil /* 27081.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27091.65Skamil * this causes a pipe (established from atf-run) to be broken. 27101.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27111.65Skamil * 27121.65Skamil * As a workaround spawn this test as a subprocess. 27131.65Skamil */ 27141.65Skamil 27151.65Skamil const int exitval = 15; 27161.65Skamil pid_t child, wpid; 27171.65Skamil#if defined(TWAIT_HAVE_STATUS) 27181.65Skamil int status; 27191.65Skamil#endif 27201.65Skamil 27211.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27221.65Skamil if (child == 0) { 27231.65Skamil child_attach_to_its_parent(true); 27241.65Skamil _exit(exitval); 27251.65Skamil } else { 27261.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27271.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27281.65Skamil 27291.65Skamil validate_status_exited(status, exitval); 27301.65Skamil 27311.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27321.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27331.65Skamil } 27341.65Skamil} 27351.65Skamil 27361.51Skamil/// ---------------------------------------------------------------------------- 27371.51Skamil 27381.1Skamil#if defined(TWAIT_HAVE_PID) 27391.1Skamil 27401.51Skamilenum tracee_sees_its_original_parent_type { 27411.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27421.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27431.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27441.51Skamil}; 27451.51Skamil 27461.51Skamilstatic void 27471.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27481.1Skamil{ 27491.1Skamil struct msg_fds parent_tracer, parent_tracee; 27501.1Skamil const int exitval_tracee = 5; 27511.1Skamil const int exitval_tracer = 10; 27521.1Skamil pid_t parent, tracee, tracer, wpid; 27531.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27541.1Skamil#if defined(TWAIT_HAVE_STATUS) 27551.1Skamil int status; 27561.1Skamil#endif 27571.51Skamil /* sysctl(3) - kinfo_proc2 */ 27581.51Skamil int name[CTL_MAXNAME]; 27591.51Skamil struct kinfo_proc2 kp; 27601.51Skamil size_t len = sizeof(kp); 27611.51Skamil unsigned int namelen; 27621.51Skamil 27631.51Skamil /* procfs - status */ 27641.51Skamil FILE *fp; 27651.51Skamil struct stat st; 27661.51Skamil const char *fname = "/proc/curproc/status"; 27671.51Skamil char s_executable[MAXPATHLEN]; 27681.51Skamil int s_pid, s_ppid; 27691.51Skamil int rv; 27701.51Skamil 27711.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27721.61Skre SYSCALL_REQUIRE( 27731.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27741.61Skre if (rv != 0) 27751.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27761.51Skamil } 27771.1Skamil 27781.13Schristos DPRINTF("Spawn tracee\n"); 27791.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27801.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27811.1Skamil tracee = atf_utils_fork(); 27821.1Skamil if (tracee == 0) { 27831.1Skamil parent = getppid(); 27841.1Skamil 27851.1Skamil /* Emit message to the parent */ 27861.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27871.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27881.1Skamil 27891.51Skamil switch (type) { 27901.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27911.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27921.51Skamil break; 27931.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27941.51Skamil namelen = 0; 27951.51Skamil name[namelen++] = CTL_KERN; 27961.51Skamil name[namelen++] = KERN_PROC2; 27971.51Skamil name[namelen++] = KERN_PROC_PID; 27981.51Skamil name[namelen++] = getpid(); 27991.51Skamil name[namelen++] = len; 28001.51Skamil name[namelen++] = 1; 28011.51Skamil 28021.61Skre FORKEE_ASSERT_EQ( 28031.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28041.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28051.51Skamil break; 28061.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28071.51Skamil /* 28081.51Skamil * Format: 28091.51Skamil * EXECUTABLE PID PPID ... 28101.51Skamil */ 28111.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28121.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28131.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28141.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28151.51Skamil break; 28161.51Skamil } 28171.1Skamil 28181.1Skamil _exit(exitval_tracee); 28191.1Skamil } 28201.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28211.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28221.1Skamil 28231.13Schristos DPRINTF("Spawn debugger\n"); 28241.1Skamil tracer = atf_utils_fork(); 28251.1Skamil if (tracer == 0) { 28261.1Skamil /* No IPC to communicate with the child */ 28271.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28281.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28291.1Skamil 28301.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28311.1Skamil FORKEE_REQUIRE_SUCCESS( 28321.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28331.1Skamil 28341.1Skamil forkee_status_stopped(status, SIGSTOP); 28351.1Skamil 28361.1Skamil /* Resume tracee with PT_CONTINUE */ 28371.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28381.1Skamil 28391.1Skamil /* Inform parent that tracer has attached to tracee */ 28401.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28411.1Skamil 28421.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28431.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28441.1Skamil 28451.1Skamil /* Wait for tracee and assert that it exited */ 28461.1Skamil FORKEE_REQUIRE_SUCCESS( 28471.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28481.1Skamil 28491.1Skamil forkee_status_exited(status, exitval_tracee); 28501.1Skamil 28511.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28521.1Skamil _exit(exitval_tracer); 28531.1Skamil } 28541.1Skamil 28551.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28561.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28571.1Skamil 28581.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28591.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28601.1Skamil 28611.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28621.1Skamil await_zombie(tracee); 28631.1Skamil 28641.13Schristos DPRINTF("Assert that there is no status about tracee - " 28651.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28661.1Skamil TWAIT_REQUIRE_SUCCESS( 28671.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28681.1Skamil 28691.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28701.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28711.1Skamil 28721.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28741.1Skamil tracer); 28751.1Skamil 28761.1Skamil validate_status_exited(status, exitval_tracer); 28771.1Skamil 28781.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28791.1Skamil TWAIT_FNAME); 28801.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28811.1Skamil tracee); 28821.1Skamil 28831.1Skamil validate_status_exited(status, exitval_tracee); 28841.1Skamil 28851.1Skamil msg_close(&parent_tracer); 28861.1Skamil msg_close(&parent_tracee); 28871.1Skamil} 28881.1Skamil 28891.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28901.61SkreATF_TC(test); \ 28911.61SkreATF_TC_HEAD(test, tc) \ 28921.61Skre{ \ 28931.61Skre atf_tc_set_md_var(tc, "descr", \ 28941.61Skre "Assert that tracee sees its original parent when being traced " \ 28951.61Skre "(check " descr ")"); \ 28961.61Skre} \ 28971.61Skre \ 28981.61SkreATF_TC_BODY(test, tc) \ 28991.61Skre{ \ 29001.61Skre \ 29011.61Skre tracee_sees_its_original_parent(type); \ 29021.1Skamil} 29031.1Skamil 29041.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29051.51Skamil tracee_sees_its_original_parent_getppid, 29061.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29071.51Skamil "getppid(2)"); 29081.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29091.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29101.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29111.51Skamil "sysctl(3) and kinfo_proc2"); 29121.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29131.51Skamil tracee_sees_its_original_parent_procfs_status, 29141.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29151.51Skamil "the status file in procfs"); 29161.1Skamil#endif 29171.1Skamil 29181.51Skamil/// ---------------------------------------------------------------------------- 29191.1Skamil 29201.53Skamilstatic void 29211.53Skamileventmask_preserved(int event) 29221.1Skamil{ 29231.1Skamil const int exitval = 5; 29241.1Skamil const int sigval = SIGSTOP; 29251.1Skamil pid_t child, wpid; 29261.1Skamil#if defined(TWAIT_HAVE_STATUS) 29271.1Skamil int status; 29281.1Skamil#endif 29291.1Skamil ptrace_event_t set_event, get_event; 29301.1Skamil const int len = sizeof(ptrace_event_t); 29311.1Skamil 29321.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29331.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29341.1Skamil if (child == 0) { 29351.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29361.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29371.1Skamil 29381.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29391.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29401.1Skamil 29411.13Schristos DPRINTF("Before exiting of the child process\n"); 29421.1Skamil _exit(exitval); 29431.1Skamil } 29441.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29451.1Skamil 29461.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29481.1Skamil 29491.1Skamil validate_status_stopped(status, sigval); 29501.1Skamil 29511.53Skamil set_event.pe_set_event = event; 29521.61Skre SYSCALL_REQUIRE( 29531.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29541.61Skre SYSCALL_REQUIRE( 29551.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29561.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29571.125Skamil get_event.pe_set_event); 29581.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29591.1Skamil 29601.13Schristos DPRINTF("Before resuming the child process where it left off and " 29611.1Skamil "without signal to be sent\n"); 29621.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29631.1Skamil 29641.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29651.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29661.1Skamil 29671.1Skamil validate_status_exited(status, exitval); 29681.1Skamil 29691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29701.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29711.1Skamil} 29721.1Skamil 29731.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29741.61SkreATF_TC(test); \ 29751.61SkreATF_TC_HEAD(test, tc) \ 29761.61Skre{ \ 29771.61Skre atf_tc_set_md_var(tc, "descr", \ 29781.61Skre "Verify that eventmask " #event " is preserved"); \ 29791.61Skre} \ 29801.61Skre \ 29811.61SkreATF_TC_BODY(test, tc) \ 29821.61Skre{ \ 29831.61Skre \ 29841.61Skre eventmask_preserved(event); \ 29851.1Skamil} 29861.1Skamil 29871.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29881.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29891.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29901.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29911.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29921.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29931.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 29941.1Skamil 29951.53Skamil/// ---------------------------------------------------------------------------- 29961.1Skamil 29971.28Skamilstatic void 29981.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 29991.105Skamil bool trackvforkdone) 30001.1Skamil{ 30011.1Skamil const int exitval = 5; 30021.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30031.1Skamil const int sigval = SIGSTOP; 30041.31Skamil pid_t child, child2 = 0, wpid; 30051.1Skamil#if defined(TWAIT_HAVE_STATUS) 30061.1Skamil int status; 30071.1Skamil#endif 30081.1Skamil ptrace_state_t state; 30091.1Skamil const int slen = sizeof(state); 30101.1Skamil ptrace_event_t event; 30111.1Skamil const int elen = sizeof(event); 30121.1Skamil 30131.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30141.124Skamil 30151.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30161.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30171.1Skamil if (child == 0) { 30181.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30191.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30201.1Skamil 30211.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30221.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30231.1Skamil 30241.125Skamil if (strcmp(fn, "spawn") == 0) { 30251.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30261.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30271.125Skamil } else { 30281.125Skamil if (strcmp(fn, "fork") == 0) { 30291.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30301.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30311.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30321.125Skamil } 30331.1Skamil 30341.124Skamil if (child2 == 0) 30351.124Skamil _exit(exitval2); 30361.124Skamil } 30371.1Skamil FORKEE_REQUIRE_SUCCESS 30381.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30391.1Skamil 30401.1Skamil forkee_status_exited(status, exitval2); 30411.1Skamil 30421.13Schristos DPRINTF("Before exiting of the child process\n"); 30431.1Skamil _exit(exitval); 30441.1Skamil } 30451.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30461.1Skamil 30471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30491.1Skamil 30501.1Skamil validate_status_stopped(status, sigval); 30511.1Skamil 30521.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30531.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30541.61Skre trackfork ? "|PTRACE_FORK" : "", 30551.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30561.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30571.30Skamil event.pe_set_event = 0; 30581.125Skamil if (trackspawn) 30591.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30601.30Skamil if (trackfork) 30611.30Skamil event.pe_set_event |= PTRACE_FORK; 30621.30Skamil if (trackvfork) 30631.30Skamil event.pe_set_event |= PTRACE_VFORK; 30641.30Skamil if (trackvforkdone) 30651.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30661.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30671.1Skamil 30681.13Schristos DPRINTF("Before resuming the child process where it left off and " 30691.1Skamil "without signal to be sent\n"); 30701.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30711.1Skamil 30721.29Skamil#if defined(TWAIT_HAVE_PID) 30731.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 30741.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 30751.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 30761.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30771.61Skre child); 30781.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30791.61Skre child); 30801.1Skamil 30811.29Skamil validate_status_stopped(status, SIGTRAP); 30821.1Skamil 30831.61Skre SYSCALL_REQUIRE( 30841.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30851.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 30861.125Skamil ATF_REQUIRE_EQ( 30871.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 30881.125Skamil PTRACE_POSIX_SPAWN); 30891.125Skamil } 30901.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 30911.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30921.30Skamil PTRACE_FORK); 30931.30Skamil } 30941.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 30951.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30961.30Skamil PTRACE_VFORK); 30971.30Skamil } 30981.29Skamil 30991.29Skamil child2 = state.pe_other_pid; 31001.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31011.29Skamil 31021.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31031.61Skre "%d\n", TWAIT_FNAME, child2, child); 31041.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31051.29Skamil child2); 31061.1Skamil 31071.29Skamil validate_status_stopped(status, SIGTRAP); 31081.1Skamil 31091.61Skre SYSCALL_REQUIRE( 31101.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31111.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31121.125Skamil ATF_REQUIRE_EQ( 31131.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31141.125Skamil PTRACE_POSIX_SPAWN); 31151.125Skamil } 31161.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31171.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31181.30Skamil PTRACE_FORK); 31191.30Skamil } 31201.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31211.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31221.30Skamil PTRACE_VFORK); 31231.30Skamil } 31241.30Skamil 31251.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31261.29Skamil 31271.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31281.29Skamil "and without signal to be sent\n"); 31291.61Skre SYSCALL_REQUIRE( 31301.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31311.29Skamil 31321.29Skamil DPRINTF("Before resuming the child process where it left off " 31331.61Skre "and without signal to be sent\n"); 31341.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31351.30Skamil } 31361.30Skamil#endif 31371.30Skamil 31381.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31391.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31401.61Skre child); 31411.61Skre TWAIT_REQUIRE_SUCCESS( 31421.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31431.30Skamil 31441.30Skamil validate_status_stopped(status, SIGTRAP); 31451.30Skamil 31461.61Skre SYSCALL_REQUIRE( 31471.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31481.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31491.30Skamil 31501.30Skamil child2 = state.pe_other_pid; 31511.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31521.61Skre child2); 31531.30Skamil 31541.30Skamil DPRINTF("Before resuming the child process where it left off " 31551.61Skre "and without signal to be sent\n"); 31561.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31571.30Skamil } 31581.29Skamil 31591.30Skamil#if defined(TWAIT_HAVE_PID) 31601.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31611.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31621.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31631.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31641.61Skre "\n", TWAIT_FNAME); 31651.61Skre TWAIT_REQUIRE_SUCCESS( 31661.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31671.29Skamil 31681.29Skamil validate_status_exited(status, exitval2); 31691.29Skamil 31701.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31711.61Skre "process\n", TWAIT_FNAME); 31721.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31731.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31741.29Skamil } 31751.29Skamil#endif 31761.1Skamil 31771.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31781.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31801.1Skamil 31811.1Skamil validate_status_stopped(status, SIGCHLD); 31821.1Skamil 31831.13Schristos DPRINTF("Before resuming the child process where it left off and " 31841.1Skamil "without signal to be sent\n"); 31851.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31861.1Skamil 31871.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31881.1Skamil TWAIT_FNAME); 31891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31901.1Skamil 31911.1Skamil validate_status_exited(status, exitval); 31921.1Skamil 31931.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31941.1Skamil TWAIT_FNAME); 31951.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 31961.1Skamil} 31971.28Skamil 31981.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 31991.61SkreATF_TC(name); \ 32001.61SkreATF_TC_HEAD(name, tc) \ 32011.61Skre{ \ 32021.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32031.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32041.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32051.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32061.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32071.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32081.61Skre} \ 32091.61Skre \ 32101.61SkreATF_TC_BODY(name, tc) \ 32111.61Skre{ \ 32121.61Skre \ 32131.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32141.32Skamil} 32151.32Skamil 32161.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32171.31Skamil#if defined(TWAIT_HAVE_PID) 32181.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32191.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32201.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32211.31Skamil#endif 32221.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32231.31Skamil#if defined(TWAIT_HAVE_PID) 32241.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32251.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32261.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32271.125Skamil#endif 32281.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32291.125Skamil#if defined(TWAIT_HAVE_PID) 32301.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32311.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32321.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32331.125Skamil#endif 32341.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32351.125Skamil#if defined(TWAIT_HAVE_PID) 32361.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32371.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32381.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32391.31Skamil#endif 32401.1Skamil 32411.110Skamil#if TEST_VFORK_ENABLED 32421.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32431.31Skamil#if defined(TWAIT_HAVE_PID) 32441.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32451.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32461.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32471.31Skamil#endif 32481.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32491.31Skamil#if defined(TWAIT_HAVE_PID) 32501.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32511.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32521.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32531.31Skamil#endif 32541.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32551.125Skamil#if defined(TWAIT_HAVE_PID) 32561.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32571.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32581.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32591.110Skamil#endif 32601.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32611.124Skamil#if defined(TWAIT_HAVE_PID) 32621.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32631.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32641.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32651.124Skamil#endif 32661.125Skamil#endif 32671.125Skamil 32681.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32691.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32701.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32711.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32721.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32731.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32741.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32751.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 32761.124Skamil#if defined(TWAIT_HAVE_PID) 32771.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 32781.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 32791.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 32801.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 32811.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 32821.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 32831.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 32841.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 32851.124Skamil#endif 32861.124Skamil 32871.54Skamil/// ---------------------------------------------------------------------------- 32881.31Skamil 32891.116Skamil#if defined(TWAIT_HAVE_PID) 32901.116Skamilstatic void 32911.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 32921.116Skamil{ 32931.116Skamil const int exitval = 5; 32941.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 32951.116Skamil const int sigval = SIGSTOP; 32961.116Skamil pid_t child, child2 = 0, wpid; 32971.116Skamil#if defined(TWAIT_HAVE_STATUS) 32981.116Skamil int status; 32991.116Skamil#endif 33001.116Skamil ptrace_state_t state; 33011.116Skamil const int slen = sizeof(state); 33021.116Skamil ptrace_event_t event; 33031.116Skamil const int elen = sizeof(event); 33041.116Skamil 33051.116Skamil int op; 33061.116Skamil 33071.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33081.116Skamil 33091.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33101.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 33111.116Skamil if (child == 0) { 33121.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33131.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33141.116Skamil 33151.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33161.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 33171.116Skamil 33181.126Skamil if (strcmp(fn, "spawn") == 0) { 33191.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 33201.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 33211.126Skamil } else { 33221.126Skamil if (strcmp(fn, "fork") == 0) { 33231.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 33241.126Skamil } else { 33251.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 33261.126Skamil } 33271.116Skamil 33281.126Skamil if (child2 == 0) 33291.126Skamil _exit(exitval2); 33301.126Skamil } 33311.116Skamil 33321.116Skamil FORKEE_REQUIRE_SUCCESS 33331.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33341.116Skamil 33351.116Skamil forkee_status_exited(status, exitval2); 33361.116Skamil 33371.116Skamil DPRINTF("Before exiting of the child process\n"); 33381.116Skamil _exit(exitval); 33391.116Skamil } 33401.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33411.116Skamil 33421.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33431.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33441.116Skamil 33451.116Skamil validate_status_stopped(status, sigval); 33461.116Skamil 33471.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 33481.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 33491.126Skamil | PTRACE_VFORK_DONE; 33501.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 33511.116Skamil 33521.116Skamil DPRINTF("Before resuming the child process where it left off and " 33531.116Skamil "without signal to be sent\n"); 33541.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 33551.116Skamil 33561.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 33571.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33581.116Skamil 33591.116Skamil validate_status_stopped(status, SIGTRAP); 33601.116Skamil 33611.116Skamil SYSCALL_REQUIRE( 33621.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33631.126Skamil 33641.126Skamil if (strcmp(fn, "spawn") == 0) 33651.126Skamil op = PTRACE_POSIX_SPAWN; 33661.126Skamil else if (strcmp(fn, "fork") == 0) 33671.126Skamil op = PTRACE_FORK; 33681.126Skamil else 33691.126Skamil op = PTRACE_VFORK; 33701.126Skamil 33711.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33721.116Skamil 33731.116Skamil child2 = state.pe_other_pid; 33741.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 33751.116Skamil 33761.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 33771.126Skamil strcmp(fn, "vfork") == 0) 33781.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33791.116Skamil else 33801.116Skamil op = PT_CONTINUE; 33811.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 33821.116Skamil 33831.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 33841.116Skamil TWAIT_FNAME, child2, child); 33851.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33861.116Skamil 33871.116Skamil validate_status_stopped(status, SIGTRAP); 33881.116Skamil 33891.116Skamil SYSCALL_REQUIRE( 33901.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 33911.126Skamil if (strcmp(fn, "spawn") == 0) 33921.126Skamil op = PTRACE_POSIX_SPAWN; 33931.126Skamil else if (strcmp(fn, "fork") == 0) 33941.126Skamil op = PTRACE_FORK; 33951.126Skamil else 33961.126Skamil op = PTRACE_VFORK; 33971.126Skamil 33981.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33991.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 34001.116Skamil 34011.116Skamil DPRINTF("Before resuming the forkee process where it left off " 34021.116Skamil "and without signal to be sent\n"); 34031.116Skamil SYSCALL_REQUIRE( 34041.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 34051.116Skamil 34061.126Skamil if (strcmp(fn, "vforkdone") == 0) { 34071.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 34081.116Skamil child); 34091.116Skamil TWAIT_REQUIRE_SUCCESS( 34101.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 34111.116Skamil 34121.116Skamil validate_status_stopped(status, SIGTRAP); 34131.116Skamil 34141.116Skamil SYSCALL_REQUIRE( 34151.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 34161.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 34171.116Skamil 34181.116Skamil child2 = state.pe_other_pid; 34191.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 34201.116Skamil child2); 34211.116Skamil 34221.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34231.116Skamil DPRINTF("Before resuming the child process where it left off " 34241.116Skamil "and without signal to be sent\n"); 34251.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34261.116Skamil } 34271.116Skamil 34281.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34291.116Skamil TWAIT_FNAME); 34301.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34311.116Skamil 34321.116Skamil validate_status_exited(status, exitval2); 34331.116Skamil 34341.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 34351.116Skamil TWAIT_FNAME); 34361.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 34371.116Skamil 34381.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34391.116Skamil TWAIT_FNAME); 34401.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34411.116Skamil 34421.116Skamil if (kill_process) { 34431.116Skamil validate_status_signaled(status, SIGKILL, 0); 34441.116Skamil } else { 34451.116Skamil validate_status_exited(status, exitval); 34461.116Skamil } 34471.116Skamil 34481.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34491.116Skamil TWAIT_FNAME); 34501.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34511.116Skamil} 34521.116Skamil 34531.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 34541.116SkamilATF_TC(name); \ 34551.116SkamilATF_TC_HEAD(name, tc) \ 34561.116Skamil{ \ 34571.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 34581.126Skamil kprocess ? "killed" : "detached"); \ 34591.116Skamil} \ 34601.116Skamil \ 34611.116SkamilATF_TC_BODY(name, tc) \ 34621.116Skamil{ \ 34631.116Skamil \ 34641.126Skamil fork_detach_forker_body(event, kprocess); \ 34651.116Skamil} 34661.116Skamil 34671.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 34681.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 34691.116Skamil#if TEST_VFORK_ENABLED 34701.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 34711.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 34721.116Skamil#endif 34731.126Skamil 34741.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 34751.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 34761.116Skamil#if TEST_VFORK_ENABLED 34771.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 34781.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 34791.116Skamil#endif 34801.116Skamil#endif 34811.116Skamil 34821.116Skamil/// ---------------------------------------------------------------------------- 34831.116Skamil 34841.110Skamil#if TEST_VFORK_ENABLED 34851.108Skamilstatic void 34861.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 34871.108Skamil{ 34881.108Skamil const int exitval = 5; 34891.108Skamil const int exitval2 = 15; 34901.108Skamil pid_t child, child2 = 0, wpid; 34911.108Skamil#if defined(TWAIT_HAVE_STATUS) 34921.108Skamil int status; 34931.108Skamil#endif 34941.108Skamil 34951.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 34961.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 34971.108Skamil if (child == 0) { 34981.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 34991.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 35001.108Skamil 35011.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 35021.108Skamil 35031.108Skamil if (child2 == 0) 35041.108Skamil _exit(exitval2); 35051.108Skamil 35061.108Skamil FORKEE_REQUIRE_SUCCESS 35071.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 35081.108Skamil 35091.108Skamil forkee_status_exited(status, exitval2); 35101.108Skamil 35111.108Skamil DPRINTF("Before exiting of the child process\n"); 35121.108Skamil _exit(exitval); 35131.108Skamil } 35141.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35151.108Skamil 35161.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 35171.108Skamil TWAIT_FNAME); 35181.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35191.108Skamil 35201.108Skamil validate_status_exited(status, exitval); 35211.108Skamil 35221.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 35231.108Skamil TWAIT_FNAME); 35241.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35251.108Skamil} 35261.108Skamil 35271.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 35281.108SkamilATF_TC(name); \ 35291.108SkamilATF_TC_HEAD(name, tc) \ 35301.108Skamil{ \ 35311.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 35321.108Skamil "called from vfork(2)ed child"); \ 35331.108Skamil} \ 35341.108Skamil \ 35351.108SkamilATF_TC_BODY(name, tc) \ 35361.108Skamil{ \ 35371.108Skamil \ 35381.108Skamil traceme_vfork_fork_body(fun); \ 35391.108Skamil} 35401.108Skamil 35411.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 35421.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 35431.110Skamil#endif 35441.108Skamil 35451.108Skamil/// ---------------------------------------------------------------------------- 35461.108Skamil 35471.54Skamilenum bytes_transfer_type { 35481.54Skamil BYTES_TRANSFER_DATA, 35491.54Skamil BYTES_TRANSFER_DATAIO, 35501.54Skamil BYTES_TRANSFER_TEXT, 35511.54Skamil BYTES_TRANSFER_TEXTIO, 35521.54Skamil BYTES_TRANSFER_AUXV 35531.54Skamil}; 35541.31Skamil 35551.54Skamilstatic int __used 35561.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 35571.54Skamil{ 35581.54Skamil int e, f, g, h; 35591.1Skamil 35601.54Skamil a *= 4; 35611.54Skamil b += 3; 35621.54Skamil c -= 2; 35631.54Skamil d /= 1; 35641.1Skamil 35651.54Skamil e = strtol("10", NULL, 10); 35661.54Skamil f = strtol("20", NULL, 10); 35671.54Skamil g = strtol("30", NULL, 10); 35681.54Skamil h = strtol("40", NULL, 10); 35691.1Skamil 35701.54Skamil return (a + b * c - d) + (e * f - g / h); 35711.1Skamil} 35721.1Skamil 35731.54Skamilstatic void 35741.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 35751.1Skamil{ 35761.1Skamil const int exitval = 5; 35771.1Skamil const int sigval = SIGSTOP; 35781.1Skamil pid_t child, wpid; 35791.54Skamil bool skip = false; 35801.1Skamil 35811.54Skamil int lookup_me = 0; 35821.54Skamil uint8_t lookup_me8 = 0; 35831.54Skamil uint16_t lookup_me16 = 0; 35841.54Skamil uint32_t lookup_me32 = 0; 35851.54Skamil uint64_t lookup_me64 = 0; 35861.1Skamil 35871.54Skamil int magic = 0x13579246; 35881.54Skamil uint8_t magic8 = 0xab; 35891.54Skamil uint16_t magic16 = 0x1234; 35901.54Skamil uint32_t magic32 = 0x98765432; 35911.54Skamil uint64_t magic64 = 0xabcdef0123456789; 35921.1Skamil 35931.54Skamil struct ptrace_io_desc io; 35941.1Skamil#if defined(TWAIT_HAVE_STATUS) 35951.1Skamil int status; 35961.1Skamil#endif 35971.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 35981.60Skre AuxInfo ai[513], *aip; 35991.55Schristos 36001.55Schristos ATF_REQUIRE(size < sizeof(ai)); 36011.1Skamil 36021.54Skamil /* Prepare variables for .TEXT transfers */ 36031.54Skamil switch (type) { 36041.54Skamil case BYTES_TRANSFER_TEXT: 36051.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 36061.54Skamil break; 36071.54Skamil case BYTES_TRANSFER_TEXTIO: 36081.54Skamil switch (size) { 36091.54Skamil case 8: 36101.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 36111.54Skamil break; 36121.54Skamil case 16: 36131.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 36141.54Skamil break; 36151.54Skamil case 32: 36161.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 36171.54Skamil break; 36181.54Skamil case 64: 36191.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 36201.54Skamil break; 36211.54Skamil } 36221.54Skamil break; 36231.54Skamil default: 36241.54Skamil break; 36251.54Skamil } 36261.1Skamil 36271.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 36281.54Skamil switch (type) { 36291.54Skamil case BYTES_TRANSFER_TEXTIO: 36301.54Skamil case BYTES_TRANSFER_DATAIO: 36311.54Skamil io.piod_op = operation; 36321.54Skamil switch (size) { 36331.54Skamil case 8: 36341.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36351.54Skamil (void *)bytes_transfer_dummy : 36361.54Skamil &lookup_me8; 36371.54Skamil io.piod_addr = &lookup_me8; 36381.54Skamil io.piod_len = sizeof(lookup_me8); 36391.54Skamil break; 36401.54Skamil case 16: 36411.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36421.54Skamil (void *)bytes_transfer_dummy : 36431.54Skamil &lookup_me16; 36441.54Skamil io.piod_addr = &lookup_me16; 36451.54Skamil io.piod_len = sizeof(lookup_me16); 36461.54Skamil break; 36471.54Skamil case 32: 36481.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36491.54Skamil (void *)bytes_transfer_dummy : 36501.54Skamil &lookup_me32; 36511.54Skamil io.piod_addr = &lookup_me32; 36521.54Skamil io.piod_len = sizeof(lookup_me32); 36531.54Skamil break; 36541.54Skamil case 64: 36551.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36561.54Skamil (void *)bytes_transfer_dummy : 36571.54Skamil &lookup_me64; 36581.54Skamil io.piod_addr = &lookup_me64; 36591.54Skamil io.piod_len = sizeof(lookup_me64); 36601.54Skamil break; 36611.54Skamil default: 36621.54Skamil break; 36631.54Skamil } 36641.54Skamil break; 36651.54Skamil case BYTES_TRANSFER_AUXV: 36661.54Skamil io.piod_op = operation; 36671.54Skamil io.piod_offs = 0; 36681.54Skamil io.piod_addr = ai; 36691.54Skamil io.piod_len = size; 36701.54Skamil break; 36711.54Skamil default: 36721.54Skamil break; 36731.1Skamil } 36741.1Skamil 36751.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36761.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36771.1Skamil if (child == 0) { 36781.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36791.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36801.1Skamil 36811.54Skamil switch (type) { 36821.54Skamil case BYTES_TRANSFER_DATA: 36831.54Skamil switch (operation) { 36841.54Skamil case PT_READ_D: 36851.54Skamil case PT_READ_I: 36861.54Skamil lookup_me = magic; 36871.54Skamil break; 36881.54Skamil default: 36891.54Skamil break; 36901.54Skamil } 36911.54Skamil break; 36921.54Skamil case BYTES_TRANSFER_DATAIO: 36931.54Skamil switch (operation) { 36941.54Skamil case PIOD_READ_D: 36951.54Skamil case PIOD_READ_I: 36961.54Skamil switch (size) { 36971.54Skamil case 8: 36981.54Skamil lookup_me8 = magic8; 36991.54Skamil break; 37001.54Skamil case 16: 37011.54Skamil lookup_me16 = magic16; 37021.54Skamil break; 37031.54Skamil case 32: 37041.54Skamil lookup_me32 = magic32; 37051.54Skamil break; 37061.54Skamil case 64: 37071.54Skamil lookup_me64 = magic64; 37081.54Skamil break; 37091.54Skamil default: 37101.54Skamil break; 37111.54Skamil } 37121.54Skamil break; 37131.54Skamil default: 37141.54Skamil break; 37151.54Skamil } 37161.54Skamil default: 37171.54Skamil break; 37181.54Skamil } 37191.54Skamil 37201.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37211.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37221.1Skamil 37231.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 37241.54Skamil switch (type) { 37251.54Skamil case BYTES_TRANSFER_DATA: 37261.54Skamil switch (operation) { 37271.54Skamil case PT_WRITE_D: 37281.54Skamil case PT_WRITE_I: 37291.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 37301.54Skamil break; 37311.54Skamil default: 37321.54Skamil break; 37331.54Skamil } 37341.54Skamil break; 37351.54Skamil case BYTES_TRANSFER_DATAIO: 37361.54Skamil switch (operation) { 37371.54Skamil case PIOD_WRITE_D: 37381.54Skamil case PIOD_WRITE_I: 37391.54Skamil switch (size) { 37401.54Skamil case 8: 37411.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 37421.54Skamil break; 37431.54Skamil case 16: 37441.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 37451.54Skamil break; 37461.54Skamil case 32: 37471.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 37481.54Skamil break; 37491.54Skamil case 64: 37501.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 37511.54Skamil break; 37521.54Skamil default: 37531.54Skamil break; 37541.54Skamil } 37551.54Skamil break; 37561.54Skamil default: 37571.54Skamil break; 37581.54Skamil } 37591.54Skamil break; 37601.54Skamil case BYTES_TRANSFER_TEXT: 37611.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 37621.54Skamil sizeof(magic)) == 0); 37631.54Skamil break; 37641.54Skamil case BYTES_TRANSFER_TEXTIO: 37651.54Skamil switch (size) { 37661.54Skamil case 8: 37671.54Skamil FORKEE_ASSERT(memcmp(&magic8, 37681.54Skamil bytes_transfer_dummy, 37691.54Skamil sizeof(magic8)) == 0); 37701.54Skamil break; 37711.54Skamil case 16: 37721.54Skamil FORKEE_ASSERT(memcmp(&magic16, 37731.54Skamil bytes_transfer_dummy, 37741.54Skamil sizeof(magic16)) == 0); 37751.54Skamil break; 37761.54Skamil case 32: 37771.54Skamil FORKEE_ASSERT(memcmp(&magic32, 37781.54Skamil bytes_transfer_dummy, 37791.54Skamil sizeof(magic32)) == 0); 37801.54Skamil break; 37811.54Skamil case 64: 37821.54Skamil FORKEE_ASSERT(memcmp(&magic64, 37831.54Skamil bytes_transfer_dummy, 37841.54Skamil sizeof(magic64)) == 0); 37851.54Skamil break; 37861.54Skamil } 37871.54Skamil break; 37881.54Skamil default: 37891.54Skamil break; 37901.54Skamil } 37911.54Skamil 37921.13Schristos DPRINTF("Before exiting of the child process\n"); 37931.1Skamil _exit(exitval); 37941.1Skamil } 37951.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37961.1Skamil 37971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37991.1Skamil 38001.1Skamil validate_status_stopped(status, sigval); 38011.1Skamil 38021.54Skamil /* Check PaX MPROTECT */ 38031.54Skamil if (!can_we_write_to_text(child)) { 38041.54Skamil switch (type) { 38051.54Skamil case BYTES_TRANSFER_TEXTIO: 38061.54Skamil switch (operation) { 38071.54Skamil case PIOD_WRITE_D: 38081.54Skamil case PIOD_WRITE_I: 38091.54Skamil skip = true; 38101.54Skamil break; 38111.54Skamil default: 38121.54Skamil break; 38131.54Skamil } 38141.54Skamil break; 38151.54Skamil case BYTES_TRANSFER_TEXT: 38161.54Skamil switch (operation) { 38171.54Skamil case PT_WRITE_D: 38181.54Skamil case PT_WRITE_I: 38191.54Skamil skip = true; 38201.54Skamil break; 38211.54Skamil default: 38221.54Skamil break; 38231.54Skamil } 38241.54Skamil break; 38251.54Skamil default: 38261.54Skamil break; 38271.54Skamil } 38281.54Skamil } 38291.1Skamil 38301.54Skamil /* Bailout cleanly killing the child process */ 38311.54Skamil if (skip) { 38321.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 38331.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38341.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38351.54Skamil child); 38361.1Skamil 38371.54Skamil validate_status_signaled(status, SIGKILL, 0); 38381.1Skamil 38391.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 38401.54Skamil } 38411.1Skamil 38421.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 38431.54Skamil "parent=%d\n", child, getpid()); 38441.1Skamil 38451.54Skamil switch (type) { 38461.54Skamil case BYTES_TRANSFER_TEXTIO: 38471.54Skamil case BYTES_TRANSFER_DATAIO: 38481.54Skamil case BYTES_TRANSFER_AUXV: 38491.54Skamil switch (operation) { 38501.54Skamil case PIOD_WRITE_D: 38511.54Skamil case PIOD_WRITE_I: 38521.54Skamil switch (size) { 38531.54Skamil case 8: 38541.54Skamil lookup_me8 = magic8; 38551.54Skamil break; 38561.54Skamil case 16: 38571.54Skamil lookup_me16 = magic16; 38581.54Skamil break; 38591.54Skamil case 32: 38601.54Skamil lookup_me32 = magic32; 38611.54Skamil break; 38621.54Skamil case 64: 38631.54Skamil lookup_me64 = magic64; 38641.54Skamil break; 38651.54Skamil default: 38661.54Skamil break; 38671.54Skamil } 38681.54Skamil break; 38691.54Skamil default: 38701.54Skamil break; 38711.54Skamil } 38721.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 38731.54Skamil switch (operation) { 38741.54Skamil case PIOD_READ_D: 38751.54Skamil case PIOD_READ_I: 38761.54Skamil switch (size) { 38771.54Skamil case 8: 38781.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 38791.54Skamil break; 38801.54Skamil case 16: 38811.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 38821.54Skamil break; 38831.54Skamil case 32: 38841.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 38851.54Skamil break; 38861.54Skamil case 64: 38871.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 38881.54Skamil break; 38891.54Skamil default: 38901.54Skamil break; 38911.54Skamil } 38921.54Skamil break; 38931.54Skamil case PIOD_READ_AUXV: 38941.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 38951.54Skamil io.piod_len); 38961.54Skamil ATF_REQUIRE(io.piod_len > 0); 38971.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 38981.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 38991.54Skamil (long long int)aip->a_type, 39001.54Skamil (long long int)aip->a_v); 39011.54Skamil break; 39021.54Skamil default: 39031.54Skamil break; 39041.54Skamil } 39051.54Skamil break; 39061.54Skamil case BYTES_TRANSFER_TEXT: 39071.54Skamil switch (operation) { 39081.54Skamil case PT_READ_D: 39091.54Skamil case PT_READ_I: 39101.54Skamil errno = 0; 39111.54Skamil lookup_me = ptrace(operation, child, 39121.54Skamil bytes_transfer_dummy, 0); 39131.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39141.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39151.54Skamil break; 39161.54Skamil case PT_WRITE_D: 39171.54Skamil case PT_WRITE_I: 39181.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 39191.54Skamil bytes_transfer_dummy, magic) 39201.54Skamil != -1); 39211.54Skamil break; 39221.54Skamil default: 39231.54Skamil break; 39241.54Skamil } 39251.54Skamil break; 39261.54Skamil case BYTES_TRANSFER_DATA: 39271.54Skamil switch (operation) { 39281.54Skamil case PT_READ_D: 39291.54Skamil case PT_READ_I: 39301.54Skamil errno = 0; 39311.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 39321.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39331.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39341.54Skamil break; 39351.54Skamil case PT_WRITE_D: 39361.54Skamil case PT_WRITE_I: 39371.54Skamil lookup_me = magic; 39381.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 39391.54Skamil magic) != -1); 39401.54Skamil break; 39411.54Skamil default: 39421.54Skamil break; 39431.54Skamil } 39441.54Skamil break; 39451.54Skamil default: 39461.54Skamil break; 39471.54Skamil } 39481.1Skamil 39491.13Schristos DPRINTF("Before resuming the child process where it left off and " 39501.1Skamil "without signal to be sent\n"); 39511.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39521.1Skamil 39531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39551.1Skamil 39561.1Skamil validate_status_exited(status, exitval); 39571.1Skamil 39581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39591.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39601.1Skamil} 39611.1Skamil 39621.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 39631.61SkreATF_TC(test); \ 39641.61SkreATF_TC_HEAD(test, tc) \ 39651.61Skre{ \ 39661.61Skre atf_tc_set_md_var(tc, "descr", \ 39671.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 39681.61Skre " of type " #type); \ 39691.61Skre} \ 39701.61Skre \ 39711.61SkreATF_TC_BODY(test, tc) \ 39721.61Skre{ \ 39731.61Skre \ 39741.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 39751.1Skamil} 39761.1Skamil 39771.54Skamil// DATA 39781.1Skamil 39791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 39801.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 39811.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 39821.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 39831.54Skamil 39841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 39851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 39861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 39871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 39881.54Skamil 39891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 39901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 39911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 39921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 39931.54Skamil 39941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 39951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 39961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 39971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 39981.54Skamil 39991.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 40001.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 40011.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 40021.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 40031.54Skamil 40041.54Skamil// TEXT 40051.54Skamil 40061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 40071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 40081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 40091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 40101.54Skamil 40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 40131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 40141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 40151.54Skamil 40161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 40171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 40181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 40191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 40201.54Skamil 40211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 40221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 40231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 40241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 40251.54Skamil 40261.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 40271.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 40281.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 40291.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 40301.1Skamil 40311.54Skamil// AUXV 40321.1Skamil 40331.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 40341.1Skamil 40351.54Skamil/// ---------------------------------------------------------------------------- 40361.1Skamil 40371.101Skamilstatic void 40381.101Skamilbytes_transfer_alignment(const char *operation) 40391.101Skamil{ 40401.101Skamil const int exitval = 5; 40411.101Skamil const int sigval = SIGSTOP; 40421.101Skamil pid_t child, wpid; 40431.101Skamil#if defined(TWAIT_HAVE_STATUS) 40441.101Skamil int status; 40451.101Skamil#endif 40461.101Skamil char *buffer; 40471.101Skamil int vector; 40481.101Skamil size_t len; 40491.101Skamil size_t i; 40501.101Skamil int op; 40511.101Skamil 40521.101Skamil struct ptrace_io_desc io; 40531.101Skamil struct ptrace_siginfo info; 40541.101Skamil 40551.101Skamil memset(&io, 0, sizeof(io)); 40561.101Skamil memset(&info, 0, sizeof(info)); 40571.101Skamil 40581.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 40591.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 40601.101Skamil buffer = malloc(len); 40611.101Skamil ATF_REQUIRE(buffer != NULL); 40621.101Skamil 40631.101Skamil /* Initialize the buffer with random data */ 40641.101Skamil for (i = 0; i < len; i++) 40651.101Skamil buffer[i] = i & 0xff; 40661.101Skamil 40671.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 40681.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 40691.101Skamil if (child == 0) { 40701.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40711.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40721.101Skamil 40731.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40741.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 40751.101Skamil 40761.101Skamil DPRINTF("Before exiting of the child process\n"); 40771.101Skamil _exit(exitval); 40781.101Skamil } 40791.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 40801.101Skamil 40811.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40821.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40831.101Skamil 40841.101Skamil validate_status_stopped(status, sigval); 40851.101Skamil 40861.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 40871.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 40881.101Skamil != -1); 40891.101Skamil 40901.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 40911.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 40921.101Skamil "si_errno=%#x\n", 40931.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 40941.101Skamil info.psi_siginfo.si_errno); 40951.101Skamil 40961.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 40971.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 40981.101Skamil 40991.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 41001.101Skamil strcmp(operation, "PT_READ_D") == 0) { 41011.101Skamil if (strcmp(operation, "PT_READ_I")) 41021.101Skamil op = PT_READ_I; 41031.101Skamil else 41041.101Skamil op = PT_READ_D; 41051.101Skamil 41061.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41071.101Skamil errno = 0; 41081.101Skamil vector = ptrace(op, child, buffer + i, 0); 41091.101Skamil ATF_REQUIRE_EQ(errno, 0); 41101.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41111.101Skamil } 41121.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41131.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41141.101Skamil if (strcmp(operation, "PT_WRITE_I")) 41151.101Skamil op = PT_WRITE_I; 41161.101Skamil else 41171.101Skamil op = PT_WRITE_D; 41181.101Skamil 41191.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41201.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 41211.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 41221.101Skamil != -1); 41231.101Skamil } 41241.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41251.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41261.101Skamil if (strcmp(operation, "PIOD_READ_I")) 41271.101Skamil op = PIOD_READ_I; 41281.101Skamil else 41291.101Skamil op = PIOD_READ_D; 41301.101Skamil 41311.101Skamil io.piod_op = op; 41321.101Skamil io.piod_addr = &vector; 41331.101Skamil io.piod_len = sizeof(int); 41341.101Skamil 41351.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41361.101Skamil io.piod_offs = buffer + i; 41371.101Skamil 41381.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41391.101Skamil != -1); 41401.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41411.101Skamil } 41421.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 41431.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 41441.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 41451.101Skamil op = PIOD_WRITE_I; 41461.101Skamil else 41471.101Skamil op = PIOD_WRITE_D; 41481.101Skamil 41491.101Skamil io.piod_op = op; 41501.101Skamil io.piod_addr = &vector; 41511.101Skamil io.piod_len = sizeof(int); 41521.101Skamil 41531.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41541.101Skamil io.piod_offs = buffer + i; 41551.101Skamil 41561.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41571.101Skamil != -1); 41581.101Skamil } 41591.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 41601.101Skamil io.piod_op = PIOD_READ_AUXV; 41611.101Skamil io.piod_addr = &vector; 41621.101Skamil io.piod_len = sizeof(int); 41631.101Skamil 41641.101Skamil errno = 0; 41651.101Skamil i = 0; 41661.101Skamil /* Read the whole AUXV vector, it has no clear length */ 41671.120Skamil while (io.piod_len > 0) { 41681.101Skamil io.piod_offs = (void *)(intptr_t)i; 41691.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41701.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 41711.101Skamil ++i; 41721.101Skamil } 41731.101Skamil } 41741.101Skamil 41751.101Skamil DPRINTF("Before resuming the child process where it left off " 41761.101Skamil "and without signal to be sent\n"); 41771.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41781.101Skamil 41791.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41801.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 41811.101Skamil child); 41821.101Skamil 41831.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41841.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41851.101Skamil} 41861.101Skamil 41871.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 41881.101SkamilATF_TC(test); \ 41891.101SkamilATF_TC_HEAD(test, tc) \ 41901.101Skamil{ \ 41911.101Skamil atf_tc_set_md_var(tc, "descr", \ 41921.101Skamil "Verify bytes transfer for potentially misaligned " \ 41931.101Skamil "operation " operation); \ 41941.101Skamil} \ 41951.101Skamil \ 41961.101SkamilATF_TC_BODY(test, tc) \ 41971.101Skamil{ \ 41981.101Skamil \ 41991.101Skamil bytes_transfer_alignment(operation); \ 42001.101Skamil} 42011.101Skamil 42021.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 42031.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 42041.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 42051.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 42061.101Skamil 42071.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 42081.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 42091.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 42101.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 42111.101Skamil 42121.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 42131.101Skamil 42141.101Skamil/// ---------------------------------------------------------------------------- 42151.101Skamil 42161.115Skamilstatic void 42171.115Skamilbytes_transfer_eof(const char *operation) 42181.115Skamil{ 42191.115Skamil const int exitval = 5; 42201.115Skamil const int sigval = SIGSTOP; 42211.115Skamil pid_t child, wpid; 42221.115Skamil#if defined(TWAIT_HAVE_STATUS) 42231.115Skamil int status; 42241.115Skamil#endif 42251.115Skamil FILE *fp; 42261.115Skamil char *p; 42271.115Skamil int vector; 42281.115Skamil int op; 42291.115Skamil 42301.115Skamil struct ptrace_io_desc io; 42311.115Skamil struct ptrace_siginfo info; 42321.115Skamil 42331.115Skamil memset(&io, 0, sizeof(io)); 42341.115Skamil memset(&info, 0, sizeof(info)); 42351.115Skamil 42361.115Skamil vector = 0; 42371.115Skamil 42381.115Skamil fp = tmpfile(); 42391.115Skamil ATF_REQUIRE(fp != NULL); 42401.115Skamil 42411.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 42421.115Skamil ATF_REQUIRE(p != MAP_FAILED); 42431.115Skamil 42441.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42451.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42461.115Skamil if (child == 0) { 42471.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42481.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42491.115Skamil 42501.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42511.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 42521.115Skamil 42531.115Skamil DPRINTF("Before exiting of the child process\n"); 42541.115Skamil _exit(exitval); 42551.115Skamil } 42561.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42571.115Skamil 42581.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42591.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42601.115Skamil 42611.115Skamil validate_status_stopped(status, sigval); 42621.115Skamil 42631.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42641.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 42651.115Skamil != -1); 42661.115Skamil 42671.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42681.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42691.115Skamil "si_errno=%#x\n", 42701.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42711.115Skamil info.psi_siginfo.si_errno); 42721.115Skamil 42731.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42741.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42751.115Skamil 42761.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 42771.115Skamil strcmp(operation, "PT_READ_D") == 0) { 42781.115Skamil if (strcmp(operation, "PT_READ_I")) 42791.115Skamil op = PT_READ_I; 42801.115Skamil else 42811.115Skamil op = PT_READ_D; 42821.115Skamil 42831.115Skamil errno = 0; 42841.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 42851.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42861.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 42871.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 42881.115Skamil if (strcmp(operation, "PT_WRITE_I")) 42891.115Skamil op = PT_WRITE_I; 42901.115Skamil else 42911.115Skamil op = PT_WRITE_D; 42921.115Skamil 42931.115Skamil errno = 0; 42941.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 42951.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42961.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 42971.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 42981.115Skamil if (strcmp(operation, "PIOD_READ_I")) 42991.115Skamil op = PIOD_READ_I; 43001.115Skamil else 43011.115Skamil op = PIOD_READ_D; 43021.115Skamil 43031.115Skamil io.piod_op = op; 43041.115Skamil io.piod_addr = &vector; 43051.115Skamil io.piod_len = sizeof(int); 43061.115Skamil io.piod_offs = p; 43071.115Skamil 43081.115Skamil errno = 0; 43091.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43101.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43111.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 43121.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 43131.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 43141.115Skamil op = PIOD_WRITE_I; 43151.115Skamil else 43161.115Skamil op = PIOD_WRITE_D; 43171.115Skamil 43181.115Skamil io.piod_op = op; 43191.115Skamil io.piod_addr = &vector; 43201.115Skamil io.piod_len = sizeof(int); 43211.115Skamil io.piod_offs = p; 43221.115Skamil 43231.115Skamil errno = 0; 43241.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43251.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43261.115Skamil } 43271.115Skamil 43281.115Skamil DPRINTF("Before resuming the child process where it left off " 43291.115Skamil "and without signal to be sent\n"); 43301.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43311.115Skamil 43321.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43331.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43341.115Skamil child); 43351.115Skamil 43361.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43371.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43381.115Skamil} 43391.115Skamil 43401.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 43411.115SkamilATF_TC(test); \ 43421.115SkamilATF_TC_HEAD(test, tc) \ 43431.115Skamil{ \ 43441.115Skamil atf_tc_set_md_var(tc, "descr", \ 43451.115Skamil "Verify bytes EOF byte transfer for the " operation \ 43461.115Skamil " operation"); \ 43471.115Skamil} \ 43481.115Skamil \ 43491.115SkamilATF_TC_BODY(test, tc) \ 43501.115Skamil{ \ 43511.115Skamil \ 43521.115Skamil bytes_transfer_eof(operation); \ 43531.115Skamil} 43541.115Skamil 43551.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 43561.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 43571.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 43581.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 43591.115Skamil 43601.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 43611.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 43621.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 43631.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 43641.115Skamil 43651.115Skamil/// ---------------------------------------------------------------------------- 43661.115Skamil 43671.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 43681.72Skamilstatic void 43691.72Skamilaccess_regs(const char *regset, const char *aux) 43701.1Skamil{ 43711.1Skamil const int exitval = 5; 43721.1Skamil const int sigval = SIGSTOP; 43731.1Skamil pid_t child, wpid; 43741.1Skamil#if defined(TWAIT_HAVE_STATUS) 43751.1Skamil int status; 43761.1Skamil#endif 43771.72Skamil#if defined(HAVE_GPREGS) 43781.72Skamil struct reg gpr; 43791.76Sscole register_t rgstr; 43801.1Skamil#endif 43811.72Skamil#if defined(HAVE_FPREGS) 43821.72Skamil struct fpreg fpr; 43831.1Skamil#endif 43841.76Sscole 43851.72Skamil#if !defined(HAVE_GPREGS) 43861.72Skamil if (strcmp(regset, "regs") == 0) 43871.72Skamil atf_tc_fail("Impossible test scenario!"); 43881.1Skamil#endif 43891.1Skamil 43901.72Skamil#if !defined(HAVE_FPREGS) 43911.72Skamil if (strcmp(regset, "fpregs") == 0) 43921.72Skamil atf_tc_fail("Impossible test scenario!"); 43931.1Skamil#endif 43941.1Skamil 43951.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43961.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43971.1Skamil if (child == 0) { 43981.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43991.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44001.1Skamil 44011.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44021.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44031.1Skamil 44041.13Schristos DPRINTF("Before exiting of the child process\n"); 44051.1Skamil _exit(exitval); 44061.1Skamil } 44071.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44081.1Skamil 44091.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44111.1Skamil 44121.1Skamil validate_status_stopped(status, sigval); 44131.1Skamil 44141.1Skamil#if defined(HAVE_GPREGS) 44151.72Skamil if (strcmp(regset, "regs") == 0) { 44161.72Skamil DPRINTF("Call GETREGS for the child process\n"); 44171.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44181.72Skamil 44191.72Skamil if (strcmp(aux, "none") == 0) { 44201.72Skamil DPRINTF("Retrieved registers\n"); 44211.72Skamil } else if (strcmp(aux, "pc") == 0) { 44221.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44231.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44241.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 44251.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44261.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 44271.72Skamil } else if (strcmp(aux, "sp") == 0) { 44281.72Skamil rgstr = PTRACE_REG_SP(&gpr); 44291.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44301.72Skamil } else if (strcmp(aux, "intrv") == 0) { 44311.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 44321.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44331.72Skamil } else if (strcmp(aux, "setregs") == 0) { 44341.72Skamil DPRINTF("Call SETREGS for the child process\n"); 44351.72Skamil SYSCALL_REQUIRE( 44361.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44371.72Skamil } 44381.72Skamil } 44391.1Skamil#endif 44401.1Skamil 44411.72Skamil#if defined(HAVE_FPREGS) 44421.72Skamil if (strcmp(regset, "fpregs") == 0) { 44431.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 44441.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 44451.72Skamil 44461.72Skamil if (strcmp(aux, "getfpregs") == 0) { 44471.72Skamil DPRINTF("Retrieved FP registers\n"); 44481.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 44491.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 44501.72Skamil SYSCALL_REQUIRE( 44511.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 44521.72Skamil } 44531.1Skamil } 44541.1Skamil#endif 44551.1Skamil 44561.13Schristos DPRINTF("Before resuming the child process where it left off and " 44571.1Skamil "without signal to be sent\n"); 44581.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44591.1Skamil 44601.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44611.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44621.1Skamil 44631.1Skamil validate_status_exited(status, exitval); 44641.1Skamil 44651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44661.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44671.1Skamil} 44681.1Skamil 44691.72Skamil#define ACCESS_REGS(test, regset, aux) \ 44701.72SkamilATF_TC(test); \ 44711.72SkamilATF_TC_HEAD(test, tc) \ 44721.72Skamil{ \ 44731.72Skamil atf_tc_set_md_var(tc, "descr", \ 44741.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 44751.72Skamil} \ 44761.72Skamil \ 44771.72SkamilATF_TC_BODY(test, tc) \ 44781.72Skamil{ \ 44791.72Skamil \ 44801.72Skamil access_regs(regset, aux); \ 44811.1Skamil} 44821.1Skamil#endif 44831.1Skamil 44841.72Skamil#if defined(HAVE_GPREGS) 44851.72SkamilACCESS_REGS(access_regs1, "regs", "none") 44861.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 44871.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 44881.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 44891.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 44901.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 44911.1Skamil#endif 44921.1Skamil#if defined(HAVE_FPREGS) 44931.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 44941.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 44951.1Skamil#endif 44961.1Skamil 44971.72Skamil/// ---------------------------------------------------------------------------- 44981.1Skamil 44991.1Skamil#if defined(PT_STEP) 45001.1Skamilstatic void 45011.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 45021.1Skamil{ 45031.1Skamil const int exitval = 5; 45041.1Skamil const int sigval = SIGSTOP; 45051.1Skamil pid_t child, wpid; 45061.1Skamil#if defined(TWAIT_HAVE_STATUS) 45071.1Skamil int status; 45081.1Skamil#endif 45091.1Skamil int happy; 45101.95Skamil struct sigaction sa; 45111.81Skamil struct ptrace_siginfo info; 45121.95Skamil sigset_t intmask; 45131.95Skamil struct kinfo_proc2 kp; 45141.95Skamil size_t len = sizeof(kp); 45151.95Skamil 45161.95Skamil int name[6]; 45171.95Skamil const size_t namelen = __arraycount(name); 45181.95Skamil ki_sigset_t kp_sigmask; 45191.95Skamil ki_sigset_t kp_sigignore; 45201.1Skamil 45211.1Skamil#if defined(__arm__) 45221.1Skamil /* PT_STEP not supported on arm 32-bit */ 45231.1Skamil atf_tc_expect_fail("PR kern/52119"); 45241.1Skamil#endif 45251.1Skamil 45261.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45271.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45281.1Skamil if (child == 0) { 45291.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45301.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45311.1Skamil 45321.95Skamil if (masked) { 45331.95Skamil sigemptyset(&intmask); 45341.95Skamil sigaddset(&intmask, SIGTRAP); 45351.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 45361.95Skamil } 45371.95Skamil 45381.95Skamil if (ignored) { 45391.95Skamil memset(&sa, 0, sizeof(sa)); 45401.95Skamil sa.sa_handler = SIG_IGN; 45411.95Skamil sigemptyset(&sa.sa_mask); 45421.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 45431.95Skamil } 45441.95Skamil 45451.1Skamil happy = check_happy(999); 45461.1Skamil 45471.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 45481.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 45491.1Skamil 45501.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 45511.1Skamil 45521.13Schristos DPRINTF("Before exiting of the child process\n"); 45531.1Skamil _exit(exitval); 45541.1Skamil } 45551.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45561.1Skamil 45571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45581.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45591.1Skamil 45601.1Skamil validate_status_stopped(status, sigval); 45611.1Skamil 45621.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45631.81Skamil SYSCALL_REQUIRE( 45641.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45651.81Skamil 45661.81Skamil DPRINTF("Before checking siginfo_t\n"); 45671.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45681.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 45691.81Skamil 45701.95Skamil name[0] = CTL_KERN, 45711.95Skamil name[1] = KERN_PROC2, 45721.95Skamil name[2] = KERN_PROC_PID; 45731.95Skamil name[3] = child; 45741.95Skamil name[4] = sizeof(kp); 45751.95Skamil name[5] = 1; 45761.95Skamil 45771.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45781.95Skamil 45791.95Skamil if (masked) 45801.95Skamil kp_sigmask = kp.p_sigmask; 45811.95Skamil 45821.95Skamil if (ignored) 45831.95Skamil kp_sigignore = kp.p_sigignore; 45841.95Skamil 45851.1Skamil while (N --> 0) { 45861.2Skamil if (setstep) { 45871.13Schristos DPRINTF("Before resuming the child process where it " 45881.2Skamil "left off and without signal to be sent (use " 45891.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 45901.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 45911.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 45921.2Skamil != -1); 45931.2Skamil } else { 45941.13Schristos DPRINTF("Before resuming the child process where it " 45951.2Skamil "left off and without signal to be sent (use " 45961.2Skamil "PT_STEP)\n"); 45971.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 45981.2Skamil != -1); 45991.2Skamil } 46001.1Skamil 46011.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 46031.1Skamil child); 46041.1Skamil 46051.1Skamil validate_status_stopped(status, SIGTRAP); 46061.2Skamil 46071.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46081.81Skamil SYSCALL_REQUIRE( 46091.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46101.81Skamil 46111.81Skamil DPRINTF("Before checking siginfo_t\n"); 46121.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46131.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 46141.81Skamil 46151.2Skamil if (setstep) { 46161.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 46171.2Skamil } 46181.95Skamil 46191.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46201.95Skamil 46211.95Skamil if (masked) { 46221.95Skamil DPRINTF("kp_sigmask=" 46231.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46241.95Skamil PRIx32 "\n", 46251.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 46261.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 46271.95Skamil 46281.95Skamil DPRINTF("kp.p_sigmask=" 46291.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46301.95Skamil PRIx32 "\n", 46311.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 46321.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 46331.95Skamil 46341.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 46351.95Skamil sizeof(kp_sigmask))); 46361.95Skamil } 46371.95Skamil 46381.95Skamil if (ignored) { 46391.95Skamil DPRINTF("kp_sigignore=" 46401.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46411.95Skamil PRIx32 "\n", 46421.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 46431.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 46441.95Skamil 46451.95Skamil DPRINTF("kp.p_sigignore=" 46461.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46471.95Skamil PRIx32 "\n", 46481.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 46491.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 46501.95Skamil 46511.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 46521.95Skamil sizeof(kp_sigignore))); 46531.95Skamil } 46541.1Skamil } 46551.1Skamil 46561.13Schristos DPRINTF("Before resuming the child process where it left off and " 46571.1Skamil "without signal to be sent\n"); 46581.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46591.1Skamil 46601.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46611.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46621.1Skamil 46631.1Skamil validate_status_exited(status, exitval); 46641.1Skamil 46651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46661.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46671.1Skamil} 46681.1Skamil 46691.73Skamil#define PTRACE_STEP(test, N, setstep) \ 46701.73SkamilATF_TC(test); \ 46711.73SkamilATF_TC_HEAD(test, tc) \ 46721.73Skamil{ \ 46731.73Skamil atf_tc_set_md_var(tc, "descr", \ 46741.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 46751.73Skamil} \ 46761.73Skamil \ 46771.73SkamilATF_TC_BODY(test, tc) \ 46781.73Skamil{ \ 46791.73Skamil \ 46801.95Skamil ptrace_step(N, setstep, false, false); \ 46811.1Skamil} 46821.1Skamil 46831.73SkamilPTRACE_STEP(step1, 1, 0) 46841.73SkamilPTRACE_STEP(step2, 2, 0) 46851.73SkamilPTRACE_STEP(step3, 3, 0) 46861.73SkamilPTRACE_STEP(step4, 4, 0) 46871.73SkamilPTRACE_STEP(setstep1, 1, 1) 46881.73SkamilPTRACE_STEP(setstep2, 2, 1) 46891.73SkamilPTRACE_STEP(setstep3, 3, 1) 46901.73SkamilPTRACE_STEP(setstep4, 4, 1) 46911.95Skamil 46921.95SkamilATF_TC(step_signalmasked); 46931.95SkamilATF_TC_HEAD(step_signalmasked, tc) 46941.95Skamil{ 46951.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 46961.95Skamil} 46971.95Skamil 46981.95SkamilATF_TC_BODY(step_signalmasked, tc) 46991.95Skamil{ 47001.95Skamil 47011.95Skamil ptrace_step(1, 0, true, false); 47021.95Skamil} 47031.95Skamil 47041.95SkamilATF_TC(step_signalignored); 47051.95SkamilATF_TC_HEAD(step_signalignored, tc) 47061.95Skamil{ 47071.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 47081.95Skamil} 47091.95Skamil 47101.95SkamilATF_TC_BODY(step_signalignored, tc) 47111.95Skamil{ 47121.95Skamil 47131.95Skamil ptrace_step(1, 0, false, true); 47141.95Skamil} 47151.1Skamil#endif 47161.1Skamil 47171.73Skamil/// ---------------------------------------------------------------------------- 47181.1Skamil 47191.75Skamilstatic void 47201.75Skamilptrace_kill(const char *type) 47211.1Skamil{ 47221.75Skamil const int sigval = SIGSTOP; 47231.1Skamil pid_t child, wpid; 47241.1Skamil#if defined(TWAIT_HAVE_STATUS) 47251.1Skamil int status; 47261.1Skamil#endif 47271.1Skamil 47281.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47291.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47301.1Skamil if (child == 0) { 47311.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47321.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47331.1Skamil 47341.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47351.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47361.1Skamil 47371.1Skamil /* NOTREACHED */ 47381.1Skamil FORKEE_ASSERTX(0 && 47391.1Skamil "Child should be terminated by a signal from its parent"); 47401.1Skamil } 47411.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47421.1Skamil 47431.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47441.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47451.1Skamil 47461.1Skamil validate_status_stopped(status, sigval); 47471.1Skamil 47481.75Skamil DPRINTF("Before killing the child process with %s\n", type); 47491.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 47501.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 47511.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 47521.75Skamil kill(child, SIGKILL); 47531.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 47541.75Skamil setpgid(child, 0); 47551.75Skamil killpg(getpgid(child), SIGKILL); 47561.75Skamil } 47571.1Skamil 47581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47601.1Skamil 47611.75Skamil validate_status_signaled(status, SIGKILL, 0); 47621.1Skamil 47631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47641.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47651.1Skamil} 47661.1Skamil 47671.75Skamil#define PTRACE_KILL(test, type) \ 47681.75SkamilATF_TC(test); \ 47691.75SkamilATF_TC_HEAD(test, tc) \ 47701.75Skamil{ \ 47711.75Skamil atf_tc_set_md_var(tc, "descr", \ 47721.75Skamil "Verify killing the child with " type); \ 47731.75Skamil} \ 47741.75Skamil \ 47751.75SkamilATF_TC_BODY(test, tc) \ 47761.75Skamil{ \ 47771.75Skamil \ 47781.75Skamil ptrace_kill(type); \ 47791.1Skamil} 47801.1Skamil 47811.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 47821.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 47831.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 47841.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 47851.1Skamil 47861.75Skamil/// ---------------------------------------------------------------------------- 47871.1Skamil 47881.77Skamilstatic void 47891.77Skamiltraceme_lwpinfo(const int threads) 47901.1Skamil{ 47911.1Skamil const int sigval = SIGSTOP; 47921.77Skamil const int sigval2 = SIGINT; 47931.1Skamil pid_t child, wpid; 47941.1Skamil#if defined(TWAIT_HAVE_STATUS) 47951.1Skamil int status; 47961.1Skamil#endif 47971.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 47981.77Skamil struct ptrace_siginfo info; 47991.77Skamil 48001.77Skamil /* Maximum number of supported threads in this test */ 48011.77Skamil pthread_t t[3]; 48021.77Skamil int n, rv; 48031.77Skamil 48041.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 48051.1Skamil 48061.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48071.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48081.1Skamil if (child == 0) { 48091.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48101.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48111.1Skamil 48121.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48131.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48141.1Skamil 48151.77Skamil for (n = 0; n < threads; n++) { 48161.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48171.77Skamil FORKEE_ASSERT(rv == 0); 48181.77Skamil } 48191.77Skamil 48201.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 48211.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 48221.77Skamil 48231.77Skamil /* NOTREACHED */ 48241.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48251.1Skamil } 48261.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48271.1Skamil 48281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48301.1Skamil 48311.1Skamil validate_status_stopped(status, sigval); 48321.1Skamil 48331.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48341.77Skamil SYSCALL_REQUIRE( 48351.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48361.77Skamil 48371.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48381.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48391.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48401.77Skamil info.psi_siginfo.si_errno); 48411.77Skamil 48421.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 48431.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48441.77Skamil 48451.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48461.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48471.1Skamil 48481.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48491.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48501.1Skamil 48511.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 48521.77Skamil lwp.pl_lwpid); 48531.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 48541.1Skamil 48551.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48561.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48571.1Skamil 48581.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48591.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48601.1Skamil 48611.13Schristos DPRINTF("Before resuming the child process where it left off and " 48621.1Skamil "without signal to be sent\n"); 48631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48641.1Skamil 48651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48671.1Skamil 48681.77Skamil validate_status_stopped(status, sigval2); 48691.77Skamil 48701.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48711.77Skamil SYSCALL_REQUIRE( 48721.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48731.77Skamil 48741.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48751.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48761.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48771.77Skamil info.psi_siginfo.si_errno); 48781.77Skamil 48791.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 48801.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48811.77Skamil 48821.77Skamil memset(&lwp, 0, sizeof(lwp)); 48831.77Skamil 48841.77Skamil for (n = 0; n <= threads; n++) { 48851.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48861.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48871.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48881.77Skamil 48891.77Skamil DPRINTF("Assert that the thread exists\n"); 48901.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48911.77Skamil 48921.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 48931.77Skamil lwp.pl_lwpid); 48941.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 48951.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 48961.77Skamil } 48971.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48981.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48991.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49001.77Skamil 49011.77Skamil DPRINTF("Assert that there are no more threads\n"); 49021.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 49031.77Skamil 49041.77Skamil DPRINTF("Before resuming the child process where it left off and " 49051.77Skamil "without signal to be sent\n"); 49061.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 49071.77Skamil 49081.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49091.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49101.77Skamil 49111.77Skamil validate_status_signaled(status, SIGKILL, 0); 49121.1Skamil 49131.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49141.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49151.1Skamil} 49161.1Skamil 49171.77Skamil#define TRACEME_LWPINFO(test, threads) \ 49181.77SkamilATF_TC(test); \ 49191.77SkamilATF_TC_HEAD(test, tc) \ 49201.77Skamil{ \ 49211.77Skamil atf_tc_set_md_var(tc, "descr", \ 49221.77Skamil "Verify LWPINFO with the child with " #threads \ 49231.77Skamil " spawned extra threads"); \ 49241.77Skamil} \ 49251.77Skamil \ 49261.77SkamilATF_TC_BODY(test, tc) \ 49271.77Skamil{ \ 49281.77Skamil \ 49291.77Skamil traceme_lwpinfo(threads); \ 49301.1Skamil} 49311.1Skamil 49321.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 49331.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 49341.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 49351.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 49361.77Skamil 49371.77Skamil/// ---------------------------------------------------------------------------- 49381.77Skamil 49391.77Skamil#if defined(TWAIT_HAVE_PID) 49401.77Skamilstatic void 49411.77Skamilattach_lwpinfo(const int threads) 49421.1Skamil{ 49431.77Skamil const int sigval = SIGINT; 49441.1Skamil struct msg_fds parent_tracee, parent_tracer; 49451.1Skamil const int exitval_tracer = 10; 49461.1Skamil pid_t tracee, tracer, wpid; 49471.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 49481.1Skamil#if defined(TWAIT_HAVE_STATUS) 49491.1Skamil int status; 49501.1Skamil#endif 49511.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 49521.77Skamil struct ptrace_siginfo info; 49531.77Skamil 49541.77Skamil /* Maximum number of supported threads in this test */ 49551.77Skamil pthread_t t[3]; 49561.77Skamil int n, rv; 49571.1Skamil 49581.13Schristos DPRINTF("Spawn tracee\n"); 49591.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 49601.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 49611.1Skamil tracee = atf_utils_fork(); 49621.1Skamil if (tracee == 0) { 49631.1Skamil /* Wait for message from the parent */ 49641.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 49651.1Skamil 49661.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 49671.77Skamil 49681.77Skamil for (n = 0; n < threads; n++) { 49691.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 49701.77Skamil FORKEE_ASSERT(rv == 0); 49711.77Skamil } 49721.77Skamil 49731.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 49741.77Skamil 49751.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49761.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 49771.77Skamil 49781.77Skamil /* NOTREACHED */ 49791.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 49801.1Skamil } 49811.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 49821.1Skamil 49831.13Schristos DPRINTF("Spawn debugger\n"); 49841.1Skamil tracer = atf_utils_fork(); 49851.1Skamil if (tracer == 0) { 49861.1Skamil /* No IPC to communicate with the child */ 49871.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 49881.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 49891.1Skamil 49901.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 49911.1Skamil FORKEE_REQUIRE_SUCCESS( 49921.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49931.1Skamil 49941.1Skamil forkee_status_stopped(status, SIGSTOP); 49951.1Skamil 49961.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49971.77Skamil "tracee"); 49981.77Skamil FORKEE_ASSERT( 49991.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50001.77Skamil 50011.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50021.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50031.77Skamil "si_errno=%#x\n", 50041.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50051.77Skamil info.psi_siginfo.si_errno); 50061.77Skamil 50071.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 50081.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 50091.77Skamil 50101.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 50111.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50121.1Skamil != -1); 50131.1Skamil 50141.13Schristos DPRINTF("Assert that there exists a thread\n"); 50151.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 50161.1Skamil 50171.13Schristos DPRINTF("Assert that lwp thread %d received event " 50181.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 50191.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 50201.1Skamil 50211.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50221.77Skamil "tracee\n"); 50231.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50241.1Skamil != -1); 50251.1Skamil 50261.77Skamil DPRINTF("Assert that there are no more lwp threads in " 50271.77Skamil "tracee\n"); 50281.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50291.1Skamil 50301.1Skamil /* Resume tracee with PT_CONTINUE */ 50311.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 50321.1Skamil 50331.1Skamil /* Inform parent that tracer has attached to tracee */ 50341.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 50351.77Skamil 50361.1Skamil /* Wait for parent */ 50371.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 50381.1Skamil 50391.77Skamil /* Wait for tracee and assert that it raised a signal */ 50401.77Skamil FORKEE_REQUIRE_SUCCESS( 50411.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50421.77Skamil 50431.77Skamil forkee_status_stopped(status, SIGINT); 50441.77Skamil 50451.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50461.77Skamil "child"); 50471.77Skamil FORKEE_ASSERT( 50481.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50491.77Skamil 50501.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50511.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50521.77Skamil "si_errno=%#x\n", 50531.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50541.77Skamil info.psi_siginfo.si_errno); 50551.77Skamil 50561.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 50571.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 50581.77Skamil 50591.77Skamil memset(&lwp, 0, sizeof(lwp)); 50601.77Skamil 50611.77Skamil for (n = 0; n <= threads; n++) { 50621.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50631.77Skamil "child\n"); 50641.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 50651.77Skamil sizeof(lwp)) != -1); 50661.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50671.77Skamil 50681.77Skamil DPRINTF("Assert that the thread exists\n"); 50691.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 50701.77Skamil 50711.77Skamil DPRINTF("Assert that lwp thread %d received expected " 50721.77Skamil "event\n", lwp.pl_lwpid); 50731.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 50741.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 50751.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 50761.77Skamil } 50771.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50781.77Skamil "tracee\n"); 50791.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50801.77Skamil != -1); 50811.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50821.77Skamil 50831.77Skamil DPRINTF("Assert that there are no more threads\n"); 50841.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50851.77Skamil 50861.77Skamil DPRINTF("Before resuming the child process where it left off " 50871.77Skamil "and without signal to be sent\n"); 50881.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 50891.77Skamil != -1); 50901.77Skamil 50911.1Skamil /* Wait for tracee and assert that it exited */ 50921.1Skamil FORKEE_REQUIRE_SUCCESS( 50931.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50941.1Skamil 50951.77Skamil forkee_status_signaled(status, SIGKILL, 0); 50961.1Skamil 50971.13Schristos DPRINTF("Before exiting of the tracer process\n"); 50981.1Skamil _exit(exitval_tracer); 50991.1Skamil } 51001.1Skamil 51011.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 51021.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 51031.1Skamil 51041.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 51051.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 51061.77Skamil 51071.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 51081.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 51091.1Skamil 51101.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 51111.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 51121.1Skamil 51131.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 51141.1Skamil TWAIT_FNAME); 51151.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 51161.1Skamil tracer); 51171.1Skamil 51181.1Skamil validate_status_exited(status, exitval_tracer); 51191.1Skamil 51201.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 51211.1Skamil TWAIT_FNAME); 51221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 51231.1Skamil tracee); 51241.1Skamil 51251.77Skamil validate_status_signaled(status, SIGKILL, 0); 51261.1Skamil 51271.1Skamil msg_close(&parent_tracer); 51281.1Skamil msg_close(&parent_tracee); 51291.1Skamil} 51301.77Skamil 51311.77Skamil#define ATTACH_LWPINFO(test, threads) \ 51321.77SkamilATF_TC(test); \ 51331.77SkamilATF_TC_HEAD(test, tc) \ 51341.77Skamil{ \ 51351.77Skamil atf_tc_set_md_var(tc, "descr", \ 51361.77Skamil "Verify LWPINFO with the child with " #threads \ 51371.77Skamil " spawned extra threads (tracer is not the original " \ 51381.77Skamil "parent)"); \ 51391.77Skamil} \ 51401.77Skamil \ 51411.77SkamilATF_TC_BODY(test, tc) \ 51421.77Skamil{ \ 51431.77Skamil \ 51441.77Skamil attach_lwpinfo(threads); \ 51451.77Skamil} 51461.77Skamil 51471.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 51481.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 51491.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 51501.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 51511.1Skamil#endif 51521.1Skamil 51531.77Skamil/// ---------------------------------------------------------------------------- 51541.77Skamil 51551.1Skamilstatic void 51561.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 51571.1Skamil{ 51581.1Skamil const int exitval = 5; 51591.1Skamil const int sigval = SIGINT; 51601.1Skamil const int sigfaked = SIGTRAP; 51611.1Skamil const int sicodefaked = TRAP_BRKPT; 51621.1Skamil pid_t child, wpid; 51631.1Skamil struct sigaction sa; 51641.1Skamil#if defined(TWAIT_HAVE_STATUS) 51651.1Skamil int status; 51661.1Skamil#endif 51671.1Skamil struct ptrace_siginfo info; 51681.1Skamil memset(&info, 0, sizeof(info)); 51691.1Skamil 51701.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 51711.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 51721.1Skamil if (child == 0) { 51731.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51741.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51751.1Skamil 51761.79Skamil sa.sa_sigaction = sah; 51771.1Skamil sa.sa_flags = SA_SIGINFO; 51781.1Skamil sigemptyset(&sa.sa_mask); 51791.1Skamil 51801.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 51811.79Skamil != -1); 51821.1Skamil 51831.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 51841.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 51851.1Skamil 51861.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 51871.1Skamil 51881.13Schristos DPRINTF("Before exiting of the child process\n"); 51891.1Skamil _exit(exitval); 51901.1Skamil } 51911.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 51921.1Skamil 51931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51951.1Skamil 51961.1Skamil validate_status_stopped(status, sigval); 51971.1Skamil 51981.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 51991.61Skre SYSCALL_REQUIRE( 52001.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52011.1Skamil 52021.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52031.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52041.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52051.1Skamil info.psi_siginfo.si_errno); 52061.1Skamil 52071.79Skamil if (faked) { 52081.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 52091.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 52101.79Skamil info.psi_siginfo.si_signo = sigfaked; 52111.79Skamil info.psi_siginfo.si_code = sicodefaked; 52121.79Skamil } 52131.1Skamil 52141.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 52151.61Skre SYSCALL_REQUIRE( 52161.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 52171.1Skamil 52181.79Skamil if (faked) { 52191.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52201.79Skamil "child\n"); 52211.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 52221.79Skamil sizeof(info)) != -1); 52231.1Skamil 52241.79Skamil DPRINTF("Before checking siginfo_t\n"); 52251.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 52261.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 52271.79Skamil } 52281.1Skamil 52291.13Schristos DPRINTF("Before resuming the child process where it left off and " 52301.1Skamil "without signal to be sent\n"); 52311.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 52321.79Skamil faked ? sigfaked : sigval) != -1); 52331.1Skamil 52341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52361.1Skamil 52371.1Skamil validate_status_exited(status, exitval); 52381.1Skamil 52391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52401.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 52411.1Skamil} 52421.1Skamil 52431.79Skamil#define PTRACE_SIGINFO(test, faked) \ 52441.79SkamilATF_TC(test); \ 52451.79SkamilATF_TC_HEAD(test, tc) \ 52461.79Skamil{ \ 52471.79Skamil atf_tc_set_md_var(tc, "descr", \ 52481.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 52491.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 52501.79Skamil} \ 52511.79Skamil \ 52521.79Skamilstatic int test##_caught = 0; \ 52531.79Skamil \ 52541.79Skamilstatic void \ 52551.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 52561.79Skamil{ \ 52571.79Skamil if (faked) { \ 52581.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 52591.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 52601.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 52611.79Skamil } else { \ 52621.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 52631.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 52641.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 52651.79Skamil } \ 52661.79Skamil \ 52671.79Skamil ++ test##_caught; \ 52681.79Skamil} \ 52691.79Skamil \ 52701.79SkamilATF_TC_BODY(test, tc) \ 52711.79Skamil{ \ 52721.79Skamil \ 52731.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 52741.79Skamil} 52751.79Skamil 52761.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 52771.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 52781.79Skamil 52791.79Skamil/// ---------------------------------------------------------------------------- 52801.79Skamil 52811.97Skamilstatic void 52821.97Skamiltraceme_exec(bool masked, bool ignored) 52831.1Skamil{ 52841.1Skamil const int sigval = SIGTRAP; 52851.1Skamil pid_t child, wpid; 52861.1Skamil#if defined(TWAIT_HAVE_STATUS) 52871.1Skamil int status; 52881.1Skamil#endif 52891.97Skamil struct sigaction sa; 52901.97Skamil struct ptrace_siginfo info; 52911.97Skamil sigset_t intmask; 52921.97Skamil struct kinfo_proc2 kp; 52931.97Skamil size_t len = sizeof(kp); 52941.97Skamil 52951.97Skamil int name[6]; 52961.97Skamil const size_t namelen = __arraycount(name); 52971.97Skamil ki_sigset_t kp_sigmask; 52981.97Skamil ki_sigset_t kp_sigignore; 52991.1Skamil 53001.1Skamil memset(&info, 0, sizeof(info)); 53011.1Skamil 53021.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53031.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53041.1Skamil if (child == 0) { 53051.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53061.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53071.1Skamil 53081.97Skamil if (masked) { 53091.97Skamil sigemptyset(&intmask); 53101.97Skamil sigaddset(&intmask, sigval); 53111.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53121.97Skamil } 53131.97Skamil 53141.97Skamil if (ignored) { 53151.97Skamil memset(&sa, 0, sizeof(sa)); 53161.97Skamil sa.sa_handler = SIG_IGN; 53171.97Skamil sigemptyset(&sa.sa_mask); 53181.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 53191.97Skamil } 53201.97Skamil 53211.13Schristos DPRINTF("Before calling execve(2) from child\n"); 53221.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 53231.1Skamil 53241.1Skamil FORKEE_ASSERT(0 && "Not reached"); 53251.1Skamil } 53261.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53271.1Skamil 53281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53301.1Skamil 53311.1Skamil validate_status_stopped(status, sigval); 53321.1Skamil 53331.97Skamil name[0] = CTL_KERN, 53341.97Skamil name[1] = KERN_PROC2, 53351.97Skamil name[2] = KERN_PROC_PID; 53361.97Skamil name[3] = getpid(); 53371.97Skamil name[4] = sizeof(kp); 53381.97Skamil name[5] = 1; 53391.97Skamil 53401.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53411.97Skamil 53421.97Skamil if (masked) 53431.97Skamil kp_sigmask = kp.p_sigmask; 53441.97Skamil 53451.97Skamil if (ignored) 53461.97Skamil kp_sigignore = kp.p_sigignore; 53471.97Skamil 53481.97Skamil name[3] = getpid(); 53491.97Skamil 53501.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53511.97Skamil 53521.97Skamil if (masked) { 53531.97Skamil DPRINTF("kp_sigmask=" 53541.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53551.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53561.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53571.97Skamil 53581.97Skamil DPRINTF("kp.p_sigmask=" 53591.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53601.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53611.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53621.97Skamil 53631.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53641.97Skamil sizeof(kp_sigmask))); 53651.97Skamil } 53661.97Skamil 53671.97Skamil if (ignored) { 53681.97Skamil DPRINTF("kp_sigignore=" 53691.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53701.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53711.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53721.97Skamil 53731.97Skamil DPRINTF("kp.p_sigignore=" 53741.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53751.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53761.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53771.97Skamil 53781.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53791.97Skamil sizeof(kp_sigignore))); 53801.97Skamil } 53811.97Skamil 53821.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 53831.61Skre SYSCALL_REQUIRE( 53841.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 53851.1Skamil 53861.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 53871.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 53881.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 53891.1Skamil info.psi_siginfo.si_errno); 53901.1Skamil 53911.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 53921.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 53931.1Skamil 53941.13Schristos DPRINTF("Before resuming the child process where it left off and " 53951.1Skamil "without signal to be sent\n"); 53961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53971.1Skamil 53981.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54001.1Skamil 54011.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54021.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54031.1Skamil} 54041.1Skamil 54051.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 54061.97SkamilATF_TC(test); \ 54071.97SkamilATF_TC_HEAD(test, tc) \ 54081.97Skamil{ \ 54091.97Skamil atf_tc_set_md_var(tc, "descr", \ 54101.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 54111.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 54121.97Skamil masked ? " with ignored signal" : ""); \ 54131.97Skamil} \ 54141.97Skamil \ 54151.97SkamilATF_TC_BODY(test, tc) \ 54161.97Skamil{ \ 54171.97Skamil \ 54181.97Skamil traceme_exec(masked, ignored); \ 54191.97Skamil} 54201.97Skamil 54211.97SkamilTRACEME_EXEC(traceme_exec, false, false) 54221.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 54231.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 54241.97Skamil 54251.82Skamil/// ---------------------------------------------------------------------------- 54261.82Skamil 54271.83Skamilstatic volatile int done; 54281.1Skamil 54291.83Skamilstatic void * 54301.83Skamiltrace_threads_cb(void *arg __unused) 54311.1Skamil{ 54321.1Skamil 54331.83Skamil done++; 54341.83Skamil 54351.83Skamil while (done < 3) 54361.83Skamil continue; 54371.83Skamil 54381.83Skamil return NULL; 54391.1Skamil} 54401.1Skamil 54411.83Skamilstatic void 54421.83Skamiltrace_threads(bool trace_create, bool trace_exit) 54431.1Skamil{ 54441.1Skamil const int sigval = SIGSTOP; 54451.1Skamil pid_t child, wpid; 54461.1Skamil#if defined(TWAIT_HAVE_STATUS) 54471.1Skamil int status; 54481.1Skamil#endif 54491.1Skamil ptrace_state_t state; 54501.1Skamil const int slen = sizeof(state); 54511.1Skamil ptrace_event_t event; 54521.1Skamil const int elen = sizeof(event); 54531.83Skamil struct ptrace_siginfo info; 54541.83Skamil 54551.83Skamil pthread_t t[3]; 54561.83Skamil int rv; 54571.83Skamil size_t n; 54581.1Skamil lwpid_t lid; 54591.83Skamil 54601.83Skamil /* Track created and exited threads */ 54611.83Skamil bool traced_lwps[__arraycount(t)]; 54621.83Skamil 54631.128Skamil#if !TEST_LWP_ENABLED 54641.120Skamil if (trace_create || trace_exit) 54651.119Skamil atf_tc_skip("PR kern/51995"); 54661.128Skamil#endif 54671.1Skamil 54681.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54691.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54701.1Skamil if (child == 0) { 54711.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54721.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54731.1Skamil 54741.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54751.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54761.1Skamil 54771.83Skamil for (n = 0; n < __arraycount(t); n++) { 54781.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 54791.83Skamil NULL); 54801.83Skamil FORKEE_ASSERT(rv == 0); 54811.83Skamil } 54821.1Skamil 54831.83Skamil for (n = 0; n < __arraycount(t); n++) { 54841.83Skamil rv = pthread_join(t[n], NULL); 54851.83Skamil FORKEE_ASSERT(rv == 0); 54861.83Skamil } 54871.1Skamil 54881.83Skamil /* 54891.83Skamil * There is race between _exit() and pthread_join() detaching 54901.83Skamil * a thread. For simplicity kill the process after detecting 54911.83Skamil * LWP events. 54921.83Skamil */ 54931.83Skamil while (true) 54941.83Skamil continue; 54951.1Skamil 54961.83Skamil FORKEE_ASSERT(0 && "Not reached"); 54971.1Skamil } 54981.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54991.1Skamil 55001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55021.1Skamil 55031.1Skamil validate_status_stopped(status, sigval); 55041.1Skamil 55051.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 55061.83Skamil SYSCALL_REQUIRE( 55071.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55081.1Skamil 55091.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55101.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55111.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55121.83Skamil info.psi_siginfo.si_errno); 55131.1Skamil 55141.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55151.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55161.1Skamil 55171.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 55181.83Skamil memset(&event, 0, sizeof(event)); 55191.83Skamil if (trace_create) 55201.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 55211.83Skamil if (trace_exit) 55221.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 55231.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 55241.1Skamil 55251.13Schristos DPRINTF("Before resuming the child process where it left off and " 55261.1Skamil "without signal to be sent\n"); 55271.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55281.1Skamil 55291.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 55301.1Skamil 55311.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 55321.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55331.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55341.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55351.83Skamil child); 55361.1Skamil 55371.83Skamil validate_status_stopped(status, SIGTRAP); 55381.1Skamil 55391.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55401.83Skamil "child\n"); 55411.83Skamil SYSCALL_REQUIRE( 55421.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55431.1Skamil 55441.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55451.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55461.83Skamil "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, SIGTRAP); 55511.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55521.1Skamil 55531.83Skamil SYSCALL_REQUIRE( 55541.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55551.1Skamil 55561.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 55571.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 55581.1Skamil 55591.83Skamil lid = state.pe_lwp; 55601.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 55611.1Skamil 55621.83Skamil traced_lwps[lid - 1] = true; 55631.1Skamil 55641.83Skamil DPRINTF("Before resuming the child process where it left off " 55651.83Skamil "and without signal to be sent\n"); 55661.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55671.83Skamil } 55681.1Skamil 55691.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 55701.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55711.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55721.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55731.83Skamil child); 55741.1Skamil 55751.83Skamil validate_status_stopped(status, SIGTRAP); 55761.1Skamil 55771.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55781.83Skamil "child\n"); 55791.83Skamil SYSCALL_REQUIRE( 55801.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55811.1Skamil 55821.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55831.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55841.83Skamil "si_errno=%#x\n", 55851.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55861.83Skamil info.psi_siginfo.si_errno); 55871.1Skamil 55881.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55891.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55901.1Skamil 55911.83Skamil SYSCALL_REQUIRE( 55921.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55931.1Skamil 55941.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 55951.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 55961.1Skamil 55971.83Skamil lid = state.pe_lwp; 55981.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 55991.1Skamil 56001.83Skamil if (trace_create) { 56011.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 56021.83Skamil traced_lwps[lid - 1] = false; 56031.83Skamil } 56041.1Skamil 56051.83Skamil DPRINTF("Before resuming the child process where it left off " 56061.83Skamil "and without signal to be sent\n"); 56071.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56081.83Skamil } 56091.1Skamil 56101.83Skamil kill(child, SIGKILL); 56111.1Skamil 56121.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 56131.1Skamil TWAIT_FNAME); 56141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56151.1Skamil 56161.83Skamil validate_status_signaled(status, SIGKILL, 0); 56171.1Skamil 56181.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 56191.1Skamil TWAIT_FNAME); 56201.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56211.1Skamil} 56221.1Skamil 56231.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 56241.83SkamilATF_TC(test); \ 56251.83SkamilATF_TC_HEAD(test, tc) \ 56261.83Skamil{ \ 56271.83Skamil atf_tc_set_md_var(tc, "descr", \ 56281.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 56291.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 56301.83Skamil trace_exit ? "" : "out"); \ 56311.83Skamil} \ 56321.83Skamil \ 56331.83SkamilATF_TC_BODY(test, tc) \ 56341.83Skamil{ \ 56351.83Skamil \ 56361.83Skamil trace_threads(trace_create, trace_exit); \ 56371.83Skamil} 56381.83Skamil 56391.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 56401.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 56411.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 56421.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 56431.83Skamil 56441.83Skamil/// ---------------------------------------------------------------------------- 56451.83Skamil 56461.84SkamilATF_TC(signal_mask_unrelated); 56471.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 56481.1Skamil{ 56491.1Skamil atf_tc_set_md_var(tc, "descr", 56501.1Skamil "Verify that masking single unrelated signal does not stop tracer " 56511.1Skamil "from catching other signals"); 56521.1Skamil} 56531.1Skamil 56541.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 56551.1Skamil{ 56561.1Skamil const int exitval = 5; 56571.1Skamil const int sigval = SIGSTOP; 56581.1Skamil const int sigmasked = SIGTRAP; 56591.1Skamil const int signotmasked = SIGINT; 56601.1Skamil pid_t child, wpid; 56611.1Skamil#if defined(TWAIT_HAVE_STATUS) 56621.1Skamil int status; 56631.1Skamil#endif 56641.1Skamil sigset_t intmask; 56651.1Skamil 56661.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56671.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56681.1Skamil if (child == 0) { 56691.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56701.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56711.1Skamil 56721.1Skamil sigemptyset(&intmask); 56731.1Skamil sigaddset(&intmask, sigmasked); 56741.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56751.1Skamil 56761.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56771.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56781.1Skamil 56791.13Schristos DPRINTF("Before raising %s from child\n", 56801.1Skamil strsignal(signotmasked)); 56811.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 56821.1Skamil 56831.13Schristos DPRINTF("Before exiting of the child process\n"); 56841.1Skamil _exit(exitval); 56851.1Skamil } 56861.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56871.1Skamil 56881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56901.1Skamil 56911.1Skamil validate_status_stopped(status, sigval); 56921.1Skamil 56931.13Schristos DPRINTF("Before resuming the child process where it left off and " 56941.1Skamil "without signal to be sent\n"); 56951.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56961.1Skamil 56971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56991.1Skamil 57001.1Skamil validate_status_stopped(status, signotmasked); 57011.1Skamil 57021.13Schristos DPRINTF("Before resuming the child process where it left off and " 57031.1Skamil "without signal to be sent\n"); 57041.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57051.1Skamil 57061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57081.1Skamil 57091.1Skamil validate_status_exited(status, exitval); 57101.1Skamil 57111.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57121.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57131.1Skamil} 57141.1Skamil 57151.84Skamil/// ---------------------------------------------------------------------------- 57161.84Skamil 57171.1Skamil#if defined(TWAIT_HAVE_PID) 57181.99Skamilstatic void 57191.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 57201.1Skamil{ 57211.1Skamil const int exitval = 5; 57221.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 57231.1Skamil const int sigval = SIGSTOP; 57241.99Skamil pid_t child, child2 = 0, wpid; 57251.1Skamil#if defined(TWAIT_HAVE_STATUS) 57261.1Skamil int status; 57271.1Skamil#endif 57281.1Skamil ptrace_state_t state; 57291.1Skamil const int slen = sizeof(state); 57301.1Skamil ptrace_event_t event; 57311.1Skamil const int elen = sizeof(event); 57321.99Skamil struct sigaction sa; 57331.99Skamil struct ptrace_siginfo info; 57341.99Skamil sigset_t intmask; 57351.99Skamil struct kinfo_proc2 kp; 57361.99Skamil size_t len = sizeof(kp); 57371.99Skamil 57381.99Skamil int name[6]; 57391.99Skamil const size_t namelen = __arraycount(name); 57401.99Skamil ki_sigset_t kp_sigmask; 57411.99Skamil ki_sigset_t kp_sigignore; 57421.1Skamil 57431.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 57441.14Schristos 57451.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57461.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57471.1Skamil if (child == 0) { 57481.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57491.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57501.1Skamil 57511.99Skamil if (masked) { 57521.99Skamil sigemptyset(&intmask); 57531.99Skamil sigaddset(&intmask, SIGTRAP); 57541.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 57551.99Skamil } 57561.99Skamil 57571.99Skamil if (ignored) { 57581.99Skamil memset(&sa, 0, sizeof(sa)); 57591.99Skamil sa.sa_handler = SIG_IGN; 57601.99Skamil sigemptyset(&sa.sa_mask); 57611.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 57621.99Skamil } 57631.1Skamil 57641.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57651.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57661.1Skamil 57671.126Skamil if (strcmp(fn, "spawn") == 0) { 57681.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 57691.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 57701.126Skamil } else { 57711.126Skamil if (strcmp(fn, "fork") == 0) { 57721.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 57731.126Skamil } else { 57741.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 57751.126Skamil } 57761.126Skamil if (child2 == 0) 57771.126Skamil _exit(exitval2); 57781.126Skamil } 57791.1Skamil 57801.1Skamil FORKEE_REQUIRE_SUCCESS 57811.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 57821.1Skamil 57831.1Skamil forkee_status_exited(status, exitval2); 57841.1Skamil 57851.13Schristos DPRINTF("Before exiting of the child process\n"); 57861.1Skamil _exit(exitval); 57871.1Skamil } 57881.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57891.1Skamil 57901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57921.1Skamil 57931.1Skamil validate_status_stopped(status, sigval); 57941.1Skamil 57951.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 57961.99Skamil SYSCALL_REQUIRE( 57971.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 57981.99Skamil 57991.99Skamil DPRINTF("Before checking siginfo_t\n"); 58001.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 58011.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 58021.1Skamil 58031.99Skamil name[0] = CTL_KERN, 58041.99Skamil name[1] = KERN_PROC2, 58051.99Skamil name[2] = KERN_PROC_PID; 58061.99Skamil name[3] = child; 58071.99Skamil name[4] = sizeof(kp); 58081.99Skamil name[5] = 1; 58091.1Skamil 58101.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58111.1Skamil 58121.99Skamil if (masked) 58131.99Skamil kp_sigmask = kp.p_sigmask; 58141.1Skamil 58151.99Skamil if (ignored) 58161.99Skamil kp_sigignore = kp.p_sigignore; 58171.1Skamil 58181.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 58191.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 58201.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 58211.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 58221.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 58231.99Skamil event.pe_set_event = 0; 58241.126Skamil if (strcmp(fn, "spawn") == 0) 58251.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 58261.126Skamil if (strcmp(fn, "fork") == 0) 58271.99Skamil event.pe_set_event |= PTRACE_FORK; 58281.126Skamil if (strcmp(fn, "vfork") == 0) 58291.99Skamil event.pe_set_event |= PTRACE_VFORK; 58301.126Skamil if (strcmp(fn, "vforkdone") == 0) 58311.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 58321.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58331.1Skamil 58341.99Skamil DPRINTF("Before resuming the child process where it left off and " 58351.99Skamil "without signal to be sent\n"); 58361.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58371.1Skamil 58381.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 58391.126Skamil strcmp(fn, "vfork") == 0) { 58401.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58411.99Skamil child); 58421.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58431.99Skamil child); 58441.1Skamil 58451.99Skamil validate_status_stopped(status, SIGTRAP); 58461.1Skamil 58471.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58481.1Skamil 58491.99Skamil if (masked) { 58501.99Skamil DPRINTF("kp_sigmask=" 58511.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58521.99Skamil PRIx32 "\n", 58531.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58541.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58551.1Skamil 58561.99Skamil DPRINTF("kp.p_sigmask=" 58571.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58581.99Skamil PRIx32 "\n", 58591.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58601.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58611.1Skamil 58621.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58631.99Skamil sizeof(kp_sigmask))); 58641.99Skamil } 58651.1Skamil 58661.99Skamil if (ignored) { 58671.99Skamil DPRINTF("kp_sigignore=" 58681.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58691.99Skamil PRIx32 "\n", 58701.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58711.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58721.1Skamil 58731.99Skamil DPRINTF("kp.p_sigignore=" 58741.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58751.99Skamil PRIx32 "\n", 58761.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58771.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58781.1Skamil 58791.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58801.99Skamil sizeof(kp_sigignore))); 58811.99Skamil } 58821.1Skamil 58831.99Skamil SYSCALL_REQUIRE( 58841.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58851.126Skamil if (strcmp(fn, "spawn") == 0) { 58861.126Skamil ATF_REQUIRE_EQ( 58871.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 58881.126Skamil PTRACE_POSIX_SPAWN); 58891.126Skamil } 58901.126Skamil if (strcmp(fn, "fork") == 0) { 58911.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 58921.99Skamil PTRACE_FORK); 58931.99Skamil } 58941.126Skamil if (strcmp(fn, "vfork") == 0) { 58951.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 58961.99Skamil PTRACE_VFORK); 58971.99Skamil } 58981.1Skamil 58991.99Skamil child2 = state.pe_other_pid; 59001.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 59011.1Skamil 59021.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 59031.99Skamil "%d\n", TWAIT_FNAME, child2, child); 59041.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 59051.99Skamil child2); 59061.1Skamil 59071.99Skamil validate_status_stopped(status, SIGTRAP); 59081.1Skamil 59091.99Skamil name[3] = child2; 59101.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59111.1Skamil 59121.99Skamil if (masked) { 59131.99Skamil DPRINTF("kp_sigmask=" 59141.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59151.99Skamil PRIx32 "\n", 59161.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59171.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59181.1Skamil 59191.99Skamil DPRINTF("kp.p_sigmask=" 59201.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59211.99Skamil PRIx32 "\n", 59221.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59231.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59241.14Schristos 59251.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59261.99Skamil sizeof(kp_sigmask))); 59271.99Skamil } 59281.1Skamil 59291.99Skamil if (ignored) { 59301.99Skamil DPRINTF("kp_sigignore=" 59311.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59321.99Skamil PRIx32 "\n", 59331.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59341.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59351.1Skamil 59361.99Skamil DPRINTF("kp.p_sigignore=" 59371.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59381.99Skamil PRIx32 "\n", 59391.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59401.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59411.1Skamil 59421.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59431.99Skamil sizeof(kp_sigignore))); 59441.99Skamil } 59451.1Skamil 59461.99Skamil SYSCALL_REQUIRE( 59471.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 59481.126Skamil if (strcmp(fn, "spawn") == 0) { 59491.126Skamil ATF_REQUIRE_EQ( 59501.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59511.126Skamil PTRACE_POSIX_SPAWN); 59521.126Skamil } 59531.126Skamil if (strcmp(fn, "fork") == 0) { 59541.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59551.99Skamil PTRACE_FORK); 59561.99Skamil } 59571.126Skamil if (strcmp(fn, "vfork") == 0) { 59581.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59591.99Skamil PTRACE_VFORK); 59601.99Skamil } 59611.1Skamil 59621.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 59631.1Skamil 59641.99Skamil DPRINTF("Before resuming the forkee process where it left off " 59651.99Skamil "and without signal to be sent\n"); 59661.99Skamil SYSCALL_REQUIRE( 59671.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 59681.1Skamil 59691.99Skamil DPRINTF("Before resuming the child process where it left off " 59701.99Skamil "and without signal to be sent\n"); 59711.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59721.1Skamil } 59731.1Skamil 59741.126Skamil if (strcmp(fn, "vforkdone") == 0) { 59751.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 59761.99Skamil child); 59771.99Skamil TWAIT_REQUIRE_SUCCESS( 59781.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 59791.1Skamil 59801.99Skamil validate_status_stopped(status, SIGTRAP); 59811.1Skamil 59821.99Skamil name[3] = child; 59831.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59841.1Skamil 59851.102Skamil /* 59861.102Skamil * SIGCHLD is now pending in the signal queue and 59871.102Skamil * the kernel presents it to userland as a masked signal. 59881.102Skamil */ 59891.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 59901.102Skamil 59911.99Skamil if (masked) { 59921.99Skamil DPRINTF("kp_sigmask=" 59931.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59941.99Skamil PRIx32 "\n", 59951.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59961.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59971.1Skamil 59981.99Skamil DPRINTF("kp.p_sigmask=" 59991.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60001.99Skamil PRIx32 "\n", 60011.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 60021.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 60031.1Skamil 60041.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 60051.99Skamil sizeof(kp_sigmask))); 60061.99Skamil } 60071.1Skamil 60081.99Skamil if (ignored) { 60091.99Skamil DPRINTF("kp_sigignore=" 60101.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60111.99Skamil PRIx32 "\n", 60121.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 60131.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 60141.1Skamil 60151.99Skamil DPRINTF("kp.p_sigignore=" 60161.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60171.99Skamil PRIx32 "\n", 60181.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 60191.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 60201.1Skamil 60211.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 60221.99Skamil sizeof(kp_sigignore))); 60231.99Skamil } 60241.1Skamil 60251.99Skamil SYSCALL_REQUIRE( 60261.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60271.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 60281.1Skamil 60291.99Skamil child2 = state.pe_other_pid; 60301.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 60311.99Skamil child2); 60321.1Skamil 60331.99Skamil DPRINTF("Before resuming the child process where it left off " 60341.99Skamil "and without signal to be sent\n"); 60351.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60361.99Skamil } 60371.1Skamil 60381.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 60391.126Skamil strcmp(fn, "vfork") == 0) { 60401.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 60411.99Skamil "\n", TWAIT_FNAME); 60421.99Skamil TWAIT_REQUIRE_SUCCESS( 60431.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 60441.1Skamil 60451.99Skamil validate_status_exited(status, exitval2); 60461.1Skamil 60471.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 60481.99Skamil "process\n", TWAIT_FNAME); 60491.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 60501.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 60511.99Skamil } 60521.1Skamil 60531.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60541.1Skamil "SIGCHLD\n", TWAIT_FNAME); 60551.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60561.1Skamil 60571.1Skamil validate_status_stopped(status, SIGCHLD); 60581.1Skamil 60591.57Skamil DPRINTF("Before resuming the child process where it left off and " 60601.1Skamil "without signal to be sent\n"); 60611.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60621.1Skamil 60631.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 60641.1Skamil TWAIT_FNAME); 60651.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60661.1Skamil 60671.1Skamil validate_status_exited(status, exitval); 60681.1Skamil 60691.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60701.57Skamil TWAIT_FNAME); 60711.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60721.1Skamil} 60731.1Skamil 60741.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 60751.99SkamilATF_TC(name); \ 60761.99SkamilATF_TC_HEAD(name, tc) \ 60771.99Skamil{ \ 60781.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 60791.99Skamil "regardless of signal %s%s", \ 60801.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 60811.99Skamil} \ 60821.99Skamil \ 60831.99SkamilATF_TC_BODY(name, tc) \ 60841.99Skamil{ \ 60851.99Skamil \ 60861.126Skamil fork2_body(fn, masked, ignored); \ 60871.1Skamil} 60881.1Skamil 60891.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 60901.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 60911.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 60921.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 60931.110Skamil#if TEST_VFORK_ENABLED 60941.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 60951.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 60961.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 60971.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 60981.1Skamil#endif 60991.110Skamil#endif 61001.1Skamil 61011.99Skamil/// ---------------------------------------------------------------------------- 61021.1Skamil 61031.83Skamilvolatile lwpid_t the_lwp_id = 0; 61041.83Skamil 61051.83Skamilstatic void 61061.83Skamillwp_main_func(void *arg) 61071.83Skamil{ 61081.83Skamil the_lwp_id = _lwp_self(); 61091.83Skamil _lwp_exit(); 61101.83Skamil} 61111.83Skamil 61121.1SkamilATF_TC(signal9); 61131.1SkamilATF_TC_HEAD(signal9, tc) 61141.1Skamil{ 61151.1Skamil atf_tc_set_md_var(tc, "descr", 61161.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61171.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 61181.1Skamil} 61191.1Skamil 61201.1SkamilATF_TC_BODY(signal9, tc) 61211.1Skamil{ 61221.1Skamil const int exitval = 5; 61231.1Skamil const int sigval = SIGSTOP; 61241.1Skamil const int sigmasked = SIGTRAP; 61251.1Skamil pid_t child, wpid; 61261.1Skamil#if defined(TWAIT_HAVE_STATUS) 61271.1Skamil int status; 61281.1Skamil#endif 61291.1Skamil sigset_t intmask; 61301.1Skamil ptrace_state_t state; 61311.1Skamil const int slen = sizeof(state); 61321.1Skamil ptrace_event_t event; 61331.1Skamil const int elen = sizeof(event); 61341.1Skamil ucontext_t uc; 61351.1Skamil lwpid_t lid; 61361.1Skamil static const size_t ssize = 16*1024; 61371.1Skamil void *stack; 61381.1Skamil 61391.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61401.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61411.1Skamil if (child == 0) { 61421.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61431.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61441.1Skamil 61451.1Skamil sigemptyset(&intmask); 61461.1Skamil sigaddset(&intmask, sigmasked); 61471.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61481.1Skamil 61491.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61501.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61511.1Skamil 61521.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61531.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61541.1Skamil 61551.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61561.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61571.1Skamil 61581.13Schristos DPRINTF("Before creating new in child\n"); 61591.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61601.1Skamil 61611.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61621.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61631.1Skamil 61641.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61651.1Skamil "are the same\n", lid, the_lwp_id); 61661.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61671.1Skamil 61681.13Schristos DPRINTF("Before exiting of the child process\n"); 61691.1Skamil _exit(exitval); 61701.1Skamil } 61711.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61721.1Skamil 61731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61751.1Skamil 61761.1Skamil validate_status_stopped(status, sigval); 61771.1Skamil 61781.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61791.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 61801.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61811.1Skamil 61821.13Schristos DPRINTF("Before resuming the child process where it left off and " 61831.1Skamil "without signal to be sent\n"); 61841.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61851.1Skamil 61861.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61871.1Skamil "SIGTRAP\n", TWAIT_FNAME); 61881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61891.1Skamil 61901.1Skamil validate_status_stopped(status, sigmasked); 61911.1Skamil 61921.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 61931.1Skamil 61941.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 61951.1Skamil 61961.1Skamil lid = state.pe_lwp; 61971.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 61981.1Skamil 61991.13Schristos DPRINTF("Before resuming the child process where it left off and " 62001.1Skamil "without signal to be sent\n"); 62011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62021.1Skamil 62031.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62041.1Skamil TWAIT_FNAME); 62051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62061.1Skamil 62071.1Skamil validate_status_exited(status, exitval); 62081.1Skamil 62091.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62101.1Skamil TWAIT_FNAME); 62111.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62121.1Skamil} 62131.1Skamil 62141.1SkamilATF_TC(signal10); 62151.1SkamilATF_TC_HEAD(signal10, tc) 62161.1Skamil{ 62171.1Skamil atf_tc_set_md_var(tc, "descr", 62181.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 62191.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 62201.1Skamil} 62211.1Skamil 62221.1SkamilATF_TC_BODY(signal10, tc) 62231.1Skamil{ 62241.1Skamil const int exitval = 5; 62251.1Skamil const int sigval = SIGSTOP; 62261.1Skamil const int sigmasked = SIGTRAP; 62271.1Skamil pid_t child, wpid; 62281.1Skamil#if defined(TWAIT_HAVE_STATUS) 62291.1Skamil int status; 62301.1Skamil#endif 62311.1Skamil sigset_t intmask; 62321.1Skamil ptrace_state_t state; 62331.1Skamil const int slen = sizeof(state); 62341.1Skamil ptrace_event_t event; 62351.1Skamil const int elen = sizeof(event); 62361.1Skamil ucontext_t uc; 62371.1Skamil lwpid_t lid; 62381.1Skamil static const size_t ssize = 16*1024; 62391.1Skamil void *stack; 62401.1Skamil 62411.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62421.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62431.1Skamil if (child == 0) { 62441.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62451.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62461.1Skamil 62471.1Skamil sigemptyset(&intmask); 62481.1Skamil sigaddset(&intmask, sigmasked); 62491.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62501.1Skamil 62511.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62521.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62531.1Skamil 62541.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62551.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62561.1Skamil 62571.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62581.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 62591.1Skamil 62601.13Schristos DPRINTF("Before creating new in child\n"); 62611.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62621.1Skamil 62631.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62641.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62651.1Skamil 62661.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62671.1Skamil "are the same\n", lid, the_lwp_id); 62681.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62691.1Skamil 62701.13Schristos DPRINTF("Before exiting of the child process\n"); 62711.1Skamil _exit(exitval); 62721.1Skamil } 62731.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62741.1Skamil 62751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62771.1Skamil 62781.1Skamil validate_status_stopped(status, sigval); 62791.1Skamil 62801.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 62811.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 62821.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 62831.1Skamil 62841.13Schristos DPRINTF("Before resuming the child process where it left off and " 62851.1Skamil "without signal to be sent\n"); 62861.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62871.1Skamil 62881.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62891.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62911.1Skamil 62921.1Skamil validate_status_stopped(status, sigmasked); 62931.1Skamil 62941.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 62951.1Skamil 62961.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 62971.1Skamil 62981.1Skamil lid = state.pe_lwp; 62991.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 63001.1Skamil 63011.13Schristos DPRINTF("Before resuming the child process where it left off and " 63021.1Skamil "without signal to be sent\n"); 63031.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63041.1Skamil 63051.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63061.1Skamil TWAIT_FNAME); 63071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63081.1Skamil 63091.1Skamil validate_status_exited(status, exitval); 63101.1Skamil 63111.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63121.1Skamil TWAIT_FNAME); 63131.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63141.1Skamil} 63151.1Skamil 63161.1Skamilstatic void 63171.1Skamillwp_main_stop(void *arg) 63181.1Skamil{ 63191.1Skamil the_lwp_id = _lwp_self(); 63201.1Skamil 63211.1Skamil raise(SIGTRAP); 63221.1Skamil 63231.1Skamil _lwp_exit(); 63241.1Skamil} 63251.1Skamil 63261.1SkamilATF_TC(suspend1); 63271.1SkamilATF_TC_HEAD(suspend1, tc) 63281.1Skamil{ 63291.1Skamil atf_tc_set_md_var(tc, "descr", 63301.1Skamil "Verify that a thread can be suspended by a debugger and later " 63311.1Skamil "resumed by a tracee"); 63321.1Skamil} 63331.1Skamil 63341.1SkamilATF_TC_BODY(suspend1, tc) 63351.1Skamil{ 63361.1Skamil const int exitval = 5; 63371.1Skamil const int sigval = SIGSTOP; 63381.1Skamil pid_t child, wpid; 63391.1Skamil#if defined(TWAIT_HAVE_STATUS) 63401.1Skamil int status; 63411.1Skamil#endif 63421.1Skamil ucontext_t uc; 63431.1Skamil lwpid_t lid; 63441.1Skamil static const size_t ssize = 16*1024; 63451.1Skamil void *stack; 63461.1Skamil struct ptrace_lwpinfo pl; 63471.1Skamil struct ptrace_siginfo psi; 63481.1Skamil volatile int go = 0; 63491.1Skamil 63501.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63511.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63521.1Skamil if (child == 0) { 63531.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63541.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63551.1Skamil 63561.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63571.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63581.1Skamil 63591.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 63601.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 63611.1Skamil 63621.13Schristos DPRINTF("Before making context for new lwp in child\n"); 63631.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 63641.1Skamil 63651.13Schristos DPRINTF("Before creating new in child\n"); 63661.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 63671.1Skamil 63681.1Skamil while (go == 0) 63691.1Skamil continue; 63701.1Skamil 63711.1Skamil raise(SIGINT); 63721.1Skamil 63731.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 63741.1Skamil 63751.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 63761.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 63771.1Skamil 63781.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 63791.1Skamil "are the same\n", lid, the_lwp_id); 63801.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 63811.1Skamil 63821.13Schristos DPRINTF("Before exiting of the child process\n"); 63831.1Skamil _exit(exitval); 63841.1Skamil } 63851.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63861.1Skamil 63871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63891.1Skamil 63901.1Skamil validate_status_stopped(status, sigval); 63911.1Skamil 63921.13Schristos DPRINTF("Before resuming the child process where it left off and " 63931.1Skamil "without signal to be sent\n"); 63941.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63951.1Skamil 63961.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63971.1Skamil "SIGTRAP\n", TWAIT_FNAME); 63981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63991.1Skamil 64001.1Skamil validate_status_stopped(status, SIGTRAP); 64011.1Skamil 64021.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64031.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64041.1Skamil 64051.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64061.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64071.1Skamil 64081.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 64091.1Skamil child, getpid()); 64101.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 64111.1Skamil 64121.13Schristos DPRINTF("Before resuming the child process where it left off and " 64131.1Skamil "without signal to be sent\n"); 64141.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64151.1Skamil 64161.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64171.1Skamil "SIGINT\n", TWAIT_FNAME); 64181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64191.1Skamil 64201.1Skamil validate_status_stopped(status, SIGINT); 64211.1Skamil 64221.1Skamil pl.pl_lwpid = 0; 64231.1Skamil 64241.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64251.1Skamil while (pl.pl_lwpid != 0) { 64261.1Skamil 64271.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64281.1Skamil switch (pl.pl_lwpid) { 64291.1Skamil case 1: 64301.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 64311.1Skamil break; 64321.1Skamil case 2: 64331.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 64341.1Skamil break; 64351.1Skamil } 64361.1Skamil } 64371.1Skamil 64381.13Schristos DPRINTF("Before resuming the child process where it left off and " 64391.1Skamil "without signal to be sent\n"); 64401.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64411.1Skamil 64421.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 64431.1Skamil TWAIT_FNAME); 64441.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64451.1Skamil 64461.1Skamil validate_status_exited(status, exitval); 64471.1Skamil 64481.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64491.1Skamil TWAIT_FNAME); 64501.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64511.1Skamil} 64521.1Skamil 64531.1SkamilATF_TC(suspend2); 64541.1SkamilATF_TC_HEAD(suspend2, tc) 64551.1Skamil{ 64561.1Skamil atf_tc_set_md_var(tc, "descr", 64571.1Skamil "Verify that the while the only thread within a process is " 64581.1Skamil "suspended, the whole process cannot be unstopped"); 64591.1Skamil} 64601.1Skamil 64611.1SkamilATF_TC_BODY(suspend2, tc) 64621.1Skamil{ 64631.1Skamil const int exitval = 5; 64641.1Skamil const int sigval = SIGSTOP; 64651.1Skamil pid_t child, wpid; 64661.1Skamil#if defined(TWAIT_HAVE_STATUS) 64671.1Skamil int status; 64681.1Skamil#endif 64691.1Skamil struct ptrace_siginfo psi; 64701.1Skamil 64711.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64721.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64731.1Skamil if (child == 0) { 64741.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64751.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64761.1Skamil 64771.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64781.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64791.1Skamil 64801.13Schristos DPRINTF("Before exiting of the child process\n"); 64811.1Skamil _exit(exitval); 64821.1Skamil } 64831.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64841.1Skamil 64851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64871.1Skamil 64881.1Skamil validate_status_stopped(status, sigval); 64891.1Skamil 64901.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64911.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64921.1Skamil 64931.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64941.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64951.1Skamil 64961.13Schristos DPRINTF("Before resuming the child process where it left off and " 64971.1Skamil "without signal to be sent\n"); 64981.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 64991.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 65001.1Skamil 65011.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65021.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65031.1Skamil 65041.13Schristos DPRINTF("Before resuming the child process where it left off and " 65051.1Skamil "without signal to be sent\n"); 65061.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65071.1Skamil 65081.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65091.1Skamil TWAIT_FNAME); 65101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65111.1Skamil 65121.1Skamil validate_status_exited(status, exitval); 65131.1Skamil 65141.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65151.1Skamil TWAIT_FNAME); 65161.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65171.1Skamil} 65181.1Skamil 65191.1SkamilATF_TC(resume1); 65201.1SkamilATF_TC_HEAD(resume1, tc) 65211.1Skamil{ 65221.1Skamil atf_tc_set_md_var(tc, "descr", 65231.1Skamil "Verify that a thread can be suspended by a debugger and later " 65241.1Skamil "resumed by the debugger"); 65251.1Skamil} 65261.1Skamil 65271.1SkamilATF_TC_BODY(resume1, tc) 65281.1Skamil{ 65291.1Skamil struct msg_fds fds; 65301.1Skamil const int exitval = 5; 65311.1Skamil const int sigval = SIGSTOP; 65321.1Skamil pid_t child, wpid; 65331.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 65341.1Skamil#if defined(TWAIT_HAVE_STATUS) 65351.1Skamil int status; 65361.1Skamil#endif 65371.1Skamil ucontext_t uc; 65381.1Skamil lwpid_t lid; 65391.1Skamil static const size_t ssize = 16*1024; 65401.1Skamil void *stack; 65411.1Skamil struct ptrace_lwpinfo pl; 65421.1Skamil struct ptrace_siginfo psi; 65431.1Skamil 65441.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 65451.1Skamil 65461.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65471.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65481.1Skamil if (child == 0) { 65491.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65501.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65511.1Skamil 65521.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65531.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65541.1Skamil 65551.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 65561.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 65571.1Skamil 65581.13Schristos DPRINTF("Before making context for new lwp in child\n"); 65591.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 65601.1Skamil 65611.13Schristos DPRINTF("Before creating new in child\n"); 65621.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 65631.1Skamil 65641.1Skamil CHILD_TO_PARENT("Message", fds, msg); 65651.1Skamil 65661.1Skamil raise(SIGINT); 65671.1Skamil 65681.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 65691.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 65701.1Skamil 65711.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 65721.1Skamil "are the same\n", lid, the_lwp_id); 65731.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 65741.1Skamil 65751.13Schristos DPRINTF("Before exiting of the child process\n"); 65761.1Skamil _exit(exitval); 65771.1Skamil } 65781.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65791.1Skamil 65801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65821.1Skamil 65831.1Skamil validate_status_stopped(status, sigval); 65841.1Skamil 65851.13Schristos DPRINTF("Before resuming the child process where it left off and " 65861.1Skamil "without signal to be sent\n"); 65871.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65881.1Skamil 65891.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 65901.1Skamil "SIGTRAP\n", TWAIT_FNAME); 65911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65921.1Skamil 65931.1Skamil validate_status_stopped(status, SIGTRAP); 65941.1Skamil 65951.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 65961.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 65971.1Skamil 65981.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 65991.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 66001.1Skamil 66011.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 66021.1Skamil 66031.13Schristos DPRINTF("Before resuming the child process where it left off and " 66041.1Skamil "without signal to be sent\n"); 66051.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66061.1Skamil 66071.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 66081.1Skamil "SIGINT\n", TWAIT_FNAME); 66091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66101.1Skamil 66111.1Skamil validate_status_stopped(status, SIGINT); 66121.1Skamil 66131.1Skamil pl.pl_lwpid = 0; 66141.1Skamil 66151.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66161.1Skamil while (pl.pl_lwpid != 0) { 66171.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66181.1Skamil switch (pl.pl_lwpid) { 66191.1Skamil case 1: 66201.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 66211.1Skamil break; 66221.1Skamil case 2: 66231.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 66241.1Skamil break; 66251.1Skamil } 66261.1Skamil } 66271.1Skamil 66281.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 66291.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 66301.1Skamil 66311.13Schristos DPRINTF("Before resuming the child process where it left off and " 66321.1Skamil "without signal to be sent\n"); 66331.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66341.1Skamil 66351.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 66361.1Skamil TWAIT_FNAME); 66371.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66381.1Skamil 66391.1Skamil validate_status_exited(status, exitval); 66401.1Skamil 66411.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 66421.1Skamil TWAIT_FNAME); 66431.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66441.1Skamil 66451.1Skamil msg_close(&fds); 66461.1Skamil} 66471.1Skamil 66481.1SkamilATF_TC(syscall1); 66491.1SkamilATF_TC_HEAD(syscall1, tc) 66501.1Skamil{ 66511.1Skamil atf_tc_set_md_var(tc, "descr", 66521.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 66531.1Skamil} 66541.1Skamil 66551.1SkamilATF_TC_BODY(syscall1, tc) 66561.1Skamil{ 66571.1Skamil const int exitval = 5; 66581.1Skamil const int sigval = SIGSTOP; 66591.1Skamil pid_t child, wpid; 66601.1Skamil#if defined(TWAIT_HAVE_STATUS) 66611.1Skamil int status; 66621.1Skamil#endif 66631.1Skamil struct ptrace_siginfo info; 66641.1Skamil memset(&info, 0, sizeof(info)); 66651.1Skamil 66661.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66671.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66681.1Skamil if (child == 0) { 66691.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66701.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66711.1Skamil 66721.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66731.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66741.1Skamil 66751.1Skamil syscall(SYS_getpid); 66761.1Skamil 66771.13Schristos DPRINTF("Before exiting of the child process\n"); 66781.1Skamil _exit(exitval); 66791.1Skamil } 66801.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66811.1Skamil 66821.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66841.1Skamil 66851.1Skamil validate_status_stopped(status, sigval); 66861.1Skamil 66871.13Schristos DPRINTF("Before resuming the child process where it left off and " 66881.1Skamil "without signal to be sent\n"); 66891.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66901.1Skamil 66911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66931.1Skamil 66941.1Skamil validate_status_stopped(status, SIGTRAP); 66951.1Skamil 66961.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 66971.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66981.1Skamil 66991.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 67001.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 67011.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67021.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 67031.1Skamil 67041.13Schristos DPRINTF("Before resuming the child process where it left off and " 67051.1Skamil "without signal to be sent\n"); 67061.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67071.1Skamil 67081.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67101.1Skamil 67111.1Skamil validate_status_stopped(status, SIGTRAP); 67121.1Skamil 67131.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67141.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67151.1Skamil 67161.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 67171.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 67181.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67191.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 67201.1Skamil 67211.13Schristos DPRINTF("Before resuming the child process where it left off and " 67221.1Skamil "without signal to be sent\n"); 67231.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67241.1Skamil 67251.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67271.1Skamil 67281.1Skamil validate_status_exited(status, exitval); 67291.1Skamil 67301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67311.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 67321.1Skamil} 67331.1Skamil 67341.1SkamilATF_TC(syscallemu1); 67351.1SkamilATF_TC_HEAD(syscallemu1, tc) 67361.1Skamil{ 67371.1Skamil atf_tc_set_md_var(tc, "descr", 67381.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 67391.1Skamil} 67401.1Skamil 67411.1SkamilATF_TC_BODY(syscallemu1, tc) 67421.1Skamil{ 67431.1Skamil const int exitval = 5; 67441.1Skamil const int sigval = SIGSTOP; 67451.1Skamil pid_t child, wpid; 67461.1Skamil#if defined(TWAIT_HAVE_STATUS) 67471.1Skamil int status; 67481.1Skamil#endif 67491.1Skamil 67501.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 67511.6Skamil /* syscallemu does not work on sparc (32-bit) */ 67521.6Skamil atf_tc_expect_fail("PR kern/52166"); 67531.6Skamil#endif 67541.6Skamil 67551.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 67561.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 67571.1Skamil if (child == 0) { 67581.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67591.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67601.1Skamil 67611.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67621.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67631.1Skamil 67641.1Skamil syscall(SYS_exit, 100); 67651.1Skamil 67661.13Schristos DPRINTF("Before exiting of the child process\n"); 67671.1Skamil _exit(exitval); 67681.1Skamil } 67691.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67701.1Skamil 67711.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67721.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67731.1Skamil 67741.1Skamil validate_status_stopped(status, sigval); 67751.1Skamil 67761.13Schristos DPRINTF("Before resuming the child process where it left off and " 67771.1Skamil "without signal to be sent\n"); 67781.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67791.1Skamil 67801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67821.1Skamil 67831.1Skamil validate_status_stopped(status, SIGTRAP); 67841.1Skamil 67851.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 67861.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 67871.1Skamil 67881.13Schristos DPRINTF("Before resuming the child process where it left off and " 67891.1Skamil "without signal to be sent\n"); 67901.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67911.1Skamil 67921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67941.1Skamil 67951.1Skamil validate_status_stopped(status, SIGTRAP); 67961.1Skamil 67971.13Schristos DPRINTF("Before resuming the child process where it left off and " 67981.1Skamil "without signal to be sent\n"); 67991.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68001.1Skamil 68011.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68031.1Skamil 68041.1Skamil validate_status_exited(status, exitval); 68051.1Skamil 68061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68071.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68081.1Skamil} 68091.1Skamil 68101.103Skamil/// ---------------------------------------------------------------------------- 68111.103Skamil 68121.106Skamilstatic void 68131.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 68141.106Skamil bool trackvforkdone) 68151.106Skamil{ 68161.106Skamil const int exitval = 5; 68171.106Skamil const int exitval2 = 15; 68181.106Skamil const int sigval = SIGSTOP; 68191.106Skamil pid_t child, child2 = 0, wpid; 68201.106Skamil#if defined(TWAIT_HAVE_STATUS) 68211.106Skamil int status; 68221.106Skamil#endif 68231.106Skamil ptrace_state_t state; 68241.106Skamil const int slen = sizeof(state); 68251.106Skamil ptrace_event_t event; 68261.106Skamil const int elen = sizeof(event); 68271.106Skamil 68281.106Skamil const size_t stack_size = 1024 * 1024; 68291.106Skamil void *stack, *stack_base; 68301.106Skamil 68311.106Skamil stack = malloc(stack_size); 68321.106Skamil ATF_REQUIRE(stack != NULL); 68331.106Skamil 68341.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 68351.106Skamil stack_base = stack; 68361.106Skamil#else 68371.106Skamil stack_base = (char *)stack + stack_size; 68381.106Skamil#endif 68391.106Skamil 68401.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 68411.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 68421.106Skamil if (child == 0) { 68431.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 68441.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 68451.106Skamil 68461.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 68471.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 68481.106Skamil 68491.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 68501.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 68511.106Skamil 68521.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 68531.106Skamil child2); 68541.106Skamil 68551.106Skamil // XXX WALLSIG? 68561.106Skamil FORKEE_REQUIRE_SUCCESS 68571.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 68581.106Skamil 68591.106Skamil forkee_status_exited(status, exitval2); 68601.106Skamil 68611.106Skamil DPRINTF("Before exiting of the child process\n"); 68621.106Skamil _exit(exitval); 68631.106Skamil } 68641.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 68651.106Skamil 68661.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68671.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68681.106Skamil 68691.106Skamil validate_status_stopped(status, sigval); 68701.106Skamil 68711.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 68721.106Skamil trackfork ? "|PTRACE_FORK" : "", 68731.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 68741.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 68751.106Skamil event.pe_set_event = 0; 68761.106Skamil if (trackfork) 68771.106Skamil event.pe_set_event |= PTRACE_FORK; 68781.106Skamil if (trackvfork) 68791.106Skamil event.pe_set_event |= PTRACE_VFORK; 68801.106Skamil if (trackvforkdone) 68811.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 68821.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 68831.106Skamil 68841.106Skamil DPRINTF("Before resuming the child process where it left off and " 68851.106Skamil "without signal to be sent\n"); 68861.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68871.106Skamil 68881.106Skamil#if defined(TWAIT_HAVE_PID) 68891.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68901.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68911.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68921.106Skamil child); 68931.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 68941.106Skamil child); 68951.106Skamil 68961.106Skamil validate_status_stopped(status, SIGTRAP); 68971.106Skamil 68981.106Skamil SYSCALL_REQUIRE( 68991.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69001.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 69011.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69021.106Skamil PTRACE_FORK); 69031.106Skamil } 69041.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69051.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69061.106Skamil PTRACE_VFORK); 69071.106Skamil } 69081.106Skamil 69091.106Skamil child2 = state.pe_other_pid; 69101.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 69111.106Skamil 69121.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 69131.106Skamil "%d\n", TWAIT_FNAME, child2, child); 69141.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 69151.106Skamil child2); 69161.106Skamil 69171.106Skamil validate_status_stopped(status, SIGTRAP); 69181.106Skamil 69191.106Skamil SYSCALL_REQUIRE( 69201.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 69211.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 69221.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69231.106Skamil PTRACE_FORK); 69241.106Skamil } 69251.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69261.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69271.106Skamil PTRACE_VFORK); 69281.106Skamil } 69291.106Skamil 69301.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 69311.106Skamil 69321.106Skamil DPRINTF("Before resuming the forkee process where it left off " 69331.106Skamil "and without signal to be sent\n"); 69341.106Skamil SYSCALL_REQUIRE( 69351.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 69361.106Skamil 69371.106Skamil DPRINTF("Before resuming the child process where it left off " 69381.106Skamil "and without signal to be sent\n"); 69391.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69401.106Skamil } 69411.106Skamil#endif 69421.106Skamil 69431.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 69441.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69451.106Skamil child); 69461.106Skamil TWAIT_REQUIRE_SUCCESS( 69471.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 69481.106Skamil 69491.106Skamil validate_status_stopped(status, SIGTRAP); 69501.106Skamil 69511.106Skamil SYSCALL_REQUIRE( 69521.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69531.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 69541.106Skamil 69551.106Skamil child2 = state.pe_other_pid; 69561.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 69571.106Skamil child2); 69581.106Skamil 69591.106Skamil DPRINTF("Before resuming the child process where it left off " 69601.106Skamil "and without signal to be sent\n"); 69611.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69621.106Skamil } 69631.106Skamil 69641.103Skamil#if defined(TWAIT_HAVE_PID) 69651.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 69661.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 69671.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 69681.106Skamil "\n", TWAIT_FNAME); 69691.106Skamil TWAIT_REQUIRE_SUCCESS( 69701.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 69711.106Skamil 69721.106Skamil validate_status_exited(status, exitval2); 69731.106Skamil 69741.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 69751.106Skamil "process\n", TWAIT_FNAME); 69761.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 69771.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 69781.106Skamil } 69791.106Skamil#endif 69801.106Skamil 69811.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 69821.106Skamil "SIGCHLD\n", TWAIT_FNAME); 69831.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69841.106Skamil 69851.106Skamil validate_status_stopped(status, SIGCHLD); 69861.106Skamil 69871.106Skamil DPRINTF("Before resuming the child process where it left off and " 69881.106Skamil "without signal to be sent\n"); 69891.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69901.106Skamil 69911.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 69921.106Skamil TWAIT_FNAME); 69931.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69941.106Skamil 69951.106Skamil validate_status_exited(status, exitval); 69961.103Skamil 69971.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 69981.106Skamil TWAIT_FNAME); 69991.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 70001.106Skamil} 70011.103Skamil 70021.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 70031.106SkamilATF_TC(name); \ 70041.106SkamilATF_TC_HEAD(name, tc) \ 70051.106Skamil{ \ 70061.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 70071.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 70081.106Skamil #flags, \ 70091.106Skamil tfork ? "|PTRACE_FORK" : "", \ 70101.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 70111.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 70121.106Skamil} \ 70131.106Skamil \ 70141.106SkamilATF_TC_BODY(name, tc) \ 70151.106Skamil{ \ 70161.106Skamil \ 70171.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 70181.103Skamil} 70191.103Skamil 70201.106SkamilCLONE_TEST(clone1, 0, false, false, false) 70211.106Skamil#if defined(TWAIT_HAVE_PID) 70221.106SkamilCLONE_TEST(clone2, 0, true, false, false) 70231.106SkamilCLONE_TEST(clone3, 0, false, true, false) 70241.106SkamilCLONE_TEST(clone4, 0, true, true, false) 70251.106Skamil#endif 70261.106SkamilCLONE_TEST(clone5, 0, false, false, true) 70271.106Skamil#if defined(TWAIT_HAVE_PID) 70281.106SkamilCLONE_TEST(clone6, 0, true, false, true) 70291.106SkamilCLONE_TEST(clone7, 0, false, true, true) 70301.106SkamilCLONE_TEST(clone8, 0, true, true, true) 70311.106Skamil#endif 70321.106Skamil 70331.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 70341.106Skamil#if defined(TWAIT_HAVE_PID) 70351.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 70361.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 70371.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 70381.106Skamil#endif 70391.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 70401.106Skamil#if defined(TWAIT_HAVE_PID) 70411.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 70421.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 70431.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 70441.106Skamil#endif 70451.106Skamil 70461.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 70471.106Skamil#if defined(TWAIT_HAVE_PID) 70481.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 70491.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 70501.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 70511.106Skamil#endif 70521.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 70531.106Skamil#if defined(TWAIT_HAVE_PID) 70541.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 70551.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 70561.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 70571.106Skamil#endif 70581.106Skamil 70591.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 70601.106Skamil#if defined(TWAIT_HAVE_PID) 70611.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 70621.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 70631.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 70641.106Skamil#endif 70651.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 70661.106Skamil#if defined(TWAIT_HAVE_PID) 70671.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 70681.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 70691.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 70701.106Skamil#endif 70711.106Skamil 70721.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 70731.106Skamil#if defined(TWAIT_HAVE_PID) 70741.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 70751.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 70761.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 70771.106Skamil#endif 70781.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 70791.106Skamil#if defined(TWAIT_HAVE_PID) 70801.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 70811.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 70821.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 70831.106Skamil#endif 70841.106Skamil 70851.110Skamil#if TEST_VFORK_ENABLED 70861.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 70871.106Skamil#if defined(TWAIT_HAVE_PID) 70881.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 70891.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 70901.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 70911.106Skamil#endif 70921.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 70931.106Skamil#if defined(TWAIT_HAVE_PID) 70941.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 70951.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 70961.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 70971.106Skamil#endif 70981.110Skamil#endif 70991.106Skamil 71001.106Skamil/// ---------------------------------------------------------------------------- 71011.106Skamil 71021.106Skamil#if defined(TWAIT_HAVE_PID) 71031.103Skamilstatic void 71041.106Skamilclone_body2(int flags, bool masked, bool ignored) 71051.103Skamil{ 71061.103Skamil const int exitval = 5; 71071.103Skamil const int exitval2 = 15; 71081.103Skamil const int sigval = SIGSTOP; 71091.103Skamil pid_t child, child2 = 0, wpid; 71101.103Skamil#if defined(TWAIT_HAVE_STATUS) 71111.103Skamil int status; 71121.103Skamil#endif 71131.103Skamil ptrace_state_t state; 71141.103Skamil const int slen = sizeof(state); 71151.103Skamil ptrace_event_t event; 71161.103Skamil const int elen = sizeof(event); 71171.103Skamil struct sigaction sa; 71181.103Skamil struct ptrace_siginfo info; 71191.103Skamil sigset_t intmask; 71201.103Skamil struct kinfo_proc2 kp; 71211.103Skamil size_t len = sizeof(kp); 71221.103Skamil 71231.103Skamil int name[6]; 71241.103Skamil const size_t namelen = __arraycount(name); 71251.103Skamil ki_sigset_t kp_sigmask; 71261.103Skamil ki_sigset_t kp_sigignore; 71271.103Skamil 71281.103Skamil const size_t stack_size = 1024 * 1024; 71291.103Skamil void *stack, *stack_base; 71301.103Skamil 71311.103Skamil stack = malloc(stack_size); 71321.103Skamil ATF_REQUIRE(stack != NULL); 71331.103Skamil 71341.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 71351.103Skamil stack_base = stack; 71361.103Skamil#else 71371.103Skamil stack_base = (char *)stack + stack_size; 71381.103Skamil#endif 71391.103Skamil 71401.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 71411.103Skamil if (child == 0) { 71421.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 71431.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 71441.103Skamil 71451.103Skamil if (masked) { 71461.103Skamil sigemptyset(&intmask); 71471.103Skamil sigaddset(&intmask, SIGTRAP); 71481.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 71491.103Skamil } 71501.103Skamil 71511.103Skamil if (ignored) { 71521.103Skamil memset(&sa, 0, sizeof(sa)); 71531.103Skamil sa.sa_handler = SIG_IGN; 71541.103Skamil sigemptyset(&sa.sa_mask); 71551.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 71561.103Skamil } 71571.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 71581.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 71591.103Skamil 71601.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 71611.103Skamil flags); 71621.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 71631.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 71641.103Skamil 71651.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 71661.103Skamil child2); 71671.103Skamil 71681.103Skamil // XXX WALLSIG? 71691.103Skamil FORKEE_REQUIRE_SUCCESS 71701.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 71711.103Skamil 71721.103Skamil forkee_status_exited(status, exitval2); 71731.103Skamil 71741.103Skamil DPRINTF("Before exiting of the child process\n"); 71751.103Skamil _exit(exitval); 71761.103Skamil } 71771.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 71781.103Skamil 71791.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 71801.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71811.103Skamil 71821.103Skamil validate_status_stopped(status, sigval); 71831.103Skamil 71841.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 71851.103Skamil SYSCALL_REQUIRE( 71861.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71871.103Skamil 71881.103Skamil DPRINTF("Before checking siginfo_t\n"); 71891.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 71901.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71911.103Skamil 71921.103Skamil name[0] = CTL_KERN, 71931.103Skamil name[1] = KERN_PROC2, 71941.103Skamil name[2] = KERN_PROC_PID; 71951.103Skamil name[3] = child; 71961.103Skamil name[4] = sizeof(kp); 71971.103Skamil name[5] = 1; 71981.103Skamil 71991.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72001.103Skamil 72011.103Skamil if (masked) 72021.103Skamil kp_sigmask = kp.p_sigmask; 72031.103Skamil 72041.103Skamil if (ignored) 72051.103Skamil kp_sigignore = kp.p_sigignore; 72061.103Skamil 72071.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 72081.103Skamil "EVENT_MASK for the child %d\n", child); 72091.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 72101.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 72111.103Skamil 72121.103Skamil DPRINTF("Before resuming the child process where it left off and " 72131.103Skamil "without signal to be sent\n"); 72141.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72151.103Skamil 72161.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72171.103Skamil child); 72181.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 72191.103Skamil child); 72201.103Skamil 72211.103Skamil validate_status_stopped(status, SIGTRAP); 72221.103Skamil 72231.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72241.103Skamil 72251.103Skamil if (masked) { 72261.103Skamil DPRINTF("kp_sigmask=" 72271.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72281.103Skamil PRIx32 "\n", 72291.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72301.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72311.103Skamil 72321.103Skamil DPRINTF("kp.p_sigmask=" 72331.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72341.103Skamil PRIx32 "\n", 72351.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72361.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72371.103Skamil 72381.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72391.103Skamil sizeof(kp_sigmask))); 72401.103Skamil } 72411.103Skamil 72421.103Skamil if (ignored) { 72431.103Skamil DPRINTF("kp_sigignore=" 72441.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72451.103Skamil PRIx32 "\n", 72461.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72471.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72481.103Skamil 72491.103Skamil DPRINTF("kp.p_sigignore=" 72501.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72511.103Skamil PRIx32 "\n", 72521.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72531.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72541.103Skamil 72551.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72561.103Skamil sizeof(kp_sigignore))); 72571.103Skamil } 72581.103Skamil 72591.103Skamil SYSCALL_REQUIRE( 72601.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 72611.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 72621.103Skamil child2); 72631.103Skamil if (!(flags & CLONE_VFORK)) { 72641.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72651.103Skamil PTRACE_FORK); 72661.103Skamil } else { 72671.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72681.103Skamil PTRACE_VFORK); 72691.103Skamil } 72701.103Skamil 72711.103Skamil child2 = state.pe_other_pid; 72721.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 72731.103Skamil 72741.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 72751.103Skamil "%d\n", TWAIT_FNAME, child2, child); 72761.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 72771.103Skamil child2); 72781.103Skamil 72791.103Skamil validate_status_stopped(status, SIGTRAP); 72801.103Skamil 72811.103Skamil name[3] = child2; 72821.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72831.103Skamil 72841.103Skamil if (masked) { 72851.103Skamil DPRINTF("kp_sigmask=" 72861.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72871.103Skamil PRIx32 "\n", 72881.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72891.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72901.103Skamil 72911.103Skamil DPRINTF("kp.p_sigmask=" 72921.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72931.103Skamil PRIx32 "\n", 72941.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72951.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72961.103Skamil 72971.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72981.103Skamil sizeof(kp_sigmask))); 72991.103Skamil } 73001.103Skamil 73011.103Skamil if (ignored) { 73021.103Skamil DPRINTF("kp_sigignore=" 73031.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73041.103Skamil PRIx32 "\n", 73051.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73061.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73071.103Skamil 73081.103Skamil DPRINTF("kp.p_sigignore=" 73091.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73101.103Skamil PRIx32 "\n", 73111.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73121.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73131.103Skamil 73141.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73151.103Skamil sizeof(kp_sigignore))); 73161.103Skamil } 73171.103Skamil 73181.103Skamil SYSCALL_REQUIRE( 73191.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 73201.103Skamil if (!(flags & CLONE_VFORK)) { 73211.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 73221.103Skamil PTRACE_FORK); 73231.103Skamil } else { 73241.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 73251.103Skamil PTRACE_VFORK); 73261.103Skamil } 73271.103Skamil 73281.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 73291.103Skamil 73301.103Skamil DPRINTF("Before resuming the forkee process where it left off " 73311.103Skamil "and without signal to be sent\n"); 73321.103Skamil SYSCALL_REQUIRE( 73331.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 73341.103Skamil 73351.103Skamil DPRINTF("Before resuming the child process where it left off " 73361.103Skamil "and without signal to be sent\n"); 73371.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73381.103Skamil 73391.103Skamil if (flags & CLONE_VFORK) { 73401.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 73411.103Skamil child); 73421.103Skamil TWAIT_REQUIRE_SUCCESS( 73431.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 73441.103Skamil 73451.103Skamil validate_status_stopped(status, SIGTRAP); 73461.103Skamil 73471.103Skamil name[3] = child; 73481.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 73491.103Skamil 73501.103Skamil /* 73511.103Skamil * SIGCHLD is now pending in the signal queue and 73521.103Skamil * the kernel presents it to userland as a masked signal. 73531.103Skamil */ 73541.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 73551.103Skamil 73561.103Skamil if (masked) { 73571.103Skamil DPRINTF("kp_sigmask=" 73581.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73591.103Skamil PRIx32 "\n", 73601.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 73611.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 73621.103Skamil 73631.103Skamil DPRINTF("kp.p_sigmask=" 73641.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73651.103Skamil PRIx32 "\n", 73661.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 73671.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 73681.103Skamil 73691.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 73701.103Skamil sizeof(kp_sigmask))); 73711.103Skamil } 73721.103Skamil 73731.103Skamil if (ignored) { 73741.103Skamil DPRINTF("kp_sigignore=" 73751.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73761.103Skamil PRIx32 "\n", 73771.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73781.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73791.103Skamil 73801.103Skamil DPRINTF("kp.p_sigignore=" 73811.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73821.103Skamil PRIx32 "\n", 73831.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73841.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73851.103Skamil 73861.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73871.103Skamil sizeof(kp_sigignore))); 73881.103Skamil } 73891.103Skamil 73901.103Skamil SYSCALL_REQUIRE( 73911.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 73921.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 73931.103Skamil 73941.103Skamil child2 = state.pe_other_pid; 73951.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 73961.103Skamil child2); 73971.103Skamil 73981.103Skamil DPRINTF("Before resuming the child process where it left off " 73991.103Skamil "and without signal to be sent\n"); 74001.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74011.103Skamil } 74021.103Skamil 74031.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 74041.103Skamil "\n", TWAIT_FNAME); 74051.103Skamil TWAIT_REQUIRE_SUCCESS( 74061.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 74071.103Skamil 74081.103Skamil validate_status_exited(status, exitval2); 74091.103Skamil 74101.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 74111.103Skamil "process\n", TWAIT_FNAME); 74121.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 74131.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 74141.103Skamil 74151.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 74161.103Skamil "SIGCHLD\n", TWAIT_FNAME); 74171.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74181.103Skamil 74191.103Skamil validate_status_stopped(status, SIGCHLD); 74201.103Skamil 74211.103Skamil DPRINTF("Before resuming the child process where it left off and " 74221.103Skamil "without signal to be sent\n"); 74231.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74241.103Skamil 74251.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74261.103Skamil TWAIT_FNAME); 74271.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74281.103Skamil 74291.103Skamil validate_status_exited(status, exitval); 74301.103Skamil 74311.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74321.103Skamil TWAIT_FNAME); 74331.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74341.103Skamil} 74351.103Skamil 74361.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 74371.103SkamilATF_TC(name); \ 74381.103SkamilATF_TC_HEAD(name, tc) \ 74391.103Skamil{ \ 74401.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 74411.103Skamil " regardless of signal %s%s", \ 74421.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 74431.103Skamil} \ 74441.103Skamil \ 74451.103SkamilATF_TC_BODY(name, tc) \ 74461.103Skamil{ \ 74471.103Skamil \ 74481.106Skamil clone_body2(flags, masked, ignored); \ 74491.103Skamil} 74501.103Skamil 74511.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 74521.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 74531.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 74541.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 74551.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 74561.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 74571.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 74581.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 74591.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 74601.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 74611.110Skamil#if TEST_VFORK_ENABLED 74621.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 74631.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 74641.103Skamil#endif 74651.110Skamil#endif 74661.103Skamil 74671.103Skamil/// ---------------------------------------------------------------------------- 74681.103Skamil 74691.111Skamil#if TEST_VFORK_ENABLED 74701.107Skamil#if defined(TWAIT_HAVE_PID) 74711.107Skamilstatic void 74721.107Skamiltraceme_vfork_clone_body(int flags) 74731.107Skamil{ 74741.107Skamil const int exitval = 5; 74751.107Skamil const int exitval2 = 15; 74761.107Skamil pid_t child, child2 = 0, wpid; 74771.107Skamil#if defined(TWAIT_HAVE_STATUS) 74781.107Skamil int status; 74791.107Skamil#endif 74801.107Skamil 74811.107Skamil const size_t stack_size = 1024 * 1024; 74821.107Skamil void *stack, *stack_base; 74831.107Skamil 74841.107Skamil stack = malloc(stack_size); 74851.107Skamil ATF_REQUIRE(stack != NULL); 74861.107Skamil 74871.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 74881.107Skamil stack_base = stack; 74891.107Skamil#else 74901.107Skamil stack_base = (char *)stack + stack_size; 74911.107Skamil#endif 74921.107Skamil 74931.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 74941.107Skamil if (child == 0) { 74951.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74961.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74971.107Skamil 74981.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 74991.107Skamil flags); 75001.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 75011.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 75021.107Skamil 75031.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 75041.107Skamil child2); 75051.107Skamil 75061.107Skamil // XXX WALLSIG? 75071.107Skamil FORKEE_REQUIRE_SUCCESS 75081.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 75091.107Skamil 75101.107Skamil forkee_status_exited(status, exitval2); 75111.107Skamil 75121.107Skamil DPRINTF("Before exiting of the child process\n"); 75131.107Skamil _exit(exitval); 75141.107Skamil } 75151.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75161.107Skamil 75171.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 75181.107Skamil TWAIT_FNAME); 75191.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75201.107Skamil 75211.107Skamil validate_status_exited(status, exitval); 75221.107Skamil 75231.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 75241.107Skamil TWAIT_FNAME); 75251.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75261.107Skamil} 75271.107Skamil 75281.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 75291.107SkamilATF_TC(name); \ 75301.107SkamilATF_TC_HEAD(name, tc) \ 75311.107Skamil{ \ 75321.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 75331.107Skamil "handled correctly with vfork(2)ed tracer", \ 75341.107Skamil #flags); \ 75351.107Skamil} \ 75361.107Skamil \ 75371.107SkamilATF_TC_BODY(name, tc) \ 75381.107Skamil{ \ 75391.107Skamil \ 75401.107Skamil traceme_vfork_clone_body(flags); \ 75411.107Skamil} 75421.107Skamil 75431.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 75441.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 75451.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 75461.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 75471.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 75481.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 75491.107Skamil#endif 75501.110Skamil#endif 75511.107Skamil 75521.107Skamil/// ---------------------------------------------------------------------------- 75531.107Skamil 75541.122Skamilstatic void 75551.122Skamiluser_va0_disable(int operation) 75561.122Skamil{ 75571.122Skamil pid_t child, wpid; 75581.122Skamil#if defined(TWAIT_HAVE_STATUS) 75591.122Skamil int status; 75601.122Skamil#endif 75611.122Skamil const int sigval = SIGSTOP; 75621.122Skamil int rv; 75631.122Skamil 75641.122Skamil struct ptrace_siginfo info; 75651.122Skamil 75661.122Skamil if (get_user_va0_disable() == 0) 75671.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 75681.122Skamil 75691.122Skamil memset(&info, 0, sizeof(info)); 75701.122Skamil 75711.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 75721.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 75731.122Skamil if (child == 0) { 75741.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 75751.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 75761.122Skamil 75771.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 75781.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 75791.122Skamil 75801.122Skamil /* NOTREACHED */ 75811.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 75821.122Skamil __unreachable(); 75831.122Skamil } 75841.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75851.122Skamil 75861.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75871.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75881.122Skamil 75891.122Skamil validate_status_stopped(status, sigval); 75901.122Skamil 75911.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 75921.122Skamil "child\n"); 75931.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 75941.122Skamil sizeof(info)) != -1); 75951.122Skamil 75961.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 75971.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 75981.122Skamil "si_errno=%#x\n", 75991.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 76001.122Skamil info.psi_siginfo.si_errno); 76011.122Skamil 76021.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 76031.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 76041.122Skamil 76051.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 76061.122Skamil "and without signal to be sent\n"); 76071.122Skamil errno = 0; 76081.122Skamil rv = ptrace(operation, child, (void *)0, 0); 76091.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 76101.122Skamil ATF_REQUIRE_EQ(rv, -1); 76111.122Skamil 76121.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 76131.122Skamil 76141.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76151.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76161.122Skamil validate_status_signaled(status, SIGKILL, 0); 76171.122Skamil 76181.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76191.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76201.122Skamil} 76211.122Skamil 76221.122Skamil#define USER_VA0_DISABLE(test, operation) \ 76231.122SkamilATF_TC(test); \ 76241.122SkamilATF_TC_HEAD(test, tc) \ 76251.122Skamil{ \ 76261.122Skamil atf_tc_set_md_var(tc, "descr", \ 76271.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 76281.122Skamil} \ 76291.122Skamil \ 76301.122SkamilATF_TC_BODY(test, tc) \ 76311.122Skamil{ \ 76321.122Skamil \ 76331.122Skamil user_va0_disable(operation); \ 76341.122Skamil} 76351.122Skamil 76361.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 76371.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 76381.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 76391.122Skamil 76401.122Skamil/// ---------------------------------------------------------------------------- 76411.122Skamil 76421.1Skamil#include "t_ptrace_amd64_wait.h" 76431.1Skamil#include "t_ptrace_i386_wait.h" 76441.1Skamil#include "t_ptrace_x86_wait.h" 76451.1Skamil 76461.1SkamilATF_TP_ADD_TCS(tp) 76471.1Skamil{ 76481.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 76491.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 76501.33Skamil 76511.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 76521.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 76531.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 76541.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 76551.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 76561.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 76571.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 76581.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 76591.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 76601.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 76611.33Skamil 76621.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 76631.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 76641.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 76651.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 76661.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 76671.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 76681.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 76691.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 76701.87Skamil 76711.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 76721.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 76731.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 76741.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 76751.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 76761.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 76771.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 76781.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 76791.86Skamil 76801.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 76811.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 76821.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 76831.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 76841.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 76851.59Skamil 76861.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 76871.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 76881.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 76891.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 76901.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 76911.88Skamil 76921.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 76931.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 76941.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 76951.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 76961.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 76971.88Skamil 76981.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 76991.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 77001.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 77011.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 77021.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 77031.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 77041.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 77051.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 77061.50Skamil 77071.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 77081.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 77091.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 77101.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 77111.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 77121.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 77131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 77141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 77151.50Skamil 77161.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 77171.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 77181.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 77191.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 77201.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 77211.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 77221.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 77231.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 77241.50Skamil 77251.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 77261.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 77271.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 77281.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 77291.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 77301.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 77311.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 77321.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 77331.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 77341.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 77351.1Skamil 77361.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 77371.37Skamil 77381.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 77391.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 77401.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 77411.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 77421.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 77431.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 77441.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 77451.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 77461.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 77471.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 77481.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 77491.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 77501.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 77511.40Skamil 77521.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 77531.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 77541.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 77551.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 77561.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 77571.41Skamil 77581.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 77591.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 77601.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 77611.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 77621.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 77631.92Skamil 77641.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 77651.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 77661.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 77671.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 77681.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 77691.92Skamil 77701.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 77711.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 77721.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 77731.43Skamil 77741.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 77751.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 77761.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 77771.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 77781.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 77791.59Skamil 77801.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77811.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 77821.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77831.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 77841.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77851.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 77861.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77871.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 77881.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77891.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 77901.94Skamil 77911.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77921.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 77931.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77941.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 77951.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77961.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 77971.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77981.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 77991.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78001.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 78011.94Skamil 78021.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 78031.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 78041.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 78051.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 78061.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 78071.51Skamil 78081.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 78091.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 78101.51Skamil 78111.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 78121.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 78131.51Skamil 78141.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78151.51Skamil tracee_sees_its_original_parent_getppid); 78161.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78171.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 78181.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78191.51Skamil tracee_sees_its_original_parent_procfs_status); 78201.1Skamil 78211.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 78221.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 78231.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 78241.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 78251.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 78261.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 78271.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 78281.1Skamil 78291.31Skamil ATF_TP_ADD_TC(tp, fork1); 78301.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 78311.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 78321.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 78331.31Skamil ATF_TP_ADD_TC(tp, fork5); 78341.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 78351.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 78361.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 78371.125Skamil ATF_TP_ADD_TC(tp, fork9); 78381.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 78391.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 78401.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 78411.125Skamil ATF_TP_ADD_TC(tp, fork13); 78421.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 78431.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 78441.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 78451.31Skamil 78461.109Skamil#if TEST_VFORK_ENABLED 78471.31Skamil ATF_TP_ADD_TC(tp, vfork1); 78481.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 78491.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 78501.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 78511.31Skamil ATF_TP_ADD_TC(tp, vfork5); 78521.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 78531.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 78541.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 78551.125Skamil ATF_TP_ADD_TC(tp, vfork9); 78561.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 78571.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 78581.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 78591.125Skamil ATF_TP_ADD_TC(tp, vfork13); 78601.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 78611.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 78621.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 78631.116Skamil#endif 78641.1Skamil 78651.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 78661.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 78671.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 78681.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 78691.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 78701.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 78711.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 78721.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 78731.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 78741.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 78751.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 78761.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 78771.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 78781.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 78791.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 78801.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 78811.124Skamil 78821.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 78831.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 78841.116Skamil#if TEST_VFORK_ENABLED 78851.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 78861.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 78871.116Skamil#endif 78881.126Skamil 78891.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 78901.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 78911.116Skamil#if TEST_VFORK_ENABLED 78921.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 78931.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 78941.116Skamil#endif 78951.116Skamil 78961.116Skamil#if TEST_VFORK_ENABLED 78971.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 78981.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 78991.109Skamil#endif 79001.108Skamil 79011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 79021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 79031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 79041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 79051.54Skamil 79061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 79071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 79081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 79091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 79101.54Skamil 79111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 79121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 79131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 79141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 79151.54Skamil 79161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 79171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 79181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 79191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 79201.54Skamil 79211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 79221.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 79231.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 79241.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 79251.54Skamil 79261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 79271.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 79281.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 79291.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 79301.54Skamil 79311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 79321.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 79331.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 79341.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 79351.54Skamil 79361.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 79371.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 79381.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 79391.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 79401.54Skamil 79411.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 79421.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 79431.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 79441.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 79451.54Skamil 79461.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 79471.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 79481.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 79491.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 79501.1Skamil 79511.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 79521.1Skamil 79531.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 79541.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 79551.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 79561.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 79571.101Skamil 79581.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 79591.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 79601.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 79611.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 79621.101Skamil 79631.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 79641.101Skamil 79651.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 79661.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 79671.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 79681.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 79691.115Skamil 79701.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 79711.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 79721.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 79731.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 79741.115Skamil 79751.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 79761.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 79771.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 79781.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 79791.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 79801.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 79811.1Skamil 79821.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 79831.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 79841.1Skamil 79851.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 79861.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 79871.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 79881.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 79891.1Skamil 79901.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 79911.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 79921.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 79931.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 79941.2Skamil 79951.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 79961.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 79971.95Skamil 79981.1Skamil ATF_TP_ADD_TC(tp, kill1); 79991.1Skamil ATF_TP_ADD_TC(tp, kill2); 80001.75Skamil ATF_TP_ADD_TC(tp, kill3); 80011.1Skamil 80021.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 80031.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 80041.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 80051.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 80061.77Skamil 80071.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 80081.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 80091.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 80101.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 80111.1Skamil 80121.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 80131.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 80141.79Skamil 80151.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 80161.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 80171.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 80181.1Skamil 80191.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 80201.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 80211.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 80221.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 80231.1Skamil 80241.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 80251.84Skamil 80261.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 80271.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 80281.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 80291.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 80301.109Skamil#if TEST_VFORK_ENABLED 80311.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 80321.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 80331.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 80341.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 80351.109Skamil#endif 80361.99Skamil 80371.1Skamil ATF_TP_ADD_TC(tp, signal9); 80381.1Skamil ATF_TP_ADD_TC(tp, signal10); 80391.1Skamil 80401.1Skamil ATF_TP_ADD_TC(tp, suspend1); 80411.1Skamil ATF_TP_ADD_TC(tp, suspend2); 80421.1Skamil 80431.1Skamil ATF_TP_ADD_TC(tp, resume1); 80441.1Skamil 80451.1Skamil ATF_TP_ADD_TC(tp, syscall1); 80461.1Skamil 80471.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 80481.1Skamil 80491.106Skamil ATF_TP_ADD_TC(tp, clone1); 80501.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 80511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 80521.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 80531.106Skamil ATF_TP_ADD_TC(tp, clone5); 80541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 80551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 80561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 80571.106Skamil 80581.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 80591.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 80601.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 80611.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 80621.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 80631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 80641.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 80651.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 80661.106Skamil 80671.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 80681.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 80691.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 80701.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 80711.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 80721.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 80731.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 80741.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 80751.106Skamil 80761.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 80771.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 80781.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 80791.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 80801.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 80811.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 80821.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 80831.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 80841.106Skamil 80851.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 80861.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 80871.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 80881.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 80891.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 80901.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 80911.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 80921.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 80931.106Skamil 80941.109Skamil#if TEST_VFORK_ENABLED 80951.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 80961.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 80971.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 80981.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 80991.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 81001.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 81011.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 81021.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 81031.109Skamil#endif 81041.106Skamil 81051.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 81061.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 81071.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 81081.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 81091.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 81101.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 81111.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 81121.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 81131.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 81141.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 81151.109Skamil#if TEST_VFORK_ENABLED 81161.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 81171.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 81181.109Skamil#endif 81191.103Skamil 81201.109Skamil#if TEST_VFORK_ENABLED 81211.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 81221.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 81231.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 81241.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 81251.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 81261.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 81271.109Skamil#endif 81281.107Skamil 81291.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 81301.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 81311.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 81321.122Skamil 81331.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 81341.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 81351.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 81361.1Skamil 81371.1Skamil return atf_no_error(); 81381.1Skamil} 8139